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>
diff --git a/src/scope_stack.h b/src/scope_stack.h
index a114723..e266886 100644
--- a/src/scope_stack.h
+++ b/src/scope_stack.h
@@ -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 @@
   }
 
   /// 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 @@
   }
 
  private:
-  std::vector<std::unordered_map<std::string, T>> stack_;
+  std::vector<std::unordered_map<uint32_t, T>> stack_;
 };
 
 }  // namespace tint
diff --git a/src/scope_stack_test.cc b/src/scope_stack_test.cc
index b11c6f1..7e58c35 100644
--- a/src/scope_stack_test.cc
+++ b/src/scope_stack_test.cc
@@ -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 @@
 
 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);
 }
 
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index 86e8d2e..048120b 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -102,7 +102,7 @@
   }
 
   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 @@
 
   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 @@
     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::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()) {
diff --git a/src/type_determiner.h b/src/type_determiner.h
index 0b1157a..51f6801 100644
--- a/src/type_determiner.h
+++ b/src/type_determiner.h
@@ -89,7 +89,7 @@
   /// 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.
diff --git a/src/validator/validator.cc b/src/validator/validator.cc
index b40d1c3..07466d9 100644
--- a/src/validator/validator.cc
+++ b/src/validator/validator.cc
@@ -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;
 }
 
diff --git a/src/validator/validator.h b/src/validator/validator.h
index fe4467e..2180de6 100644
--- a/src/validator/validator.h
+++ b/src/validator/validator.h
@@ -27,8 +27,6 @@
 
 namespace tint {
 
-class ValidatorImpl;
-
 /// Determines if the module is complete and valid
 class Validator {
  public:
@@ -52,7 +50,6 @@
   const diag::List& diagnostics() const { return diags_; }
 
  private:
-  std::unique_ptr<ValidatorImpl> impl_;
   diag::List diags_;
 };
 
diff --git a/src/validator/validator_function_test.cc b/src/validator/validator_function_test.cc
index b4855fe..905d7b3 100644
--- a/src/validator/validator_function_test.cc
+++ b/src/validator/validator_function_test.cc
@@ -52,7 +52,7 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
 
   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 @@
 
   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 @@
 
   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 @@
   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 @@
   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");
diff --git a/src/validator/validator_impl.cc b/src/validator/validator_impl.cc
index a2a6637..ade7fca 100644
--- a/src/validator/validator_impl.cc
+++ b/src/validator/validator_impl.cc
@@ -37,7 +37,7 @@
 
 namespace tint {
 
-ValidatorImpl::ValidatorImpl() = default;
+ValidatorImpl::ValidatorImpl(const ast::Module* module) : module_(*module) {}
 
 ValidatorImpl::~ValidatorImpl() = default;
 
@@ -60,21 +60,18 @@
   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::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 @@
                 "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 @@
   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::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 @@
   }
 
   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 @@
 
   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::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;
diff --git a/src/validator/validator_impl.h b/src/validator/validator_impl.h
index 53a8edf..c0a8d2b 100644
--- a/src/validator/validator_impl.h
+++ b/src/validator/validator_impl.h
@@ -39,13 +39,13 @@
 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 @@
       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_;
diff --git a/src/validator/validator_test.cc b/src/validator/validator_test.cc
index 335ee5f..eacc3e3 100644
--- a/src/validator/validator_test.cc
+++ b/src/validator/validator_test.cc
@@ -217,7 +217,7 @@
                              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 @@
                                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 @@
                                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 @@
                     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 @@
   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 @@
 
   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 @@
 
   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 @@
   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) {
diff --git a/src/validator/validator_test_helper.cc b/src/validator/validator_test_helper.cc
index 656b6f6..eb0b903 100644
--- a/src/validator/validator_test_helper.cc
+++ b/src/validator/validator_test_helper.cc
@@ -20,7 +20,7 @@
 
 ValidatorTestHelper::ValidatorTestHelper() {
   td_ = std::make_unique<TypeDeterminer>(mod);
-  v_ = std::make_unique<ValidatorImpl>();
+  v_ = std::make_unique<ValidatorImpl>(mod);
 }
 
 ValidatorTestHelper::~ValidatorTestHelper() = default;
diff --git a/src/validator/validator_type_test.cc b/src/validator/validator_type_test.cc
index 2a3721c..91be119 100644
--- a/src/validator/validator_type_test.cc
+++ b/src/validator/validator_type_test.cc
@@ -160,7 +160,7 @@
   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 @@
   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");
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index f040181..193302a 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -205,7 +205,7 @@
 }
 
 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 @@
                                    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 @@
   // 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;
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index 4af9556..cf93d59 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -116,7 +116,7 @@
   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::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
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index ca93364..5423d60 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -458,8 +458,9 @@
     }
 
     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 @@
     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 @@
       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 @@
     }
   }
 
-  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 @@
     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 @@
     }
   }
 
-  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::GenerateIdentifierExpression(
     ast::IdentifierExpression* expr) {
   uint32_t val = 0;
-  if (scope_stack_.get(expr->name(), &val)) {
+  if (scope_stack_.get(expr->symbol(), &val)) {
     return val;
   }