Remove infrastructure for fallthrough

This Cl removes the internal infrastructor and backend code
generation for the fallthrough statement.

Bug: tint:1644
Change-Id: I2a1de7d527865e5a7221074f4e0fb106599f4c57
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/109005
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
dan sinclair
2022-11-15 00:30:33 +00:00
committed by Dawn LUCI CQ
parent bf586f6dfd
commit 267f1748c8
32 changed files with 39 additions and 571 deletions

View File

@@ -14,7 +14,6 @@
#include "src/tint/ast/break_statement.h"
#include "src/tint/ast/continue_statement.h"
#include "src/tint/ast/fallthrough_statement.h"
#include "src/tint/ast/switch_statement.h"
#include "src/tint/resolver/resolver_test_helper.h"
@@ -378,24 +377,6 @@ TEST_F(ResolverControlBlockValidationTest, NonUniqueCaseSelectorValueSint_Fail)
"12:34 note: previous case declared here");
}
TEST_F(ResolverControlBlockValidationTest, LastClauseLastStatementIsFallthrough_Fail) {
// var a : i32 = 2;
// switch (a) {
// default: { fallthrough; }
// }
auto* var = Var("a", ty.i32(), Expr(2_i));
auto* fallthrough = create<ast::FallthroughStatement>(Source{{12, 34}});
auto* block = Block(Decl(var), //
Switch("a", //
DefaultCase(Block(fallthrough))));
WrapInFunction(block);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: a fallthrough statement must not be used in the last "
"switch case");
}
TEST_F(ResolverControlBlockValidationTest, SwitchCase_Pass) {
// var a : i32 = 2;
// switch (a) {

View File

@@ -35,7 +35,6 @@
#include "src/tint/ast/external_texture.h"
#include "src/tint/ast/f16.h"
#include "src/tint/ast/f32.h"
#include "src/tint/ast/fallthrough_statement.h"
#include "src/tint/ast/for_loop_statement.h"
#include "src/tint/ast/i32.h"
#include "src/tint/ast/id_attribute.h"
@@ -320,7 +319,7 @@ class DependencyScanner {
[&](const ast::StaticAssert* assertion) { TraverseExpression(assertion->condition); },
[&](Default) {
if (!stmt->IsAnyOf<ast::BreakStatement, ast::ContinueStatement,
ast::DiscardStatement, ast::FallthroughStatement>()) {
ast::DiscardStatement>()) {
UnhandledNode(diagnostics_, stmt);
}
});

View File

@@ -1273,8 +1273,6 @@ TEST_F(ResolverDependencyGraphTraversalTest, SymbolsReached) {
Switch(V, //
Case(CaseSelector(1_i), //
Block(Assign(V, V))), //
Case(CaseSelector(2_i), //
Block(Fallthrough())), //
DefaultCase(Block(Assign(V, V)))), //
Return(V), //
Break(), //

View File

@@ -31,7 +31,6 @@
#include "src/tint/ast/depth_texture.h"
#include "src/tint/ast/disable_validation_attribute.h"
#include "src/tint/ast/discard_statement.h"
#include "src/tint/ast/fallthrough_statement.h"
#include "src/tint/ast/for_loop_statement.h"
#include "src/tint/ast/id_attribute.h"
#include "src/tint/ast/if_statement.h"
@@ -1217,7 +1216,6 @@ sem::Statement* Resolver::Statement(const ast::Statement* stmt) {
[&](const ast::CompoundAssignmentStatement* c) { return CompoundAssignmentStatement(c); },
[&](const ast::ContinueStatement* c) { return ContinueStatement(c); },
[&](const ast::DiscardStatement* d) { return DiscardStatement(d); },
[&](const ast::FallthroughStatement* f) { return FallthroughStatement(f); },
[&](const ast::IncrementDecrementStatement* i) { return IncrementDecrementStatement(i); },
[&](const ast::ReturnStatement* r) { return ReturnStatement(r); },
[&](const ast::VariableDeclStatement* v) { return VariableDeclStatement(v); },
@@ -3146,7 +3144,7 @@ sem::SwitchStatement* Resolver::SwitchStatement(const ast::SwitchStatement* stmt
if (behaviors.Contains(sem::Behavior::kBreak)) {
behaviors.Add(sem::Behavior::kNext);
}
behaviors.Remove(sem::Behavior::kBreak, sem::Behavior::kFallthrough);
behaviors.Remove(sem::Behavior::kBreak);
return validator_.SwitchStatement(stmt);
});
@@ -3308,16 +3306,6 @@ sem::Statement* Resolver::DiscardStatement(const ast::DiscardStatement* stmt) {
});
}
sem::Statement* Resolver::FallthroughStatement(const ast::FallthroughStatement* stmt) {
auto* sem =
builder_->create<sem::Statement>(stmt, current_compound_statement_, current_function_);
return StatementScope(stmt, sem, [&] {
sem->Behaviors() = sem::Behavior::kFallthrough;
return validator_.FallthroughStatement(sem);
});
}
sem::Statement* Resolver::IncrementDecrementStatement(
const ast::IncrementDecrementStatement* stmt) {
auto* sem =

View File

@@ -212,7 +212,6 @@ class Resolver {
sem::Statement* CompoundAssignmentStatement(const ast::CompoundAssignmentStatement*);
sem::Statement* ContinueStatement(const ast::ContinueStatement*);
sem::Statement* DiscardStatement(const ast::DiscardStatement*);
sem::Statement* FallthroughStatement(const ast::FallthroughStatement*);
sem::ForLoopStatement* ForLoopStatement(const ast::ForLoopStatement*);
sem::WhileStatement* WhileStatement(const ast::WhileStatement*);
sem::GlobalVariable* GlobalVariable(const ast::Variable*);

View File

@@ -477,10 +477,9 @@ class UniformityGraph {
}
// Propagate all variables assignments to the containing scope if the behavior is
// either 'Next' or 'Fallthrough'.
// 'Next'.
auto& behaviors = sem_.Get(b)->Behaviors();
if (behaviors.Contains(sem::Behavior::kNext) ||
behaviors.Contains(sem::Behavior::kFallthrough)) {
if (behaviors.Contains(sem::Behavior::kNext)) {
for (auto var : scoped_assignments) {
current_function_->variables.Set(var.key, var.value);
}
@@ -613,8 +612,6 @@ class UniformityGraph {
[&](const ast::DiscardStatement*) { return cf; },
[&](const ast::FallthroughStatement*) { return cf; },
[&](const ast::ForLoopStatement* f) {
auto* sem_loop = sem_.Get(f);
auto* cfx = CreateNode("loop_start");
@@ -937,46 +934,35 @@ class UniformityGraph {
info.type = "switch";
auto* cf_n = v;
bool previous_case_has_fallthrough = false;
for (auto* c : s->body) {
auto* sem_case = sem_.Get(c);
if (previous_case_has_fallthrough) {
cf_n = ProcessStatement(cf_n, c->body);
} else {
current_function_->variables.Push();
cf_n = ProcessStatement(v, c->body);
}
current_function_->variables.Push();
cf_n = ProcessStatement(v, c->body);
if (cf_end) {
cf_end->AddEdge(cf_n);
}
bool has_fallthrough =
sem_case->Behaviors().Contains(sem::Behavior::kFallthrough);
if (!has_fallthrough) {
if (sem_case->Behaviors().Contains(sem::Behavior::kNext)) {
// Propagate variable values to the switch exit nodes.
for (auto* var : current_function_->local_var_decls) {
// Skip variables that were declared inside the switch.
if (auto* lv = var->As<sem::LocalVariable>();
lv && lv->Statement()->FindFirstParent(
[&](auto* st) { return st == sem_switch; })) {
continue;
}
// Add an edge from the variable exit node to its new value.
auto* exit_node = info.var_exit_nodes.GetOrCreate(var, [&]() {
auto name =
builder_->Symbols().NameFor(var->Declaration()->symbol);
return CreateNode(name + "_value_" + info.type + "_exit");
});
exit_node->AddEdge(current_function_->variables.Get(var));
if (sem_case->Behaviors().Contains(sem::Behavior::kNext)) {
// Propagate variable values to the switch exit nodes.
for (auto* var : current_function_->local_var_decls) {
// Skip variables that were declared inside the switch.
if (auto* lv = var->As<sem::LocalVariable>();
lv && lv->Statement()->FindFirstParent(
[&](auto* st) { return st == sem_switch; })) {
continue;
}
// Add an edge from the variable exit node to its new value.
auto* exit_node = info.var_exit_nodes.GetOrCreate(var, [&]() {
auto name = builder_->Symbols().NameFor(var->Declaration()->symbol);
return CreateNode(name + "_value_" + info.type + "_exit");
});
exit_node->AddEdge(current_function_->variables.Get(var));
}
current_function_->variables.Pop();
}
previous_case_has_fallthrough = has_fallthrough;
current_function_->variables.Pop();
}
// Update nodes for any variables assigned in the switch statement.

View File

@@ -28,7 +28,6 @@
#include "src/tint/ast/depth_texture.h"
#include "src/tint/ast/disable_validation_attribute.h"
#include "src/tint/ast/discard_statement.h"
#include "src/tint/ast/fallthrough_statement.h"
#include "src/tint/ast/for_loop_statement.h"
#include "src/tint/ast/id_attribute.h"
#include "src/tint/ast/if_statement.h"
@@ -1538,26 +1537,6 @@ bool Validator::Call(const sem::Call* call, sem::Statement* current_statement) c
return true;
}
bool Validator::FallthroughStatement(const sem::Statement* stmt) const {
if (auto* block = As<sem::BlockStatement>(stmt->Parent())) {
if (auto* c = As<sem::CaseStatement>(block->Parent())) {
if (block->Declaration()->Last() == stmt->Declaration()) {
if (auto* s = As<sem::SwitchStatement>(c->Parent())) {
if (c->Declaration() != s->Declaration()->body.Back()) {
return true;
}
AddError("a fallthrough statement must not be used in the last switch case",
stmt->Declaration()->source);
return false;
}
}
}
}
AddError("fallthrough must only be used as the last statement of a case block",
stmt->Declaration()->source);
return false;
}
bool Validator::LoopStatement(const sem::LoopStatement* stmt) const {
if (stmt->Behaviors().Empty()) {
AddError("loop does not exit", stmt->Declaration()->source.Begin());

View File

@@ -223,11 +223,6 @@ class Validator {
/// @returns true on success, false otherwise
bool WhileStatement(const sem::WhileStatement* stmt) const;
/// Validates a fallthrough statement
/// @param stmt the fallthrough to validate
/// @returns true on success, false otherwise
bool FallthroughStatement(const sem::Statement* stmt) const;
/// Validates a function
/// @param func the function to validate
/// @param stage the current pipeline stage