reader/wgsl: Tail-call optimize expression methods

Fixes stack overflows in complex arithmetic expressions

Fixed: chromium:1182709
Change-Id: I5f5470cf59525725a437f26672904e9653b447a7
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/43940
Reviewed-by: David Neto <dneto@google.com>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2021-03-04 22:52:05 +00:00 committed by Commit Bot service account
parent d1781fd0af
commit dee7d36f8a
1 changed files with 187 additions and 161 deletions

View File

@ -2256,6 +2256,7 @@ Maybe<ast::Expression*> ParserImpl::unary_expression() {
// | MODULO unary_expression multiplicative_expr // | MODULO unary_expression multiplicative_expr
Expect<ast::Expression*> ParserImpl::expect_multiplicative_expr( Expect<ast::Expression*> ParserImpl::expect_multiplicative_expr(
ast::Expression* lhs) { ast::Expression* lhs) {
while (synchronized_) {
auto t = peek(); auto t = peek();
ast::BinaryOp op = ast::BinaryOp::kNone; ast::BinaryOp op = ast::BinaryOp::kNone;
@ -2280,8 +2281,9 @@ Expect<ast::Expression*> ParserImpl::expect_multiplicative_expr(
"unable to parse right side of " + name + " expression"); "unable to parse right side of " + name + " expression");
} }
return expect_multiplicative_expr( lhs = create<ast::BinaryExpression>(source, op, lhs, rhs.value);
create<ast::BinaryExpression>(source, op, lhs, rhs.value)); }
return Failure::kErrored;
} }
// multiplicative_expression // multiplicative_expression
@ -2302,6 +2304,7 @@ Maybe<ast::Expression*> ParserImpl::multiplicative_expression() {
// | MINUS multiplicative_expression additive_expr // | MINUS multiplicative_expression additive_expr
Expect<ast::Expression*> ParserImpl::expect_additive_expr( Expect<ast::Expression*> ParserImpl::expect_additive_expr(
ast::Expression* lhs) { ast::Expression* lhs) {
while (synchronized_) {
auto t = peek(); auto t = peek();
ast::BinaryOp op = ast::BinaryOp::kNone; ast::BinaryOp op = ast::BinaryOp::kNone;
@ -2321,8 +2324,9 @@ Expect<ast::Expression*> ParserImpl::expect_additive_expr(
if (!rhs.matched) if (!rhs.matched)
return add_error(peek(), "unable to parse right side of + expression"); return add_error(peek(), "unable to parse right side of + expression");
return expect_additive_expr( lhs = create<ast::BinaryExpression>(source, op, lhs, rhs.value);
create<ast::BinaryExpression>(source, op, lhs, rhs.value)); }
return Failure::kErrored;
} }
// additive_expression // additive_expression
@ -2342,6 +2346,7 @@ Maybe<ast::Expression*> ParserImpl::additive_expression() {
// | SHIFT_LEFT additive_expression shift_expr // | SHIFT_LEFT additive_expression shift_expr
// | SHIFT_RIGHT additive_expression shift_expr // | SHIFT_RIGHT additive_expression shift_expr
Expect<ast::Expression*> ParserImpl::expect_shift_expr(ast::Expression* lhs) { Expect<ast::Expression*> ParserImpl::expect_shift_expr(ast::Expression* lhs) {
while (synchronized_) {
auto t = peek(); auto t = peek();
auto source = t.source(); auto source = t.source();
@ -2366,9 +2371,11 @@ Expect<ast::Expression*> ParserImpl::expect_shift_expr(ast::Expression* lhs) {
return add_error(peek(), std::string("unable to parse right side of ") + return add_error(peek(), std::string("unable to parse right side of ") +
name + " expression"); name + " expression");
} }
return expect_shift_expr(
create<ast::BinaryExpression>(source, op, lhs, rhs.value)); return lhs = create<ast::BinaryExpression>(source, op, lhs, rhs.value);
} // namespace wgsl }
return Failure::kErrored;
}
// shift_expression // shift_expression
// : additive_expression shift_expr // : additive_expression shift_expr
@ -2390,6 +2397,7 @@ Maybe<ast::Expression*> ParserImpl::shift_expression() {
// | GREATER_THAN_EQUAL shift_expression relational_expr // | GREATER_THAN_EQUAL shift_expression relational_expr
Expect<ast::Expression*> ParserImpl::expect_relational_expr( Expect<ast::Expression*> ParserImpl::expect_relational_expr(
ast::Expression* lhs) { ast::Expression* lhs) {
while (synchronized_) {
auto t = peek(); auto t = peek();
ast::BinaryOp op = ast::BinaryOp::kNone; ast::BinaryOp op = ast::BinaryOp::kNone;
if (t.IsLessThan()) if (t.IsLessThan())
@ -2415,8 +2423,9 @@ Expect<ast::Expression*> ParserImpl::expect_relational_expr(
"unable to parse right side of " + name + " expression"); "unable to parse right side of " + name + " expression");
} }
return expect_relational_expr( lhs = create<ast::BinaryExpression>(source, op, lhs, rhs.value);
create<ast::BinaryExpression>(source, op, lhs, rhs.value)); }
return Failure::kErrored;
} }
// relational_expression // relational_expression
@ -2437,6 +2446,7 @@ Maybe<ast::Expression*> ParserImpl::relational_expression() {
// | NOT_EQUAL relational_expression equality_expr // | NOT_EQUAL relational_expression equality_expr
Expect<ast::Expression*> ParserImpl::expect_equality_expr( Expect<ast::Expression*> ParserImpl::expect_equality_expr(
ast::Expression* lhs) { ast::Expression* lhs) {
while (synchronized_) {
auto t = peek(); auto t = peek();
ast::BinaryOp op = ast::BinaryOp::kNone; ast::BinaryOp op = ast::BinaryOp::kNone;
if (t.IsEqualEqual()) if (t.IsEqualEqual())
@ -2458,8 +2468,9 @@ Expect<ast::Expression*> ParserImpl::expect_equality_expr(
"unable to parse right side of " + name + " expression"); "unable to parse right side of " + name + " expression");
} }
return expect_equality_expr( lhs = create<ast::BinaryExpression>(source, op, lhs, rhs.value);
create<ast::BinaryExpression>(source, op, lhs, rhs.value)); }
return Failure::kErrored;
} }
// equality_expression // equality_expression
@ -2478,6 +2489,7 @@ Maybe<ast::Expression*> ParserImpl::equality_expression() {
// : // :
// | AND equality_expression and_expr // | AND equality_expression and_expr
Expect<ast::Expression*> ParserImpl::expect_and_expr(ast::Expression* lhs) { Expect<ast::Expression*> ParserImpl::expect_and_expr(ast::Expression* lhs) {
while (synchronized_) {
auto t = peek(); auto t = peek();
if (!t.IsAnd()) if (!t.IsAnd())
return lhs; return lhs;
@ -2491,8 +2503,10 @@ Expect<ast::Expression*> ParserImpl::expect_and_expr(ast::Expression* lhs) {
if (!rhs.matched) if (!rhs.matched)
return add_error(peek(), "unable to parse right side of & expression"); return add_error(peek(), "unable to parse right side of & expression");
return expect_and_expr(create<ast::BinaryExpression>( lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kAnd, lhs,
source, ast::BinaryOp::kAnd, lhs, rhs.value)); rhs.value);
}
return Failure::kErrored;
} }
// and_expression // and_expression
@ -2512,6 +2526,7 @@ Maybe<ast::Expression*> ParserImpl::and_expression() {
// | XOR and_expression exclusive_or_expr // | XOR and_expression exclusive_or_expr
Expect<ast::Expression*> ParserImpl::expect_exclusive_or_expr( Expect<ast::Expression*> ParserImpl::expect_exclusive_or_expr(
ast::Expression* lhs) { ast::Expression* lhs) {
while (synchronized_) {
Source source; Source source;
if (!match(Token::Type::kXor, &source)) if (!match(Token::Type::kXor, &source))
return lhs; return lhs;
@ -2522,8 +2537,10 @@ Expect<ast::Expression*> ParserImpl::expect_exclusive_or_expr(
if (!rhs.matched) if (!rhs.matched)
return add_error(peek(), "unable to parse right side of ^ expression"); return add_error(peek(), "unable to parse right side of ^ expression");
return expect_exclusive_or_expr(create<ast::BinaryExpression>( lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kXor, lhs,
source, ast::BinaryOp::kXor, lhs, rhs.value)); rhs.value);
}
return Failure::kErrored;
} }
// exclusive_or_expression // exclusive_or_expression
@ -2543,6 +2560,7 @@ Maybe<ast::Expression*> ParserImpl::exclusive_or_expression() {
// | OR exclusive_or_expression inclusive_or_expr // | OR exclusive_or_expression inclusive_or_expr
Expect<ast::Expression*> ParserImpl::expect_inclusive_or_expr( Expect<ast::Expression*> ParserImpl::expect_inclusive_or_expr(
ast::Expression* lhs) { ast::Expression* lhs) {
while (synchronized_) {
Source source; Source source;
if (!match(Token::Type::kOr)) if (!match(Token::Type::kOr))
return lhs; return lhs;
@ -2553,8 +2571,10 @@ Expect<ast::Expression*> ParserImpl::expect_inclusive_or_expr(
if (!rhs.matched) if (!rhs.matched)
return add_error(peek(), "unable to parse right side of | expression"); return add_error(peek(), "unable to parse right side of | expression");
return expect_inclusive_or_expr(create<ast::BinaryExpression>( lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kOr, lhs,
source, ast::BinaryOp::kOr, lhs, rhs.value)); rhs.value);
}
return Failure::kErrored;
} }
// inclusive_or_expression // inclusive_or_expression
@ -2574,6 +2594,7 @@ Maybe<ast::Expression*> ParserImpl::inclusive_or_expression() {
// | AND_AND inclusive_or_expression logical_and_expr // | AND_AND inclusive_or_expression logical_and_expr
Expect<ast::Expression*> ParserImpl::expect_logical_and_expr( Expect<ast::Expression*> ParserImpl::expect_logical_and_expr(
ast::Expression* lhs) { ast::Expression* lhs) {
while (synchronized_) {
auto t = peek(); auto t = peek();
if (!t.IsAndAnd()) if (!t.IsAndAnd())
return lhs; return lhs;
@ -2587,8 +2608,10 @@ Expect<ast::Expression*> ParserImpl::expect_logical_and_expr(
if (!rhs.matched) if (!rhs.matched)
return add_error(peek(), "unable to parse right side of && expression"); return add_error(peek(), "unable to parse right side of && expression");
return expect_logical_and_expr(create<ast::BinaryExpression>( lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalAnd, lhs,
source, ast::BinaryOp::kLogicalAnd, lhs, rhs.value)); rhs.value);
}
return Failure::kErrored;
} }
// logical_and_expression // logical_and_expression
@ -2608,6 +2631,7 @@ Maybe<ast::Expression*> ParserImpl::logical_and_expression() {
// | OR_OR logical_and_expression logical_or_expr // | OR_OR logical_and_expression logical_or_expr
Expect<ast::Expression*> ParserImpl::expect_logical_or_expr( Expect<ast::Expression*> ParserImpl::expect_logical_or_expr(
ast::Expression* lhs) { ast::Expression* lhs) {
while (synchronized_) {
Source source; Source source;
if (!match(Token::Type::kOrOr)) if (!match(Token::Type::kOrOr))
return lhs; return lhs;
@ -2618,8 +2642,10 @@ Expect<ast::Expression*> ParserImpl::expect_logical_or_expr(
if (!rhs.matched) if (!rhs.matched)
return add_error(peek(), "unable to parse right side of || expression"); return add_error(peek(), "unable to parse right side of || expression");
return expect_logical_or_expr(create<ast::BinaryExpression>( lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalOr, lhs,
source, ast::BinaryOp::kLogicalOr, lhs, rhs.value)); rhs.value);
}
return Failure::kErrored;
} }
// logical_or_expression // logical_or_expression