mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-12 06:45:16 +00:00
Store expressions in switch case statements.
This CL moves switch case statements to store Expression instead of an IntLiteralExpression. The SEM is updated to store the materialized constant instead of accessing the expression value directly. Bug: tint:1633 Change-Id: Id79dabb806be1049f775299732bc1c7b1bf0c05f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/106300 Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Reviewed-by: Ben Clayton <bclayton@google.com> Auto-Submit: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
00aa7ef462
commit
d32fbe07e7
@@ -3024,7 +3024,7 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
|
||||
for (size_t i = last_clause_index;; --i) {
|
||||
// Create a list of integer literals for the selector values leading to
|
||||
// this case clause.
|
||||
utils::Vector<const ast::IntLiteralExpression*, 4> selectors;
|
||||
utils::Vector<const ast::Expression*, 4> selectors;
|
||||
const bool has_selectors = clause_heads[i]->case_values.has_value();
|
||||
if (has_selectors) {
|
||||
auto values = clause_heads[i]->case_values.value();
|
||||
|
||||
@@ -2148,21 +2148,19 @@ Maybe<const ast::CaseStatement*> ParserImpl::switch_body() {
|
||||
}
|
||||
|
||||
// case_selectors
|
||||
// : const_literal (COMMA const_literal)* COMMA?
|
||||
// : expression (COMMA expression)* COMMA?
|
||||
Expect<ParserImpl::CaseSelectorList> ParserImpl::expect_case_selectors() {
|
||||
CaseSelectorList selectors;
|
||||
|
||||
while (continue_parsing()) {
|
||||
auto cond = const_literal();
|
||||
if (cond.errored) {
|
||||
auto expr = expression();
|
||||
if (expr.errored) {
|
||||
return Failure::kErrored;
|
||||
} else if (!cond.matched) {
|
||||
break;
|
||||
} else if (!cond->Is<ast::IntLiteralExpression>()) {
|
||||
return add_error(cond.value->source, "invalid case selector must be an integer value");
|
||||
}
|
||||
|
||||
selectors.Push(cond.value->As<ast::IntLiteralExpression>());
|
||||
if (!expr.matched) {
|
||||
break;
|
||||
}
|
||||
selectors.Push(expr.value);
|
||||
|
||||
if (!match(Token::Type::kComma)) {
|
||||
break;
|
||||
|
||||
@@ -74,7 +74,7 @@ class ParserImpl {
|
||||
/// Pre-determined small vector sizes for AST pointers
|
||||
//! @cond Doxygen_Suppress
|
||||
using AttributeList = utils::Vector<const ast::Attribute*, 4>;
|
||||
using CaseSelectorList = utils::Vector<const ast::IntLiteralExpression*, 4>;
|
||||
using CaseSelectorList = utils::Vector<const ast::Expression*, 4>;
|
||||
using CaseStatementList = utils::Vector<const ast::CaseStatement*, 4>;
|
||||
using ExpressionList = utils::Vector<const ast::Expression*, 8>;
|
||||
using ParameterList = utils::Vector<const ast::Parameter*, 8>;
|
||||
|
||||
@@ -1339,14 +1339,6 @@ fn f() { switch(1) { case ^: } }
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, SwitchStmtInvalidCase2) {
|
||||
EXPECT("fn f() { switch(1) { case false: } }",
|
||||
R"(test.wgsl:1:27 error: invalid case selector must be an integer value
|
||||
fn f() { switch(1) { case false: } }
|
||||
^^^^^
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, SwitchStmtCaseMissingLBrace) {
|
||||
EXPECT("fn f() { switch(1) { case 1: } }",
|
||||
R"(test.wgsl:1:30 error: expected '{' for case statement
|
||||
|
||||
@@ -26,10 +26,42 @@ TEST_F(ParserImplTest, SwitchBody_Case) {
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
ASSERT_TRUE(e->Is<ast::CaseStatement>());
|
||||
EXPECT_FALSE(e->IsDefault());
|
||||
|
||||
auto* stmt = e->As<ast::CaseStatement>();
|
||||
ASSERT_EQ(stmt->selectors.Length(), 1u);
|
||||
EXPECT_EQ(stmt->selectors[0]->value, 1);
|
||||
EXPECT_EQ(stmt->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
ASSERT_TRUE(stmt->selectors[0]->Is<ast::IntLiteralExpression>());
|
||||
|
||||
auto* expr = stmt->selectors[0]->As<ast::IntLiteralExpression>();
|
||||
EXPECT_EQ(expr->value, 1);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
ASSERT_EQ(e->body->statements.Length(), 1u);
|
||||
EXPECT_TRUE(e->body->statements[0]->Is<ast::AssignmentStatement>());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_Expression) {
|
||||
auto p = parser("case 1 + 2 { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
EXPECT_TRUE(e.matched);
|
||||
EXPECT_FALSE(e.errored);
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
ASSERT_TRUE(e->Is<ast::CaseStatement>());
|
||||
EXPECT_FALSE(e->IsDefault());
|
||||
|
||||
auto* stmt = e->As<ast::CaseStatement>();
|
||||
ASSERT_EQ(stmt->selectors.Length(), 1u);
|
||||
ASSERT_TRUE(stmt->selectors[0]->Is<ast::BinaryExpression>());
|
||||
auto* expr = stmt->selectors[0]->As<ast::BinaryExpression>();
|
||||
|
||||
EXPECT_EQ(ast::BinaryOp::kAdd, expr->op);
|
||||
auto* v = expr->lhs->As<ast::IntLiteralExpression>();
|
||||
ASSERT_NE(nullptr, v);
|
||||
EXPECT_EQ(v->value, 1u);
|
||||
|
||||
v = expr->rhs->As<ast::IntLiteralExpression>();
|
||||
ASSERT_NE(nullptr, v);
|
||||
EXPECT_EQ(v->value, 2u);
|
||||
|
||||
ASSERT_EQ(e->body->statements.Length(), 1u);
|
||||
EXPECT_TRUE(e->body->statements[0]->Is<ast::AssignmentStatement>());
|
||||
}
|
||||
@@ -43,10 +75,14 @@ TEST_F(ParserImplTest, SwitchBody_Case_WithColon) {
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
ASSERT_TRUE(e->Is<ast::CaseStatement>());
|
||||
EXPECT_FALSE(e->IsDefault());
|
||||
|
||||
auto* stmt = e->As<ast::CaseStatement>();
|
||||
ASSERT_EQ(stmt->selectors.Length(), 1u);
|
||||
EXPECT_EQ(stmt->selectors[0]->value, 1);
|
||||
EXPECT_EQ(stmt->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
ASSERT_TRUE(stmt->selectors[0]->Is<ast::IntLiteralExpression>());
|
||||
|
||||
auto* expr = stmt->selectors[0]->As<ast::IntLiteralExpression>();
|
||||
EXPECT_EQ(expr->value, 1);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
ASSERT_EQ(e->body->statements.Length(), 1u);
|
||||
EXPECT_TRUE(e->body->statements[0]->Is<ast::AssignmentStatement>());
|
||||
}
|
||||
@@ -62,9 +98,16 @@ TEST_F(ParserImplTest, SwitchBody_Case_TrailingComma) {
|
||||
EXPECT_FALSE(e->IsDefault());
|
||||
auto* stmt = e->As<ast::CaseStatement>();
|
||||
ASSERT_EQ(stmt->selectors.Length(), 2u);
|
||||
EXPECT_EQ(stmt->selectors[0]->value, 1);
|
||||
EXPECT_EQ(stmt->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
EXPECT_EQ(stmt->selectors[1]->value, 2);
|
||||
ASSERT_TRUE(stmt->selectors[0]->Is<ast::IntLiteralExpression>());
|
||||
|
||||
auto* expr = stmt->selectors[0]->As<ast::IntLiteralExpression>();
|
||||
EXPECT_EQ(expr->value, 1);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
|
||||
ASSERT_TRUE(stmt->selectors[1]->Is<ast::IntLiteralExpression>());
|
||||
expr = stmt->selectors[1]->As<ast::IntLiteralExpression>();
|
||||
EXPECT_EQ(expr->value, 2);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_TrailingComma_WithColon) {
|
||||
@@ -76,15 +119,23 @@ TEST_F(ParserImplTest, SwitchBody_Case_TrailingComma_WithColon) {
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
ASSERT_TRUE(e->Is<ast::CaseStatement>());
|
||||
EXPECT_FALSE(e->IsDefault());
|
||||
|
||||
auto* stmt = e->As<ast::CaseStatement>();
|
||||
ASSERT_EQ(stmt->selectors.Length(), 2u);
|
||||
EXPECT_EQ(stmt->selectors[0]->value, 1);
|
||||
EXPECT_EQ(stmt->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
EXPECT_EQ(stmt->selectors[1]->value, 2);
|
||||
ASSERT_TRUE(stmt->selectors[0]->Is<ast::IntLiteralExpression>());
|
||||
|
||||
auto* expr = stmt->selectors[0]->As<ast::IntLiteralExpression>();
|
||||
EXPECT_EQ(expr->value, 1);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
|
||||
ASSERT_TRUE(stmt->selectors[1]->Is<ast::IntLiteralExpression>());
|
||||
expr = stmt->selectors[1]->As<ast::IntLiteralExpression>();
|
||||
EXPECT_EQ(expr->value, 2);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
|
||||
auto p = parser("case a == 4: { a = 4; }");
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_Invalid) {
|
||||
auto p = parser("case if: { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
EXPECT_TRUE(p->has_error());
|
||||
EXPECT_TRUE(e.errored);
|
||||
@@ -93,16 +144,6 @@ TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
|
||||
EXPECT_EQ(p->error(), "1:6: unable to parse case selectors");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_InvalidSelector_bool) {
|
||||
auto p = parser("case true: { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
EXPECT_TRUE(p->has_error());
|
||||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_FALSE(e.matched);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:6: invalid case selector must be an integer value");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_MissingConstLiteral) {
|
||||
auto p = parser("case: { a = 4; }");
|
||||
auto e = p->switch_body();
|
||||
@@ -164,10 +205,16 @@ TEST_F(ParserImplTest, SwitchBody_Case_MultipleSelectors) {
|
||||
EXPECT_FALSE(e->IsDefault());
|
||||
ASSERT_EQ(e->body->statements.Length(), 0u);
|
||||
ASSERT_EQ(e->selectors.Length(), 2u);
|
||||
ASSERT_EQ(e->selectors[0]->value, 1);
|
||||
EXPECT_EQ(e->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
ASSERT_EQ(e->selectors[1]->value, 2);
|
||||
EXPECT_EQ(e->selectors[1]->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
ASSERT_TRUE(e->selectors[0]->Is<ast::IntLiteralExpression>());
|
||||
|
||||
auto* expr = e->selectors[0]->As<ast::IntLiteralExpression>();
|
||||
ASSERT_EQ(expr->value, 1);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
|
||||
ASSERT_TRUE(e->selectors[1]->Is<ast::IntLiteralExpression>());
|
||||
expr = e->selectors[1]->As<ast::IntLiteralExpression>();
|
||||
ASSERT_EQ(expr->value, 2);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_MultipleSelectors_WithColon) {
|
||||
@@ -181,10 +228,16 @@ TEST_F(ParserImplTest, SwitchBody_Case_MultipleSelectors_WithColon) {
|
||||
EXPECT_FALSE(e->IsDefault());
|
||||
ASSERT_EQ(e->body->statements.Length(), 0u);
|
||||
ASSERT_EQ(e->selectors.Length(), 2u);
|
||||
ASSERT_EQ(e->selectors[0]->value, 1);
|
||||
EXPECT_EQ(e->selectors[0]->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
ASSERT_EQ(e->selectors[1]->value, 2);
|
||||
EXPECT_EQ(e->selectors[1]->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
ASSERT_TRUE(e->selectors[0]->Is<ast::IntLiteralExpression>());
|
||||
|
||||
auto* expr = e->selectors[0]->As<ast::IntLiteralExpression>();
|
||||
ASSERT_EQ(expr->value, 1);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
|
||||
ASSERT_TRUE(e->selectors[1]->Is<ast::IntLiteralExpression>());
|
||||
expr = e->selectors[1]->As<ast::IntLiteralExpression>();
|
||||
ASSERT_EQ(expr->value, 2);
|
||||
EXPECT_EQ(expr->suffix, ast::IntLiteralExpression::Suffix::kNone);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, SwitchBody_Case_MultipleSelectorsMissingComma) {
|
||||
|
||||
Reference in New Issue
Block a user