tint/writer: Handle static_asserts

These (with exception to the WGSL writer) are not emitted.

Bug: tint:1625
Change-Id: Id8b36b5c83a6fe2dab042cf46b0c3dbca75e0926
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97962
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2022-08-03 07:01:08 +00:00 committed by Dawn LUCI CQ
parent 759ac33cd1
commit b4744ac359
12 changed files with 294 additions and 88 deletions

View File

@ -1322,6 +1322,7 @@ if (tint_build_unittests) {
"writer/spirv/builder_literal_test.cc",
"writer/spirv/builder_loop_test.cc",
"writer/spirv/builder_return_test.cc",
"writer/spirv/builder_static_assert_test.cc",
"writer/spirv/builder_switch_test.cc",
"writer/spirv/builder_test.cc",
"writer/spirv/builder_type_test.cc",
@ -1447,6 +1448,7 @@ if (tint_build_unittests) {
"writer/wgsl/generator_impl_loop_test.cc",
"writer/wgsl/generator_impl_member_accessor_test.cc",
"writer/wgsl/generator_impl_return_test.cc",
"writer/wgsl/generator_impl_static_assert_test.cc",
"writer/wgsl/generator_impl_switch_test.cc",
"writer/wgsl/generator_impl_test.cc",
"writer/wgsl/generator_impl_type_test.cc",
@ -1487,6 +1489,7 @@ if (tint_build_unittests) {
"writer/msl/generator_impl_module_constant_test.cc",
"writer/msl/generator_impl_return_test.cc",
"writer/msl/generator_impl_sanitizer_test.cc",
"writer/msl/generator_impl_static_assert_test.cc",
"writer/msl/generator_impl_switch_test.cc",
"writer/msl/generator_impl_test.cc",
"writer/msl/generator_impl_type_test.cc",
@ -1526,6 +1529,7 @@ if (tint_build_unittests) {
"writer/hlsl/generator_impl_module_constant_test.cc",
"writer/hlsl/generator_impl_return_test.cc",
"writer/hlsl/generator_impl_sanitizer_test.cc",
"writer/hlsl/generator_impl_static_assert_test.cc",
"writer/hlsl/generator_impl_switch_test.cc",
"writer/hlsl/generator_impl_test.cc",
"writer/hlsl/generator_impl_type_test.cc",

View File

@ -1039,6 +1039,7 @@ if(TINT_BUILD_TESTS)
writer/spirv/builder_literal_test.cc
writer/spirv/builder_loop_test.cc
writer/spirv/builder_return_test.cc
writer/spirv/builder_static_assert_test.cc
writer/spirv/builder_switch_test.cc
writer/spirv/builder_test.cc
writer/spirv/builder_type_test.cc
@ -1078,6 +1079,7 @@ if(TINT_BUILD_TESTS)
writer/wgsl/generator_impl_literal_test.cc
writer/wgsl/generator_impl_member_accessor_test.cc
writer/wgsl/generator_impl_return_test.cc
writer/wgsl/generator_impl_static_assert_test.cc
writer/wgsl/generator_impl_switch_test.cc
writer/wgsl/generator_impl_type_test.cc
writer/wgsl/generator_impl_unary_op_test.cc
@ -1160,6 +1162,7 @@ if(TINT_BUILD_TESTS)
writer/msl/generator_impl_module_constant_test.cc
writer/msl/generator_impl_return_test.cc
writer/msl/generator_impl_sanitizer_test.cc
writer/msl/generator_impl_static_assert_test.cc
writer/msl/generator_impl_switch_test.cc
writer/msl/generator_impl_test.cc
writer/msl/generator_impl_type_test.cc
@ -1231,6 +1234,7 @@ if(TINT_BUILD_TESTS)
writer/hlsl/generator_impl_module_constant_test.cc
writer/hlsl/generator_impl_return_test.cc
writer/hlsl/generator_impl_sanitizer_test.cc
writer/hlsl/generator_impl_static_assert_test.cc
writer/hlsl/generator_impl_switch_test.cc
writer/hlsl/generator_impl_test.cc
writer/hlsl/generator_impl_type_test.cc

View File

@ -273,8 +273,8 @@ bool GeneratorImpl::Generate() {
auto* mod = builder_.Sem().Module();
for (auto* decl : mod->DependencyOrderedDeclarations()) {
if (decl->Is<ast::Alias>()) {
continue; // Ignore aliases.
if (decl->IsAnyOf<ast::Alias, ast::StaticAssert>()) {
continue; // These are not emitted.
}
if (auto* global = decl->As<ast::Variable>()) {
@ -2652,69 +2652,53 @@ bool GeneratorImpl::EmitReturn(const ast::ReturnStatement* stmt) {
}
bool GeneratorImpl::EmitStatement(const ast::Statement* stmt) {
if (auto* a = stmt->As<ast::AssignmentStatement>()) {
return EmitAssign(a);
}
if (auto* b = stmt->As<ast::BlockStatement>()) {
return EmitBlock(b);
}
if (auto* b = stmt->As<ast::BreakStatement>()) {
return EmitBreak(b);
}
if (auto* c = stmt->As<ast::CallStatement>()) {
auto out = line();
if (!EmitCall(out, c->expr)) {
return false;
}
out << ";";
return true;
}
if (auto* c = stmt->As<ast::ContinueStatement>()) {
return EmitContinue(c);
}
if (auto* d = stmt->As<ast::DiscardStatement>()) {
return EmitDiscard(d);
}
if (stmt->As<ast::FallthroughStatement>()) {
line() << "/* fallthrough */";
return true;
}
if (auto* i = stmt->As<ast::IfStatement>()) {
return EmitIf(i);
}
if (auto* l = stmt->As<ast::LoopStatement>()) {
return EmitLoop(l);
}
if (auto* l = stmt->As<ast::ForLoopStatement>()) {
return EmitForLoop(l);
}
if (auto* l = stmt->As<ast::WhileStatement>()) {
return EmitWhile(l);
}
if (auto* r = stmt->As<ast::ReturnStatement>()) {
return EmitReturn(r);
}
if (auto* s = stmt->As<ast::SwitchStatement>()) {
return EmitSwitch(s);
}
if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
return Switch(
v->variable, //
[&](const ast::Var* var) { return EmitVar(var); },
[&](const ast::Let* let) { return EmitLet(let); },
[&](const ast::Const*) {
return true; // Constants are embedded at their use
},
[&](Default) { //
TINT_ICE(Writer, diagnostics_)
<< "unknown variable type: " << v->variable->TypeInfo().name;
return Switch(
stmt, //
[&](const ast::AssignmentStatement* a) { return EmitAssign(a); },
[&](const ast::BlockStatement* b) { return EmitBlock(b); },
[&](const ast::BreakStatement* b) { return EmitBreak(b); },
[&](const ast::CallStatement* c) {
auto out = line();
if (!EmitCall(out, c->expr)) {
return false;
});
}
diagnostics_.add_error(diag::System::Writer,
"unknown statement type: " + std::string(stmt->TypeInfo().name));
return false;
}
out << ";";
return true;
},
[&](const ast::ContinueStatement* c) { return EmitContinue(c); },
[&](const ast::DiscardStatement* d) { return EmitDiscard(d); },
[&](const ast::FallthroughStatement*) {
line() << "/* fallthrough */";
return true;
},
[&](const ast::IfStatement* i) { return EmitIf(i); },
[&](const ast::LoopStatement* l) { return EmitLoop(l); },
[&](const ast::ForLoopStatement* l) { return EmitForLoop(l); },
[&](const ast::WhileStatement* l) { return EmitWhile(l); },
[&](const ast::ReturnStatement* r) { return EmitReturn(r); },
[&](const ast::SwitchStatement* s) { return EmitSwitch(s); },
[&](const ast::VariableDeclStatement* v) {
return Switch(
v->variable, //
[&](const ast::Var* var) { return EmitVar(var); },
[&](const ast::Let* let) { return EmitLet(let); },
[&](const ast::Const*) {
return true; // Constants are embedded at their use
},
[&](Default) { //
TINT_ICE(Writer, diagnostics_)
<< "unknown variable type: " << v->variable->TypeInfo().name;
return false;
});
},
[&](const ast::StaticAssert*) {
return true; // Not emitted
},
[&](Default) {
diagnostics_.add_error(diag::System::Writer,
"unknown statement type: " + std::string(stmt->TypeInfo().name));
return false;
});
}
bool GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {

View File

@ -275,12 +275,8 @@ bool GeneratorImpl::Generate() {
auto* mod = builder_.Sem().Module();
for (auto* decl : mod->DependencyOrderedDeclarations()) {
if (decl->Is<ast::Alias>()) {
continue; // Ignore aliases.
}
if (decl->Is<ast::Enable>()) {
// Currently we don't have to do anything for using a extension in HLSL.
continue;
if (decl->IsAnyOf<ast::Alias, ast::Enable, ast::StaticAssert>()) {
continue; // These are not emitted.
}
// Emit a new line between declarations if the type of declaration has
@ -3646,6 +3642,9 @@ bool GeneratorImpl::EmitStatement(const ast::Statement* stmt) {
return false;
});
},
[&](const ast::StaticAssert*) {
return true; // Not emitted
},
[&](Default) { //
diagnostics_.add_error(diag::System::Writer,
"unknown statement type: " + std::string(stmt->TypeInfo().name));

View File

@ -0,0 +1,47 @@
// 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/writer/hlsl/test_helper.h"
using namespace tint::number_suffixes; // NOLINT
namespace tint::writer::hlsl {
namespace {
using HlslGeneratorImplTest = TestHelper;
TEST_F(HlslGeneratorImplTest, Emit_GlobalStaticAssert) {
GlobalStaticAssert(true);
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
// static asserts are not emitted
EXPECT_EQ(gen.result(), "");
}
TEST_F(HlslGeneratorImplTest, Emit_FunctionStaticAssert) {
Func("f", utils::Empty, ty.void_(), utils::Vector{StaticAssert(true)});
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
// static asserts are not emitted
EXPECT_EQ(gen.result(), R"(void f() {
}
)");
}
} // namespace
} // namespace tint::writer::hlsl

View File

@ -286,6 +286,9 @@ bool GeneratorImpl::Generate() {
// Do nothing for enabling extension in MSL
return true;
},
[&](const ast::StaticAssert*) {
return true; // Not emitted
},
[&](Default) {
// These are pushed into the entry point by sanitizer transforms.
TINT_ICE(Writer, diagnostics_) << "unhandled type: " << decl->TypeInfo().name;
@ -2419,6 +2422,9 @@ bool GeneratorImpl::EmitStatement(const ast::Statement* stmt) {
return false;
});
},
[&](const ast::StaticAssert*) {
return true; // Not emitted
},
[&](Default) {
diagnostics_.add_error(diag::System::Writer,
"unknown statement type: " + std::string(stmt->TypeInfo().name));

View File

@ -0,0 +1,54 @@
// 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/writer/msl/test_helper.h"
using namespace tint::number_suffixes; // NOLINT
namespace tint::writer::msl {
namespace {
using MslGeneratorImplTest = TestHelper;
TEST_F(MslGeneratorImplTest, Emit_GlobalStaticAssert) {
GlobalStaticAssert(true);
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
// static asserts are not emitted
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
using namespace metal;
)");
}
TEST_F(MslGeneratorImplTest, Emit_FunctionStaticAssert) {
Func("f", utils::Empty, ty.void_(), utils::Vector{StaticAssert(true)});
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
// static asserts are not emitted
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
using namespace metal;
void f() {
}
)");
}
} // namespace
} // namespace tint::writer::msl

View File

@ -3723,12 +3723,8 @@ bool Builder::GenerateLoopStatement(const ast::LoopStatement* stmt) {
bool Builder::GenerateStatement(const ast::Statement* stmt) {
return Switch(
stmt, [&](const ast::AssignmentStatement* a) { return GenerateAssignStatement(a); },
[&](const ast::BlockStatement* b) { //
return GenerateBlockStatement(b);
},
[&](const ast::BreakStatement* b) { //
return GenerateBreakStatement(b);
},
[&](const ast::BlockStatement* b) { return GenerateBlockStatement(b); },
[&](const ast::BreakStatement* b) { return GenerateBreakStatement(b); },
[&](const ast::CallStatement* c) { return GenerateCallExpression(c->expr) != 0; },
[&](const ast::ContinueStatement* c) { return GenerateContinueStatement(c); },
[&](const ast::DiscardStatement* d) { return GenerateDiscardStatement(d); },
@ -3736,19 +3732,14 @@ bool Builder::GenerateStatement(const ast::Statement* stmt) {
// Do nothing here, the fallthrough gets handled by the switch code.
return true;
},
[&](const ast::IfStatement* i) { //
return GenerateIfStatement(i);
},
[&](const ast::LoopStatement* l) { //
return GenerateLoopStatement(l);
},
[&](const ast::ReturnStatement* r) { //
return GenerateReturnStatement(r);
},
[&](const ast::SwitchStatement* s) { //
return GenerateSwitchStatement(s);
},
[&](const ast::IfStatement* i) { return GenerateIfStatement(i); },
[&](const ast::LoopStatement* l) { return GenerateLoopStatement(l); },
[&](const ast::ReturnStatement* r) { return GenerateReturnStatement(r); },
[&](const ast::SwitchStatement* s) { return GenerateSwitchStatement(s); },
[&](const ast::VariableDeclStatement* v) { return GenerateVariableDeclStatement(v); },
[&](const ast::StaticAssert*) {
return true; // Not emitted
},
[&](Default) {
error_ = "Unknown statement: " + std::string(stmt->TypeInfo().name);
return false;

View File

@ -0,0 +1,54 @@
// 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/fallthrough_statement.h"
#include "src/tint/writer/spirv/spv_dump.h"
#include "src/tint/writer/spirv/test_helper.h"
using namespace tint::number_suffixes; // NOLINT
namespace tint::writer::spirv {
namespace {
using BuilderTest = TestHelper;
TEST_F(BuilderTest, GlobalStaticAssert) {
GlobalStaticAssert(true);
spirv::Builder& b = Build();
ASSERT_TRUE(b.Build()) << b.error();
// static asserts are not emitted
EXPECT_EQ(DumpInstructions(b.types()), "");
EXPECT_EQ(b.functions().size(), 0u);
}
TEST_F(BuilderTest, FunctionStaticAssert) {
Func("f", utils::Empty, ty.void_(), utils::Vector{StaticAssert(true)});
spirv::Builder& b = Build();
ASSERT_TRUE(b.Build()) << b.error();
// static asserts are not emitted
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
%1 = OpTypeFunction %2
)");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpReturn
)");
}
} // namespace
} // namespace tint::writer::spirv

View File

@ -80,6 +80,7 @@ bool GeneratorImpl::Generate() {
[&](const ast::TypeDecl* td) { return EmitTypeDecl(td); },
[&](const ast::Function* func) { return EmitFunction(func); },
[&](const ast::Variable* var) { return EmitVariable(line(), var); },
[&](const ast::StaticAssert* sa) { return EmitStaticAssert(sa); },
[&](Default) {
TINT_UNREACHABLE(Writer, diagnostics_);
return false;
@ -946,6 +947,7 @@ bool GeneratorImpl::EmitStatement(const ast::Statement* stmt) {
[&](const ast::ForLoopStatement* l) { return EmitForLoop(l); },
[&](const ast::WhileStatement* l) { return EmitWhile(l); },
[&](const ast::ReturnStatement* r) { return EmitReturn(r); },
[&](const ast::StaticAssert* s) { return EmitStaticAssert(s); },
[&](const ast::SwitchStatement* s) { return EmitSwitch(s); },
[&](const ast::VariableDeclStatement* v) { return EmitVariable(line(), v->variable); },
[&](Default) {
@ -1244,6 +1246,16 @@ bool GeneratorImpl::EmitReturn(const ast::ReturnStatement* stmt) {
return true;
}
bool GeneratorImpl::EmitStaticAssert(const ast::StaticAssert* stmt) {
auto out = line();
out << "static_assert ";
if (!EmitExpression(out, stmt->condition)) {
return false;
}
out << ";";
return true;
}
bool GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
{
auto out = line();

View File

@ -165,6 +165,10 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted
bool EmitReturn(const ast::ReturnStatement* stmt);
/// Handles static assertion statements
/// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted
bool EmitStaticAssert(const ast::StaticAssert* stmt);
/// Handles statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted

View File

@ -0,0 +1,47 @@
// 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/writer/wgsl/test_helper.h"
using namespace tint::number_suffixes; // NOLINT
namespace tint::writer::wgsl {
namespace {
using WgslGeneratorImplTest = TestHelper;
TEST_F(WgslGeneratorImplTest, Emit_GlobalStaticAssert) {
GlobalStaticAssert(true);
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(static_assert true;
)");
}
TEST_F(WgslGeneratorImplTest, Emit_FunctionStaticAssert) {
Func("f", utils::Empty, ty.void_(), utils::Vector{StaticAssert(true)});
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(fn f() {
static_assert true;
}
)");
}
} // namespace
} // namespace tint::writer::wgsl