tint/sem: Move variable decls to CompoundStatement
Variables can be declared in more than just BlockStatement.
For example, for-loops can declare a variable.
Change this to be a map instead of a vector. This helps with lookups.
Change-Id: Ic9429425af70e9535c21cc0875b875f145724266
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/104040
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index eebd5ea..f6df04d 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -2268,21 +2268,16 @@
current_statement_->FindFirstParent<sem::LoopContinuingBlockStatement>()) {
auto* loop_block = continuing_block->FindFirstParent<sem::LoopBlockStatement>();
if (loop_block->FirstContinue()) {
- auto& decls = loop_block->Decls();
// If our identifier is in loop_block->decls, make sure its index is
// less than first_continue
- auto iter = std::find_if(decls.begin(), decls.end(),
- [&symbol](auto* v) { return v->symbol == symbol; });
- if (iter != decls.end()) {
- auto var_decl_index =
- static_cast<size_t>(std::distance(decls.begin(), iter));
- if (var_decl_index >= loop_block->NumDeclsAtFirstContinue()) {
+ if (auto* decl = loop_block->Decls().Find(symbol)) {
+ if (decl->order >= loop_block->NumDeclsAtFirstContinue()) {
AddError("continue statement bypasses declaration of '" +
builder_->Symbols().NameFor(symbol) + "'",
loop_block->FirstContinue()->source);
AddNote("identifier '" + builder_->Symbols().NameFor(symbol) +
"' declared here",
- (*iter)->source);
+ decl->variable->Declaration()->source);
AddNote("identifier '" + builder_->Symbols().NameFor(symbol) +
"' referenced in continuing block here",
expr->source);
@@ -3128,9 +3123,7 @@
}
}
- if (current_block_) { // Not all statements are inside a block
- current_block_->AddDecl(stmt->variable);
- }
+ current_compound_statement_->AddDecl(variable->As<sem::LocalVariable>());
if (auto* ctor = variable->Constructor()) {
sem->Behaviors() = ctor->Behaviors();
@@ -3232,7 +3225,7 @@
if (auto* block = sem->FindFirstParent<sem::LoopBlockStatement>()) {
if (!block->FirstContinue()) {
const_cast<sem::LoopBlockStatement*>(block)->SetFirstContinue(
- stmt, block->Decls().size());
+ stmt, block->Decls().Count());
}
}
@@ -3337,12 +3330,10 @@
builder_->Sem().Add(ast, sem);
auto* as_compound = As<sem::CompoundStatement, CastFlags::kDontErrorOnImpossibleCast>(sem);
- auto* as_block = As<sem::BlockStatement, CastFlags::kDontErrorOnImpossibleCast>(sem);
TINT_SCOPED_ASSIGNMENT(current_statement_, sem);
TINT_SCOPED_ASSIGNMENT(current_compound_statement_,
as_compound ? as_compound : current_compound_statement_);
- TINT_SCOPED_ASSIGNMENT(current_block_, as_block ? as_block : current_block_);
if (!callback()) {
return nullptr;
diff --git a/src/tint/resolver/resolver.h b/src/tint/resolver/resolver.h
index f699996..c25b48e 100644
--- a/src/tint/resolver/resolver.h
+++ b/src/tint/resolver/resolver.h
@@ -375,11 +375,8 @@
/// * Assigns `sem` to #current_statement_
/// * Assigns `sem` to #current_compound_statement_ if `sem` derives from
/// sem::CompoundStatement.
- /// * Assigns `sem` to #current_block_ if `sem` derives from
- /// sem::BlockStatement.
/// * Then calls `callback`.
- /// * Before returning #current_statement_, #current_compound_statement_, and
- /// #current_block_ are restored to their original values.
+ /// * Before returning #current_statement_ and #current_compound_statement_ are restored to their original values.
/// @returns `sem` if `callback` returns true, otherwise `nullptr`.
template <typename SEM, typename F>
SEM* StatementScope(const ast::Statement* ast, SEM* sem, F&& callback);
@@ -441,7 +438,6 @@
sem::Function* current_function_ = nullptr;
sem::Statement* current_statement_ = nullptr;
sem::CompoundStatement* current_compound_statement_ = nullptr;
- sem::BlockStatement* current_block_ = nullptr;
};
} // namespace tint::resolver
diff --git a/src/tint/resolver/uniformity.cc b/src/tint/resolver/uniformity.cc
index f75536b..7de92f8 100644
--- a/src/tint/resolver/uniformity.cc
+++ b/src/tint/resolver/uniformity.cc
@@ -481,8 +481,8 @@
}
// Remove any variables declared in this scope from the set of in-scope variables.
- for (auto* d : sem_.Get<sem::BlockStatement>(b)->Decls()) {
- current_function_->local_var_decls.erase(sem_.Get<sem::LocalVariable>(d));
+ for (auto decl : sem_.Get<sem::BlockStatement>(b)->Decls()) {
+ current_function_->local_var_decls.erase(decl.value.variable);
}
return cf;
diff --git a/src/tint/sem/block_statement.cc b/src/tint/sem/block_statement.cc
index 51bad0f..12b8318 100644
--- a/src/tint/sem/block_statement.cc
+++ b/src/tint/sem/block_statement.cc
@@ -35,10 +35,6 @@
return Base::Declaration()->As<ast::BlockStatement>();
}
-void BlockStatement::AddDecl(const ast::Variable* var) {
- decls_.push_back(var);
-}
-
FunctionBlockStatement::FunctionBlockStatement(const sem::Function* function)
: Base(function->Declaration()->body, nullptr, function) {
TINT_ASSERT(Semantic, function);
diff --git a/src/tint/sem/block_statement.h b/src/tint/sem/block_statement.h
index 4f12122..e5d4969 100644
--- a/src/tint/sem/block_statement.h
+++ b/src/tint/sem/block_statement.h
@@ -47,16 +47,6 @@
/// @returns the AST block statement associated with this semantic block
/// statement
const ast::BlockStatement* Declaration() const;
-
- /// @returns the declarations associated with this block
- const std::vector<const ast::Variable*>& Decls() const { return decls_; }
-
- /// Associates a declaration with this block.
- /// @param var a variable declaration to be added to the block
- void AddDecl(const ast::Variable* var);
-
- private:
- std::vector<const ast::Variable*> decls_;
};
/// The root block statement for a function
diff --git a/src/tint/sem/statement.cc b/src/tint/sem/statement.cc
index fb8e557..685f0d6 100644
--- a/src/tint/sem/statement.cc
+++ b/src/tint/sem/statement.cc
@@ -17,8 +17,10 @@
#include "src/tint/ast/block_statement.h"
#include "src/tint/ast/loop_statement.h"
#include "src/tint/ast/statement.h"
+#include "src/tint/ast/variable.h"
#include "src/tint/sem/block_statement.h"
#include "src/tint/sem/statement.h"
+#include "src/tint/sem/variable.h"
TINT_INSTANTIATE_TYPEINFO(tint::sem::Statement);
TINT_INSTANTIATE_TYPEINFO(tint::sem::CompoundStatement);
@@ -43,4 +45,8 @@
CompoundStatement::~CompoundStatement() = default;
+void CompoundStatement::AddDecl(const sem::LocalVariable* var) {
+ decls_.Add(var->Declaration()->symbol, OrderedLocalVariable{decls_.Count(), var});
+}
+
} // namespace tint::sem
diff --git a/src/tint/sem/statement.h b/src/tint/sem/statement.h
index bdcb55c..09112d5 100644
--- a/src/tint/sem/statement.h
+++ b/src/tint/sem/statement.h
@@ -17,6 +17,8 @@
#include "src/tint/sem/behavior.h"
#include "src/tint/sem/node.h"
+#include "src/tint/symbol.h"
+#include "src/tint/utils/hashmap.h"
// Forward declarations
namespace tint::ast {
@@ -26,6 +28,7 @@
class BlockStatement;
class CompoundStatement;
class Function;
+class LocalVariable;
} // namespace tint::sem
namespace tint::sem {
@@ -128,6 +131,25 @@
/// Destructor
~CompoundStatement() override;
+
+ /// OrderedLocalVariable describes a local variable declaration, and order of declaration.
+ struct OrderedLocalVariable {
+ /// The 0-based declaration order index of the variable
+ size_t order;
+ /// The variable
+ const LocalVariable* variable;
+ };
+
+ /// @returns a map of variable name to variable declarations associated with this block
+ const utils::Hashmap<Symbol, OrderedLocalVariable, 4>& Decls() const { return decls_; }
+
+ /// Associates a declaration with this block.
+ /// @note this method must be called in variable declaration order
+ /// @param var a variable declaration to be added to the block
+ void AddDecl(const LocalVariable* var);
+
+ private:
+ utils::Hashmap<Symbol, OrderedLocalVariable, 4> decls_;
};
template <typename Pred>