mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 02:39:11 +00:00
[WGSL] Allow default as a case selector
This CL updates the WGSL parser to parse `default` as a case selector value. Bug: tint:1633 Change-Id: I57661d25924e36bec5c03f96399c557fb7bbf760 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/106382 Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com> Auto-Submit: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
d27151d333
commit
f148f0891b
39
src/tint/ast/case_selector.cc
Normal file
39
src/tint/ast/case_selector.cc
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/ast/case_selector.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "src/tint/program_builder.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::CaseSelector);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
CaseSelector::CaseSelector(ProgramID pid, NodeID nid, const Source& src, const ast::Expression* e)
|
||||
: Base(pid, nid, src), expr(e) {}
|
||||
|
||||
CaseSelector::CaseSelector(CaseSelector&&) = default;
|
||||
|
||||
CaseSelector::~CaseSelector() = default;
|
||||
|
||||
const CaseSelector* CaseSelector::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto ex = ctx->Clone(expr);
|
||||
return ctx->dst->create<CaseSelector>(src, ex);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
52
src/tint/ast/case_selector.h
Normal file
52
src/tint/ast/case_selector.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_TINT_AST_CASE_SELECTOR_H_
|
||||
#define SRC_TINT_AST_CASE_SELECTOR_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/ast/block_statement.h"
|
||||
#include "src/tint/ast/expression.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
/// A case selector
|
||||
class CaseSelector final : public Castable<CaseSelector, Node> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param nid the unique node identifier
|
||||
/// @param src the source of this node
|
||||
/// @param expr the selector expression, |nullptr| for a `default` selector
|
||||
CaseSelector(ProgramID pid, NodeID nid, const Source& src, const Expression* expr = nullptr);
|
||||
/// Move constructor
|
||||
CaseSelector(CaseSelector&&);
|
||||
~CaseSelector() override;
|
||||
|
||||
/// @returns true if this is a default statement
|
||||
bool IsDefault() const { return expr == nullptr; }
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CaseSelector* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The selector, nullptr for a default selector
|
||||
const Expression* const expr = nullptr;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
#endif // SRC_TINT_AST_CASE_SELECTOR_H_
|
||||
40
src/tint/ast/case_selector_test.cc
Normal file
40
src/tint/ast/case_selector_test.cc
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/ast/case_selector.h"
|
||||
|
||||
#include "gtest/gtest-spi.h"
|
||||
#include "src/tint/ast/test_helper.h"
|
||||
|
||||
using namespace tint::number_suffixes; // NOLINT
|
||||
|
||||
namespace tint::ast {
|
||||
namespace {
|
||||
|
||||
using CaseSelectorTest = TestHelper;
|
||||
|
||||
TEST_F(CaseSelectorTest, NonDefault) {
|
||||
auto* e = Expr(2_i);
|
||||
auto* c = CaseSelector(e);
|
||||
EXPECT_FALSE(c->IsDefault());
|
||||
EXPECT_EQ(e, c->expr);
|
||||
}
|
||||
|
||||
TEST_F(CaseSelectorTest, Default) {
|
||||
auto* c = DefaultCaseSelector();
|
||||
EXPECT_TRUE(c->IsDefault());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::ast
|
||||
@@ -25,10 +25,11 @@ namespace tint::ast {
|
||||
CaseStatement::CaseStatement(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
utils::VectorRef<const Expression*> s,
|
||||
utils::VectorRef<const CaseSelector*> s,
|
||||
const BlockStatement* b)
|
||||
: Base(pid, nid, src), selectors(std::move(s)), body(b) {
|
||||
TINT_ASSERT(AST, body);
|
||||
TINT_ASSERT(AST, !selectors.IsEmpty());
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
|
||||
for (auto* selector : selectors) {
|
||||
TINT_ASSERT(AST, selector);
|
||||
@@ -40,6 +41,15 @@ CaseStatement::CaseStatement(CaseStatement&&) = default;
|
||||
|
||||
CaseStatement::~CaseStatement() = default;
|
||||
|
||||
bool CaseStatement::ContainsDefault() const {
|
||||
for (const auto* sel : selectors) {
|
||||
if (sel->IsDefault()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const CaseStatement* CaseStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/ast/block_statement.h"
|
||||
#include "src/tint/ast/expression.h"
|
||||
#include "src/tint/ast/case_selector.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
@@ -34,23 +34,23 @@ class CaseStatement final : public Castable<CaseStatement, Statement> {
|
||||
CaseStatement(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
utils::VectorRef<const Expression*> selectors,
|
||||
utils::VectorRef<const CaseSelector*> selectors,
|
||||
const BlockStatement* body);
|
||||
/// Move constructor
|
||||
CaseStatement(CaseStatement&&);
|
||||
~CaseStatement() override;
|
||||
|
||||
/// @returns true if this is a default statement
|
||||
bool IsDefault() const { return selectors.IsEmpty(); }
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CaseStatement* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// @returns true if this item contains a default selector
|
||||
bool ContainsDefault() const;
|
||||
|
||||
/// The case selectors, empty if none set
|
||||
const utils::Vector<const Expression*, 4> selectors;
|
||||
const utils::Vector<const CaseSelector*, 4> selectors;
|
||||
|
||||
/// The case body
|
||||
const BlockStatement* const body;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace {
|
||||
using CaseStatementTest = TestHelper;
|
||||
|
||||
TEST_F(CaseStatementTest, Creation_i32) {
|
||||
auto* selector = Expr(2_i);
|
||||
auto* selector = CaseSelector(2_i);
|
||||
utils::Vector b{selector};
|
||||
|
||||
auto* discard = create<DiscardStatement>();
|
||||
@@ -41,7 +41,7 @@ TEST_F(CaseStatementTest, Creation_i32) {
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, Creation_u32) {
|
||||
auto* selector = Expr(2_u);
|
||||
auto* selector = CaseSelector(2_u);
|
||||
utils::Vector b{selector};
|
||||
|
||||
auto* discard = create<DiscardStatement>();
|
||||
@@ -54,8 +54,20 @@ TEST_F(CaseStatementTest, Creation_u32) {
|
||||
EXPECT_EQ(c->body->statements[0], discard);
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, ContainsDefault_WithDefault) {
|
||||
utils::Vector b{CaseSelector(2_u), DefaultCaseSelector()};
|
||||
auto* c = create<CaseStatement>(b, create<BlockStatement>(utils::Empty));
|
||||
EXPECT_TRUE(c->ContainsDefault());
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, ContainsDefault_WithOutDefault) {
|
||||
utils::Vector b{CaseSelector(2_u), CaseSelector(3_u)};
|
||||
auto* c = create<CaseStatement>(b, create<BlockStatement>(utils::Empty));
|
||||
EXPECT_FALSE(c->ContainsDefault());
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, Creation_WithSource) {
|
||||
utils::Vector b{Expr(2_i)};
|
||||
utils::Vector b{CaseSelector(2_i)};
|
||||
|
||||
auto* body = create<BlockStatement>(utils::Vector{
|
||||
create<DiscardStatement>(),
|
||||
@@ -66,22 +78,9 @@ TEST_F(CaseStatementTest, Creation_WithSource) {
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, IsDefault_WithoutSelectors) {
|
||||
auto* body = create<BlockStatement>(utils::Vector{
|
||||
create<DiscardStatement>(),
|
||||
});
|
||||
auto* c = create<CaseStatement>(utils::Empty, body);
|
||||
EXPECT_TRUE(c->IsDefault());
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, IsDefault_WithSelectors) {
|
||||
utils::Vector b{Expr(2_i)};
|
||||
auto* c = create<CaseStatement>(b, create<BlockStatement>(utils::Empty));
|
||||
EXPECT_FALSE(c->IsDefault());
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, IsCase) {
|
||||
auto* c = create<CaseStatement>(utils::Empty, create<BlockStatement>(utils::Empty));
|
||||
auto* c = create<CaseStatement>(utils::Vector{DefaultCaseSelector()},
|
||||
create<BlockStatement>(utils::Empty));
|
||||
EXPECT_TRUE(c->Is<CaseStatement>());
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ TEST_F(CaseStatementTest, Assert_Null_Body) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CaseStatement>(utils::Empty, nullptr);
|
||||
b.create<CaseStatement>(utils::Vector{b.DefaultCaseSelector()}, nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
@@ -98,7 +97,7 @@ TEST_F(CaseStatementTest, Assert_Null_Selector) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CaseStatement>(utils::Vector<const ast::IntLiteralExpression*, 1>{nullptr},
|
||||
b.create<CaseStatement>(utils::Vector<const ast::CaseSelector*, 1>{nullptr},
|
||||
b.create<BlockStatement>(utils::Empty));
|
||||
},
|
||||
"internal compiler error");
|
||||
@@ -109,7 +108,8 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Call) {
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CaseStatement>(utils::Empty, b2.create<BlockStatement>(utils::Empty));
|
||||
b1.create<CaseStatement>(utils::Vector{b1.DefaultCaseSelector()},
|
||||
b2.create<BlockStatement>(utils::Empty));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
@@ -119,7 +119,7 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Selector) {
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CaseStatement>(utils::Vector{b2.Expr(2_i)},
|
||||
b1.create<CaseStatement>(utils::Vector{b2.CaseSelector(b2.Expr(2_i))},
|
||||
b1.create<BlockStatement>(utils::Empty));
|
||||
},
|
||||
"internal compiler error");
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace {
|
||||
using SwitchStatementTest = TestHelper;
|
||||
|
||||
TEST_F(SwitchStatementTest, Creation) {
|
||||
auto* case_stmt = create<CaseStatement>(utils::Vector{Expr(1_u)}, Block());
|
||||
auto* case_stmt = create<CaseStatement>(utils::Vector{CaseSelector(1_u)}, Block());
|
||||
auto* ident = Expr("ident");
|
||||
utils::Vector body{case_stmt};
|
||||
|
||||
@@ -44,7 +44,7 @@ TEST_F(SwitchStatementTest, Creation_WithSource) {
|
||||
}
|
||||
|
||||
TEST_F(SwitchStatementTest, IsSwitch) {
|
||||
utils::Vector lit{Expr(2_i)};
|
||||
utils::Vector lit{CaseSelector(2_i)};
|
||||
auto* ident = Expr("ident");
|
||||
utils::Vector body{create<CaseStatement>(lit, Block())};
|
||||
|
||||
@@ -58,7 +58,8 @@ TEST_F(SwitchStatementTest, Assert_Null_Condition) {
|
||||
{
|
||||
ProgramBuilder b;
|
||||
CaseStatementList cases;
|
||||
cases.Push(b.create<CaseStatement>(utils::Vector{b.Expr(1_i)}, b.Block()));
|
||||
cases.Push(
|
||||
b.create<CaseStatement>(utils::Vector{b.CaseSelector(b.Expr(1_i))}, b.Block()));
|
||||
b.create<SwitchStatement>(nullptr, cases);
|
||||
},
|
||||
"internal compiler error");
|
||||
@@ -82,7 +83,7 @@ TEST_F(SwitchStatementTest, Assert_DifferentProgramID_Condition) {
|
||||
b1.create<SwitchStatement>(b2.Expr(true), utils::Vector{
|
||||
b1.create<CaseStatement>(
|
||||
utils::Vector{
|
||||
b1.Expr(1_i),
|
||||
b1.CaseSelector(b1.Expr(1_i)),
|
||||
},
|
||||
b1.Block()),
|
||||
});
|
||||
@@ -98,7 +99,7 @@ TEST_F(SwitchStatementTest, Assert_DifferentProgramID_CaseStatement) {
|
||||
b1.create<SwitchStatement>(b1.Expr(true), utils::Vector{
|
||||
b2.create<CaseStatement>(
|
||||
utils::Vector{
|
||||
b2.Expr(1_i),
|
||||
b2.CaseSelector(b2.Expr(1_i)),
|
||||
},
|
||||
b2.Block()),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user