Convert ScopeStack over to symbols.
This CL converts the ScopeStack to use a Symbol instead of a string as the accessor. Change-Id: I2893003bc119c86c4822732ef36c7393e4be1e79 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/36580 Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: dan sinclair <dsinclair@chromium.org> Auto-Submit: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
f51d965bef
commit
795b6b5a28
|
@ -14,10 +14,11 @@
|
|||
#ifndef SRC_SCOPE_STACK_H_
|
||||
#define SRC_SCOPE_STACK_H_
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "src/symbol.h"
|
||||
|
||||
namespace tint {
|
||||
|
||||
/// Used to store a stack of scope information.
|
||||
|
@ -45,38 +46,40 @@ class ScopeStack {
|
|||
}
|
||||
|
||||
/// Set a global variable in the stack
|
||||
/// @param name the name of the variable
|
||||
/// @param symbol the symbol of the variable
|
||||
/// @param val the value
|
||||
void set_global(const std::string& name, T val) { stack_[0][name] = val; }
|
||||
|
||||
/// Sets variable into the top most scope of the stack
|
||||
/// @param name the name of the variable
|
||||
/// @param val the value
|
||||
void set(const std::string& name, T val) { stack_.back()[name] = val; }
|
||||
|
||||
/// Checks for the given `name` in the stack
|
||||
/// @param name the name to look for
|
||||
/// @returns true if the stack contains `name`
|
||||
bool has(const std::string& name) const { return get(name, nullptr); }
|
||||
|
||||
/// Retrieves a given name from the stack
|
||||
/// @param name the name to look for
|
||||
/// @param ret where to place the name
|
||||
/// @returns true if the name was successfully found, false otherwise
|
||||
bool get(const std::string& name, T* ret) const {
|
||||
return get(name, ret, nullptr);
|
||||
void set_global(const Symbol& symbol, T val) {
|
||||
stack_[0][symbol.value()] = val;
|
||||
}
|
||||
|
||||
/// Retrieves a given name from the stack
|
||||
/// @param name the name to look for
|
||||
/// @param ret where to place the name
|
||||
/// @param is_global set true if the name references a global variable
|
||||
/// Sets variable into the top most scope of the stack
|
||||
/// @param symbol the symbol of the variable
|
||||
/// @param val the value
|
||||
void set(const Symbol& symbol, T val) { stack_.back()[symbol.value()] = val; }
|
||||
|
||||
/// Checks for the given `symbol` in the stack
|
||||
/// @param symbol the symbol to look for
|
||||
/// @returns true if the stack contains `symbol`
|
||||
bool has(const Symbol& symbol) const { return get(symbol, nullptr); }
|
||||
|
||||
/// Retrieves a given variable from the stack
|
||||
/// @param symbol the symbol to look for
|
||||
/// @param ret where to place the value
|
||||
/// @returns true if the symbol was successfully found, false otherwise
|
||||
bool get(const Symbol& symbol, T* ret) const {
|
||||
return get(symbol, ret, nullptr);
|
||||
}
|
||||
|
||||
/// Retrieves a given variable from the stack
|
||||
/// @param symbol the symbol to look for
|
||||
/// @param ret where to place the value
|
||||
/// @param is_global set true if the symbol references a global variable
|
||||
/// otherwise unchanged
|
||||
/// @returns true if the name was successfully found, false otherwise
|
||||
bool get(const std::string& name, T* ret, bool* is_global) const {
|
||||
/// @returns true if the symbol was successfully found, false otherwise
|
||||
bool get(const Symbol& symbol, T* ret, bool* is_global) const {
|
||||
for (auto iter = stack_.rbegin(); iter != stack_.rend(); ++iter) {
|
||||
auto& map = *iter;
|
||||
auto val = map.find(name);
|
||||
auto val = map.find(symbol.value());
|
||||
|
||||
if (val != map.end()) {
|
||||
if (ret) {
|
||||
|
@ -92,7 +95,7 @@ class ScopeStack {
|
|||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unordered_map<std::string, T>> stack_;
|
||||
std::vector<std::unordered_map<uint32_t, T>> stack_;
|
||||
};
|
||||
|
||||
} // namespace tint
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "src/ast/builder.h"
|
||||
#include "src/ast/type/f32_type.h"
|
||||
#include "src/ast/variable.h"
|
||||
#include "src/symbol.h"
|
||||
|
||||
namespace tint {
|
||||
namespace {
|
||||
|
@ -25,68 +26,75 @@ class ScopeStackTest : public ast::BuilderWithModule, public testing::Test {};
|
|||
|
||||
TEST_F(ScopeStackTest, Global) {
|
||||
ScopeStack<uint32_t> s;
|
||||
s.set_global("var", 5);
|
||||
Symbol sym(1);
|
||||
s.set_global(sym, 5);
|
||||
|
||||
uint32_t val = 0;
|
||||
EXPECT_TRUE(s.get("var", &val));
|
||||
EXPECT_TRUE(s.get(sym, &val));
|
||||
EXPECT_EQ(val, 5u);
|
||||
}
|
||||
|
||||
TEST_F(ScopeStackTest, Global_SetWithPointer) {
|
||||
auto* v = Var("my_var", ast::StorageClass::kNone, ty.f32);
|
||||
ScopeStack<ast::Variable*> s;
|
||||
s.set_global("var", v);
|
||||
s.set_global(v->symbol(), v);
|
||||
|
||||
ast::Variable* v2 = nullptr;
|
||||
EXPECT_TRUE(s.get("var", &v2));
|
||||
EXPECT_EQ(v2->name(), "my_var");
|
||||
EXPECT_TRUE(s.get(v->symbol(), &v2));
|
||||
EXPECT_EQ(v2->symbol(), v->symbol());
|
||||
}
|
||||
|
||||
TEST_F(ScopeStackTest, Global_CanNotPop) {
|
||||
ScopeStack<uint32_t> s;
|
||||
s.set_global("var", 5);
|
||||
Symbol sym(1);
|
||||
s.set_global(sym, 5);
|
||||
s.pop_scope();
|
||||
|
||||
uint32_t val = 0;
|
||||
EXPECT_TRUE(s.get("var", &val));
|
||||
EXPECT_TRUE(s.get(sym, &val));
|
||||
EXPECT_EQ(val, 5u);
|
||||
}
|
||||
|
||||
TEST_F(ScopeStackTest, Scope) {
|
||||
ScopeStack<uint32_t> s;
|
||||
Symbol sym(1);
|
||||
s.push_scope();
|
||||
s.set("var", 5);
|
||||
s.set(sym, 5);
|
||||
|
||||
uint32_t val = 0;
|
||||
EXPECT_TRUE(s.get("var", &val));
|
||||
EXPECT_TRUE(s.get(sym, &val));
|
||||
EXPECT_EQ(val, 5u);
|
||||
}
|
||||
|
||||
TEST_F(ScopeStackTest, Get_MissingName) {
|
||||
TEST_F(ScopeStackTest, Get_MissingSymbol) {
|
||||
ScopeStack<uint32_t> s;
|
||||
Symbol sym(1);
|
||||
uint32_t ret = 0;
|
||||
EXPECT_FALSE(s.get("val", &ret));
|
||||
EXPECT_FALSE(s.get(sym, &ret));
|
||||
EXPECT_EQ(ret, 0u);
|
||||
}
|
||||
|
||||
TEST_F(ScopeStackTest, Has) {
|
||||
ScopeStack<uint32_t> s;
|
||||
s.set_global("var2", 3);
|
||||
Symbol sym(1);
|
||||
Symbol sym2(2);
|
||||
s.set_global(sym2, 3);
|
||||
s.push_scope();
|
||||
s.set("var", 5);
|
||||
s.set(sym, 5);
|
||||
|
||||
EXPECT_TRUE(s.has("var"));
|
||||
EXPECT_TRUE(s.has("var2"));
|
||||
EXPECT_TRUE(s.has(sym));
|
||||
EXPECT_TRUE(s.has(sym2));
|
||||
}
|
||||
|
||||
TEST_F(ScopeStackTest, ReturnsScopeBeforeGlobalFirst) {
|
||||
ScopeStack<uint32_t> s;
|
||||
s.set_global("var", 3);
|
||||
Symbol sym(1);
|
||||
s.set_global(sym, 3);
|
||||
s.push_scope();
|
||||
s.set("var", 5);
|
||||
s.set(sym, 5);
|
||||
|
||||
uint32_t ret;
|
||||
EXPECT_TRUE(s.get("var", &ret));
|
||||
EXPECT_TRUE(s.get(sym, &ret));
|
||||
EXPECT_EQ(ret, 5u);
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ bool TypeDeterminer::Determine() {
|
|||
}
|
||||
|
||||
for (auto* var : mod_->global_variables()) {
|
||||
variable_stack_.set_global(var->name(), var);
|
||||
variable_stack_.set_global(var->symbol(), var);
|
||||
|
||||
if (var->has_constructor()) {
|
||||
if (!DetermineResultType(var->constructor())) {
|
||||
|
@ -154,7 +154,7 @@ bool TypeDeterminer::DetermineFunction(ast::Function* func) {
|
|||
|
||||
variable_stack_.push_scope();
|
||||
for (auto* param : func->params()) {
|
||||
variable_stack_.set(param->name(), param);
|
||||
variable_stack_.set(param->symbol(), param);
|
||||
}
|
||||
|
||||
if (!DetermineStatements(func->body())) {
|
||||
|
@ -267,7 +267,7 @@ bool TypeDeterminer::DetermineResultType(ast::Statement* stmt) {
|
|||
return true;
|
||||
}
|
||||
if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
|
||||
variable_stack_.set(v->variable()->name(), v->variable());
|
||||
variable_stack_.set(v->variable()->symbol(), v->variable());
|
||||
return DetermineResultType(v->variable()->constructor());
|
||||
}
|
||||
|
||||
|
@ -859,8 +859,9 @@ bool TypeDeterminer::DetermineConstructor(ast::ConstructorExpression* expr) {
|
|||
|
||||
bool TypeDeterminer::DetermineIdentifier(ast::IdentifierExpression* expr) {
|
||||
auto name = expr->name();
|
||||
auto symbol = expr->symbol();
|
||||
ast::Variable* var;
|
||||
if (variable_stack_.get(name, &var)) {
|
||||
if (variable_stack_.get(symbol, &var)) {
|
||||
// A constant is the type, but a variable is always a pointer so synthesize
|
||||
// the pointer around the variable type.
|
||||
if (var->is_const()) {
|
||||
|
|
|
@ -89,7 +89,7 @@ class TypeDeterminer {
|
|||
/// Testing method to set a given variable into the type stack
|
||||
/// @param var the variable to set
|
||||
void RegisterVariableForTesting(ast::Variable* var) {
|
||||
variable_stack_.set(var->name(), var);
|
||||
variable_stack_.set(var->symbol(), var);
|
||||
}
|
||||
|
||||
/// Retrieves information for the requested import.
|
||||
|
|
|
@ -18,15 +18,14 @@
|
|||
|
||||
namespace tint {
|
||||
|
||||
Validator::Validator() : impl_(std::make_unique<tint::ValidatorImpl>()) {}
|
||||
Validator::Validator() = default;
|
||||
|
||||
Validator::~Validator() = default;
|
||||
|
||||
bool Validator::Validate(const ast::Module* module) {
|
||||
bool ret = impl_->Validate(module);
|
||||
|
||||
diags_ = impl_->diagnostics();
|
||||
|
||||
ValidatorImpl impl(module);
|
||||
bool ret = impl.Validate();
|
||||
diags_ = impl.diagnostics();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
namespace tint {
|
||||
|
||||
class ValidatorImpl;
|
||||
|
||||
/// Determines if the module is complete and valid
|
||||
class Validator {
|
||||
public:
|
||||
|
@ -52,7 +50,6 @@ class Validator {
|
|||
const diag::List& diagnostics() const { return diags_; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<ValidatorImpl> impl_;
|
||||
diag::List diags_;
|
||||
};
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ TEST_F(ValidateFunctionTest, VoidFunctionEndWithoutReturnStatement_Pass) {
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_TRUE(v()->Validate(mod));
|
||||
EXPECT_TRUE(v()->Validate());
|
||||
}
|
||||
|
||||
TEST_F(ValidateFunctionTest,
|
||||
|
@ -68,7 +68,7 @@ TEST_F(ValidateFunctionTest,
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_TRUE(v()->Validate(mod));
|
||||
EXPECT_TRUE(v()->Validate());
|
||||
}
|
||||
|
||||
TEST_F(ValidateFunctionTest, FunctionEndWithoutReturnStatement_Fail) {
|
||||
|
@ -86,7 +86,7 @@ TEST_F(ValidateFunctionTest, FunctionEndWithoutReturnStatement_Fail) {
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(),
|
||||
"12:34 v-0002: non-void function must end with a return statement");
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ TEST_F(ValidateFunctionTest, FunctionEndWithoutReturnStatementEmptyBody_Fail) {
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(),
|
||||
"12:34 v-0002: non-void function must end with a return statement");
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ TEST_F(ValidateFunctionTest, FunctionTypeMustMatchReturnStatementType_fail) {
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
// TODO(sarahM0): replace 000y with a rule number
|
||||
EXPECT_EQ(v()->error(),
|
||||
"12:34 v-000y: return statement type must match its function "
|
||||
|
@ -150,7 +150,7 @@ TEST_F(ValidateFunctionTest, FunctionTypeMustMatchReturnStatementTypeF32_fail) {
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
// TODO(sarahM0): replace 000y with a rule number
|
||||
EXPECT_EQ(v()->error(),
|
||||
"12:34 v-000y: return statement type must match its function "
|
||||
|
@ -177,7 +177,7 @@ TEST_F(ValidateFunctionTest, FunctionNamesMustBeUnique_fail) {
|
|||
mod->AddFunction(func_copy);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(), "12:34 v-0016: function names must be unique 'func'");
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ TEST_F(ValidateFunctionTest, RecursionIsNotAllowed_Fail) {
|
|||
mod->AddFunction(func0);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod)) << v()->error();
|
||||
EXPECT_FALSE(v()->Validate()) << v()->error();
|
||||
EXPECT_EQ(v()->error(), "12:34 v-0004: recursion is not allowed: 'func'");
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ TEST_F(ValidateFunctionTest, RecursionIsNotAllowedExpr_Fail) {
|
|||
mod->AddFunction(func0);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod)) << v()->error();
|
||||
EXPECT_FALSE(v()->Validate()) << v()->error();
|
||||
EXPECT_EQ(v()->error(), "12:34 v-0004: recursion is not allowed: 'func'");
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ TEST_F(ValidateFunctionTest, Function_WithPipelineStage_NotVoid_Fail) {
|
|||
|
||||
mod->AddFunction(func);
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(),
|
||||
"12:34 v-0024: Entry point function must return void: 'vtx_main'");
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ TEST_F(ValidateFunctionTest, Function_WithPipelineStage_WithParams_Fail) {
|
|||
|
||||
mod->AddFunction(func);
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(),
|
||||
"12:34 v-0023: Entry point function must accept no parameters: "
|
||||
"'vtx_func'");
|
||||
|
@ -279,7 +279,7 @@ TEST_F(ValidateFunctionTest, PipelineStage_MustBeUnique_Fail) {
|
|||
|
||||
mod->AddFunction(func);
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(
|
||||
v()->error(),
|
||||
"12:34 v-0020: only one stage decoration permitted per entry point");
|
||||
|
@ -299,7 +299,7 @@ TEST_F(ValidateFunctionTest, OnePipelineStageFunctionMustBePresent_Pass) {
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_TRUE(v()->Validate(mod)) << v()->error();
|
||||
EXPECT_TRUE(v()->Validate()) << v()->error();
|
||||
}
|
||||
|
||||
TEST_F(ValidateFunctionTest, OnePipelineStageFunctionMustBePresent_Fail) {
|
||||
|
@ -312,7 +312,7 @@ TEST_F(ValidateFunctionTest, OnePipelineStageFunctionMustBePresent_Fail) {
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(),
|
||||
"v-0003: At least one of vertex, fragment or compute shader must "
|
||||
"be present");
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
namespace tint {
|
||||
|
||||
ValidatorImpl::ValidatorImpl() = default;
|
||||
ValidatorImpl::ValidatorImpl(const ast::Module* module) : module_(*module) {}
|
||||
|
||||
ValidatorImpl::~ValidatorImpl() = default;
|
||||
|
||||
|
@ -60,21 +60,18 @@ void ValidatorImpl::add_error(const Source& src, const std::string& msg) {
|
|||
diags_.add(std::move(diag));
|
||||
}
|
||||
|
||||
bool ValidatorImpl::Validate(const ast::Module* module) {
|
||||
if (!module) {
|
||||
return false;
|
||||
}
|
||||
bool ValidatorImpl::Validate() {
|
||||
function_stack_.push_scope();
|
||||
if (!ValidateGlobalVariables(module->global_variables())) {
|
||||
if (!ValidateGlobalVariables(module_.global_variables())) {
|
||||
return false;
|
||||
}
|
||||
if (!ValidateConstructedTypes(module->constructed_types())) {
|
||||
if (!ValidateConstructedTypes(module_.constructed_types())) {
|
||||
return false;
|
||||
}
|
||||
if (!ValidateFunctions(module->functions())) {
|
||||
if (!ValidateFunctions(module_.functions())) {
|
||||
return false;
|
||||
}
|
||||
if (!ValidateEntryPoint(module->functions())) {
|
||||
if (!ValidateEntryPoint(module_.functions())) {
|
||||
return false;
|
||||
}
|
||||
function_stack_.pop_scope();
|
||||
|
@ -113,9 +110,10 @@ bool ValidatorImpl::ValidateConstructedTypes(
|
|||
bool ValidatorImpl::ValidateGlobalVariables(
|
||||
const ast::VariableList& global_vars) {
|
||||
for (auto* var : global_vars) {
|
||||
if (variable_stack_.has(var->name())) {
|
||||
if (variable_stack_.has(var->symbol())) {
|
||||
add_error(var->source(), "v-0011",
|
||||
"redeclared global identifier '" + var->name() + "'");
|
||||
"redeclared global identifier '" +
|
||||
module_.SymbolToName(var->symbol()) + "'");
|
||||
return false;
|
||||
}
|
||||
if (!var->is_const() && var->storage_class() == ast::StorageClass::kNone) {
|
||||
|
@ -129,20 +127,21 @@ bool ValidatorImpl::ValidateGlobalVariables(
|
|||
"global constants shouldn't have a storage class");
|
||||
return false;
|
||||
}
|
||||
variable_stack_.set_global(var->name(), var);
|
||||
variable_stack_.set_global(var->symbol(), var);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValidatorImpl::ValidateFunctions(const ast::FunctionList& funcs) {
|
||||
for (auto* func : funcs) {
|
||||
if (function_stack_.has(func->name())) {
|
||||
if (function_stack_.has(func->symbol())) {
|
||||
add_error(func->source(), "v-0016",
|
||||
"function names must be unique '" + func->name() + "'");
|
||||
"function names must be unique '" +
|
||||
module_.SymbolToName(func->symbol()) + "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
function_stack_.set(func->name(), func);
|
||||
function_stack_.set(func->symbol(), func);
|
||||
current_function_ = func;
|
||||
if (!ValidateFunction(func)) {
|
||||
return false;
|
||||
|
@ -197,7 +196,7 @@ bool ValidatorImpl::ValidateFunction(const ast::Function* func) {
|
|||
variable_stack_.push_scope();
|
||||
|
||||
for (auto* param : func->params()) {
|
||||
variable_stack_.set(param->name(), param);
|
||||
variable_stack_.set(param->symbol(), param);
|
||||
if (!ValidateParameter(param)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -265,18 +264,18 @@ bool ValidatorImpl::ValidateStatements(const ast::BlockStatement* block) {
|
|||
|
||||
bool ValidatorImpl::ValidateDeclStatement(
|
||||
const ast::VariableDeclStatement* decl) {
|
||||
auto name = decl->variable()->name();
|
||||
auto symbol = decl->variable()->symbol();
|
||||
bool is_global = false;
|
||||
if (variable_stack_.get(name, nullptr, &is_global)) {
|
||||
if (variable_stack_.get(symbol, nullptr, &is_global)) {
|
||||
const char* error_code = "v-0014";
|
||||
if (is_global) {
|
||||
error_code = "v-0013";
|
||||
}
|
||||
add_error(decl->source(), error_code,
|
||||
"redeclared identifier '" + name + "'");
|
||||
"redeclared identifier '" + module_.SymbolToName(symbol) + "'");
|
||||
return false;
|
||||
}
|
||||
variable_stack_.set(name, decl->variable());
|
||||
variable_stack_.set(symbol, decl->variable());
|
||||
if (auto* arr =
|
||||
decl->variable()->type()->UnwrapAll()->As<ast::type::Array>()) {
|
||||
if (arr->IsRuntimeArray()) {
|
||||
|
@ -403,18 +402,20 @@ bool ValidatorImpl::ValidateCallExpr(const ast::CallExpression* expr) {
|
|||
}
|
||||
|
||||
if (auto* ident = expr->func()->As<ast::IdentifierExpression>()) {
|
||||
auto func_name = ident->name();
|
||||
if (ident->IsIntrinsic()) {
|
||||
// TODO(sarahM0): validate intrinsics - tied with type-determiner
|
||||
} else {
|
||||
if (!function_stack_.has(func_name)) {
|
||||
auto symbol = ident->symbol();
|
||||
if (!function_stack_.has(symbol)) {
|
||||
add_error(expr->source(), "v-0005",
|
||||
"function must be declared before use: '" + func_name + "'");
|
||||
"function must be declared before use: '" +
|
||||
module_.SymbolToName(symbol) + "'");
|
||||
return false;
|
||||
}
|
||||
if (func_name == current_function_->name()) {
|
||||
add_error(expr->source(), "v-0004",
|
||||
"recursion is not allowed: '" + func_name + "'");
|
||||
if (symbol == current_function_->symbol()) {
|
||||
add_error(
|
||||
expr->source(), "v-0004",
|
||||
"recursion is not allowed: '" + module_.SymbolToName(symbol) + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -450,10 +451,11 @@ bool ValidatorImpl::ValidateConstant(const ast::AssignmentStatement* assign) {
|
|||
|
||||
if (auto* ident = assign->lhs()->As<ast::IdentifierExpression>()) {
|
||||
ast::Variable* var;
|
||||
if (variable_stack_.get(ident->name(), &var)) {
|
||||
if (variable_stack_.get(ident->symbol(), &var)) {
|
||||
if (var->is_const()) {
|
||||
add_error(assign->source(), "v-0021",
|
||||
"cannot re-assign a constant: '" + ident->name() + "'");
|
||||
"cannot re-assign a constant: '" +
|
||||
module_.SymbolToName(ident->symbol()) + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -495,9 +497,10 @@ bool ValidatorImpl::ValidateExpression(const ast::Expression* expr) {
|
|||
|
||||
bool ValidatorImpl::ValidateIdentifier(const ast::IdentifierExpression* ident) {
|
||||
ast::Variable* var;
|
||||
if (!variable_stack_.get(ident->name(), &var)) {
|
||||
add_error(ident->source(), "v-0006",
|
||||
"'" + ident->name() + "' is not declared");
|
||||
if (!variable_stack_.get(ident->symbol(), &var)) {
|
||||
add_error(
|
||||
ident->source(), "v-0006",
|
||||
"'" + module_.SymbolToName(ident->symbol()) + "' is not declared");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -39,13 +39,13 @@ namespace tint {
|
|||
class ValidatorImpl {
|
||||
public:
|
||||
/// Constructor
|
||||
ValidatorImpl();
|
||||
/// @param module the module to validate
|
||||
explicit ValidatorImpl(const ast::Module* module);
|
||||
~ValidatorImpl();
|
||||
|
||||
/// Runs the validator
|
||||
/// @param module the module to validate
|
||||
/// @returns true if the validation was successful
|
||||
bool Validate(const ast::Module* module);
|
||||
bool Validate();
|
||||
|
||||
/// @returns the diagnostic messages
|
||||
const diag::List& diagnostics() const { return diags_; }
|
||||
|
@ -148,6 +148,7 @@ class ValidatorImpl {
|
|||
const std::vector<ast::type::Type*>& constructed_types);
|
||||
|
||||
private:
|
||||
const ast::Module& module_;
|
||||
diag::List diags_;
|
||||
ScopeStack<ast::Variable*> variable_stack_;
|
||||
ScopeStack<ast::Function*> function_stack_;
|
||||
|
|
|
@ -217,7 +217,7 @@ TEST_F(ValidatorTest, GlobalVariableNoStorageClass_Fail) {
|
|||
ast::StorageClass::kNone, ty.f32, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(),
|
||||
"12:34 v-0022: global variables must have a storage class");
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ TEST_F(ValidatorTest, GlobalConstantWithStorageClass_Fail) {
|
|||
ast::StorageClass::kInput, ty.f32, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(
|
||||
v()->error(),
|
||||
"12:34 v-global01: global constants shouldn't have a storage class");
|
||||
|
@ -240,7 +240,7 @@ TEST_F(ValidatorTest, GlobalConstNoStorageClass_Pass) {
|
|||
ast::StorageClass::kNone, ty.f32, nullptr,
|
||||
ast::VariableDecorationList{}));
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod)) << v()->error();
|
||||
EXPECT_FALSE(v()->Validate()) << v()->error();
|
||||
}
|
||||
|
||||
TEST_F(ValidatorTest, UsingUndefinedVariableGlobalVariable_Fail) {
|
||||
|
@ -263,7 +263,7 @@ TEST_F(ValidatorTest, UsingUndefinedVariableGlobalVariable_Fail) {
|
|||
ast::FunctionDecorationList{});
|
||||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(), "12:34 v-0006: 'not_global_var' is not declared");
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,7 @@ TEST_F(ValidatorTest, UsingUndefinedVariableGlobalVariable_Pass) {
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_TRUE(v()->Validate(mod)) << v()->error();
|
||||
EXPECT_TRUE(v()->Validate()) << v()->error();
|
||||
}
|
||||
|
||||
TEST_F(ValidatorTest, UsingUndefinedVariableInnerScope_Fail) {
|
||||
|
@ -435,7 +435,7 @@ TEST_F(ValidatorTest, GlobalVariableFunctionVariableNotUnique_Fail) {
|
|||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_TRUE(td()->DetermineFunction(func)) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod)) << v()->error();
|
||||
EXPECT_FALSE(v()->Validate()) << v()->error();
|
||||
EXPECT_EQ(v()->error(), "12:34 v-0013: redeclared identifier 'a'");
|
||||
}
|
||||
|
||||
|
@ -462,7 +462,7 @@ TEST_F(ValidatorTest, RedeclaredIndentifier_Fail) {
|
|||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_TRUE(td()->DetermineFunction(func)) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(), "12:34 v-0014: redeclared identifier 'a'");
|
||||
}
|
||||
|
||||
|
@ -552,7 +552,7 @@ TEST_F(ValidatorTest, RedeclaredIdentifierDifferentFunctions_Pass) {
|
|||
mod->AddFunction(func1);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_TRUE(v()->Validate(mod)) << v()->error();
|
||||
EXPECT_TRUE(v()->Validate()) << v()->error();
|
||||
}
|
||||
|
||||
TEST_F(ValidatorTest, VariableDeclNoConstructor_Pass) {
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace tint {
|
|||
|
||||
ValidatorTestHelper::ValidatorTestHelper() {
|
||||
td_ = std::make_unique<TypeDeterminer>(mod);
|
||||
v_ = std::make_unique<ValidatorImpl>();
|
||||
v_ = std::make_unique<ValidatorImpl>(mod);
|
||||
}
|
||||
|
||||
ValidatorTestHelper::~ValidatorTestHelper() = default;
|
||||
|
|
|
@ -160,7 +160,7 @@ TEST_F(ValidatorTypeTest, RuntimeArrayInFunction_Fail) {
|
|||
mod->AddFunction(func);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(),
|
||||
"12:34 v-0015: runtime arrays may only appear as the last member "
|
||||
"of a struct");
|
||||
|
@ -192,7 +192,7 @@ TEST_F(ValidatorTypeTest, RuntimeArrayAsParameter_Fail) {
|
|||
mod->AddFunction(main);
|
||||
|
||||
EXPECT_TRUE(td()->Determine()) << td()->error();
|
||||
EXPECT_FALSE(v()->Validate(mod));
|
||||
EXPECT_FALSE(v()->Validate());
|
||||
EXPECT_EQ(v()->error(),
|
||||
"12:34 v-0015: runtime arrays may only appear as the last member "
|
||||
"of a struct");
|
||||
|
|
|
@ -205,7 +205,7 @@ bool GeneratorImpl::Generate(std::ostream& out) {
|
|||
}
|
||||
|
||||
void GeneratorImpl::register_global(ast::Variable* global) {
|
||||
global_variables_.set(global->name(), global);
|
||||
global_variables_.set(global->symbol(), global);
|
||||
}
|
||||
|
||||
std::string GeneratorImpl::generate_name(const std::string& prefix) {
|
||||
|
@ -1077,7 +1077,7 @@ bool GeneratorImpl::EmitIdentifier(std::ostream&,
|
|||
ast::IdentifierExpression* expr) {
|
||||
auto* ident = expr->As<ast::IdentifierExpression>();
|
||||
ast::Variable* var = nullptr;
|
||||
if (global_variables_.get(ident->name(), &var)) {
|
||||
if (global_variables_.get(ident->symbol(), &var)) {
|
||||
if (global_is_in_struct(var)) {
|
||||
auto var_type = var->storage_class() == ast::StorageClass::kInput
|
||||
? VarType::kIn
|
||||
|
@ -1964,7 +1964,7 @@ bool GeneratorImpl::is_storage_buffer_access(
|
|||
// Check if this is a storage buffer variable
|
||||
if (auto* ident = expr->structure()->As<ast::IdentifierExpression>()) {
|
||||
ast::Variable* var = nullptr;
|
||||
if (!global_variables_.get(ident->name(), &var)) {
|
||||
if (!global_variables_.get(ident->symbol(), &var)) {
|
||||
return false;
|
||||
}
|
||||
return var->storage_class() == ast::StorageClass::kStorageBuffer;
|
||||
|
|
|
@ -116,7 +116,7 @@ bool GeneratorImpl::Generate() {
|
|||
out_ << "#include <metal_stdlib>" << std::endl << std::endl;
|
||||
|
||||
for (auto* global : module_->global_variables()) {
|
||||
global_variables_.set(global->name(), global);
|
||||
global_variables_.set(global->symbol(), global);
|
||||
}
|
||||
|
||||
for (auto* const ty : module_->constructed_types()) {
|
||||
|
@ -1528,7 +1528,7 @@ bool GeneratorImpl::global_is_in_struct(ast::Variable* var) const {
|
|||
bool GeneratorImpl::EmitIdentifier(ast::IdentifierExpression* expr) {
|
||||
auto* ident = expr->As<ast::IdentifierExpression>();
|
||||
ast::Variable* var = nullptr;
|
||||
if (global_variables_.get(ident->name(), &var)) {
|
||||
if (global_variables_.get(ident->symbol(), &var)) {
|
||||
if (global_is_in_struct(var)) {
|
||||
auto var_type = var->storage_class() == ast::StorageClass::kInput
|
||||
? VarType::kIn
|
||||
|
|
|
@ -458,8 +458,9 @@ bool Builder::GenerateEntryPoint(ast::Function* func, uint32_t id) {
|
|||
}
|
||||
|
||||
uint32_t var_id;
|
||||
if (!scope_stack_.get(var->name(), &var_id)) {
|
||||
error_ = "unable to find ID for global variable: " + var->name();
|
||||
if (!scope_stack_.get(var->symbol(), &var_id)) {
|
||||
error_ = "unable to find ID for global variable: " +
|
||||
mod_->SymbolToName(var->symbol());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -567,7 +568,7 @@ bool Builder::GenerateFunction(ast::Function* func) {
|
|||
params.push_back(Instruction{spv::Op::OpFunctionParameter,
|
||||
{Operand::Int(param_type_id), param_op}});
|
||||
|
||||
scope_stack_.set(param->name(), param_id);
|
||||
scope_stack_.set(param->symbol(), param_id);
|
||||
}
|
||||
|
||||
push_function(Function{definition_inst, result_op(), std::move(params)});
|
||||
|
@ -639,7 +640,7 @@ bool Builder::GenerateFunctionVariable(ast::Variable* var) {
|
|||
error_ = "missing constructor for constant";
|
||||
return false;
|
||||
}
|
||||
scope_stack_.set(var->name(), init_id);
|
||||
scope_stack_.set(var->symbol(), init_id);
|
||||
spirv_id_to_variable_[init_id] = var;
|
||||
return true;
|
||||
}
|
||||
|
@ -673,7 +674,7 @@ bool Builder::GenerateFunctionVariable(ast::Variable* var) {
|
|||
}
|
||||
}
|
||||
|
||||
scope_stack_.set(var->name(), var_id);
|
||||
scope_stack_.set(var->symbol(), var_id);
|
||||
spirv_id_to_variable_[var_id] = var;
|
||||
|
||||
return true;
|
||||
|
@ -707,7 +708,7 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) {
|
|||
push_debug(spv::Op::OpName,
|
||||
{Operand::Int(init_id), Operand::String(var->name())});
|
||||
|
||||
scope_stack_.set_global(var->name(), init_id);
|
||||
scope_stack_.set_global(var->symbol(), init_id);
|
||||
spirv_id_to_variable_[init_id] = var;
|
||||
return true;
|
||||
}
|
||||
|
@ -820,7 +821,7 @@ bool Builder::GenerateGlobalVariable(ast::Variable* var) {
|
|||
}
|
||||
}
|
||||
|
||||
scope_stack_.set_global(var->name(), var_id);
|
||||
scope_stack_.set_global(var->symbol(), var_id);
|
||||
spirv_id_to_variable_[var_id] = var;
|
||||
return true;
|
||||
}
|
||||
|
@ -1108,7 +1109,7 @@ uint32_t Builder::GenerateAccessorExpression(ast::Expression* expr) {
|
|||
uint32_t Builder::GenerateIdentifierExpression(
|
||||
ast::IdentifierExpression* expr) {
|
||||
uint32_t val = 0;
|
||||
if (scope_stack_.get(expr->name(), &val)) {
|
||||
if (scope_stack_.get(expr->symbol(), &val)) {
|
||||
return val;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue