Add builtin information to Symbol.

This CL extends the Symbol class to store if the content of the symbol could parse as a builtin.

Change-Id: I7e14ad944c1c9c43d900f9ccf8be6539ac9ea667
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/127460
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/docs/tint/layering.md b/docs/tint/layering.md
index 3e3c8f6..587febc 100644
--- a/docs/tint/layering.md
+++ b/docs/tint/layering.md
@@ -50,11 +50,6 @@
 |               Types                     |      |
 +-----------------------------------------+      |
                   |                              |
-                  V                              |
-+-----------------------------------------+      |
-|              Builtin                    |      |
-+-----------------------------------------+      |
-                  |                              |
                   |------------------------------+
                   V
 +-----------------------------------------+
@@ -62,6 +57,11 @@
 +-----------------------------------------+
                   |
                   V
++-----------------------------------------+
+|              Builtin                    |
++-----------------------------------------+
+                  |
+                  V
 +-----------------------------------------+ +-------------+
 |               Utils                     | | Initializer |
 +-----------------------------------------+ +-------------+
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 66d97a4..492e355 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -206,7 +206,10 @@
     "symbol_table.cc",
     "symbol_table.h",
   ]
-  deps = [ ":libtint_utils_src" ]
+  deps = [
+    ":libtint_builtins_src",
+    ":libtint_utils_src",
+  ]
 }
 
 libtint_source_set("libtint_utils_src") {
diff --git a/src/tint/builtin/function.cc b/src/tint/builtin/function.cc
index 88e86b6..332e9d1 100644
--- a/src/tint/builtin/function.cc
+++ b/src/tint/builtin/function.cc
@@ -24,7 +24,7 @@
 
 namespace tint::builtin {
 
-Function ParseFunction(const std::string& name) {
+Function ParseFunction(std::string_view name) {
     if (name == "abs") {
         return Function::kAbs;
     }
diff --git a/src/tint/builtin/function.cc.tmpl b/src/tint/builtin/function.cc.tmpl
index e2729dc..7912482 100644
--- a/src/tint/builtin/function.cc.tmpl
+++ b/src/tint/builtin/function.cc.tmpl
@@ -15,7 +15,7 @@
 
 namespace tint::builtin {
 
-Function ParseFunction(const std::string& name) {
+Function ParseFunction(std::string_view name) {
 {{- range Sem.Builtins  }}
     if (name == "{{.Name}}") {
         return Function::k{{PascalCase .Name}};
diff --git a/src/tint/builtin/function.h b/src/tint/builtin/function.h
index 3ccb341..046e87a 100644
--- a/src/tint/builtin/function.h
+++ b/src/tint/builtin/function.h
@@ -153,7 +153,7 @@
 /// @param name the builtin name to parse
 /// @returns the parsed Function, or Function::kNone if `name` did not
 /// match any builtin function.
-Function ParseFunction(const std::string& name);
+Function ParseFunction(std::string_view name);
 
 /// @returns the name of the builtin function type. The spelling, including
 /// case, matches the name in the WGSL spec.
diff --git a/src/tint/builtin/function.h.tmpl b/src/tint/builtin/function.h.tmpl
index d9109bf..02f9acb 100644
--- a/src/tint/builtin/function.h.tmpl
+++ b/src/tint/builtin/function.h.tmpl
@@ -33,7 +33,7 @@
 /// @param name the builtin name to parse
 /// @returns the parsed Function, or Function::kNone if `name` did not
 /// match any builtin function.
-Function ParseFunction(const std::string& name);
+Function ParseFunction(std::string_view name);
 
 /// @returns the name of the builtin function type. The spelling, including
 /// case, matches the name in the WGSL spec.
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index ec6bda7..5ba9ee2 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -436,48 +436,44 @@
     void AddDependency(const ast::Identifier* from, Symbol to) {
         auto* resolved = scope_stack_.Get(to);
         if (!resolved) {
-            auto s = to.Name();
-            if (auto builtin_fn = builtin::ParseFunction(s);
-                builtin_fn != builtin::Function::kNone) {
-                graph_.resolved_identifiers.Add(from, ResolvedIdentifier(builtin_fn));
-                return;
+            switch (to.Type()) {
+                case Symbol::BuiltinType::kNone:
+                    graph_.resolved_identifiers.Add(from, UnresolvedIdentifier{to.Name()});
+                    break;
+                case Symbol::BuiltinType::kFunction:
+                    graph_.resolved_identifiers.Add(
+                        from, ResolvedIdentifier(to.BuiltinValue<builtin::Function>()));
+                    break;
+                case Symbol::BuiltinType::kBuiltin:
+                    graph_.resolved_identifiers.Add(
+                        from, ResolvedIdentifier(to.BuiltinValue<builtin::Builtin>()));
+                    break;
+                case Symbol::BuiltinType::kBuiltinValue:
+                    graph_.resolved_identifiers.Add(
+                        from, ResolvedIdentifier(to.BuiltinValue<builtin::BuiltinValue>()));
+                    break;
+                case Symbol::BuiltinType::kAddressSpace:
+                    graph_.resolved_identifiers.Add(
+                        from, ResolvedIdentifier(to.BuiltinValue<builtin::AddressSpace>()));
+                    break;
+                case Symbol::BuiltinType::kTexelFormat:
+                    graph_.resolved_identifiers.Add(
+                        from, ResolvedIdentifier(to.BuiltinValue<builtin::TexelFormat>()));
+                    break;
+                case Symbol::BuiltinType::kAccess:
+                    graph_.resolved_identifiers.Add(
+                        from, ResolvedIdentifier(to.BuiltinValue<builtin::Access>()));
+                    break;
+                case Symbol::BuiltinType::kInterpolationType:
+                    graph_.resolved_identifiers.Add(
+                        from, ResolvedIdentifier(to.BuiltinValue<builtin::InterpolationType>()));
+                    break;
+                case Symbol::BuiltinType::kInterpolationSampling:
+                    graph_.resolved_identifiers.Add(
+                        from,
+                        ResolvedIdentifier(to.BuiltinValue<builtin::InterpolationSampling>()));
+                    break;
             }
-            if (auto builtin_ty = builtin::ParseBuiltin(s);
-                builtin_ty != builtin::Builtin::kUndefined) {
-                graph_.resolved_identifiers.Add(from, ResolvedIdentifier(builtin_ty));
-                return;
-            }
-            if (auto builtin_val = builtin::ParseBuiltinValue(s);
-                builtin_val != builtin::BuiltinValue::kUndefined) {
-                graph_.resolved_identifiers.Add(from, ResolvedIdentifier(builtin_val));
-                return;
-            }
-            if (auto addr = builtin::ParseAddressSpace(s);
-                addr != builtin::AddressSpace::kUndefined) {
-                graph_.resolved_identifiers.Add(from, ResolvedIdentifier(addr));
-                return;
-            }
-            if (auto fmt = builtin::ParseTexelFormat(s); fmt != builtin::TexelFormat::kUndefined) {
-                graph_.resolved_identifiers.Add(from, ResolvedIdentifier(fmt));
-                return;
-            }
-            if (auto access = builtin::ParseAccess(s); access != builtin::Access::kUndefined) {
-                graph_.resolved_identifiers.Add(from, ResolvedIdentifier(access));
-                return;
-            }
-            if (auto i_type = builtin::ParseInterpolationType(s);
-                i_type != builtin::InterpolationType::kUndefined) {
-                graph_.resolved_identifiers.Add(from, ResolvedIdentifier(i_type));
-                return;
-            }
-            if (auto i_smpl = builtin::ParseInterpolationSampling(s);
-                i_smpl != builtin::InterpolationSampling::kUndefined) {
-                graph_.resolved_identifiers.Add(from, ResolvedIdentifier(i_smpl));
-                return;
-            }
-
-            // Unresolved.
-            graph_.resolved_identifiers.Add(from, UnresolvedIdentifier{s});
             return;
         }
 
diff --git a/src/tint/symbol.cc b/src/tint/symbol.cc
index 7e69b5d..ad84add 100644
--- a/src/tint/symbol.cc
+++ b/src/tint/symbol.cc
@@ -21,7 +21,9 @@
 Symbol::Symbol() = default;
 
 Symbol::Symbol(uint32_t val, tint::ProgramID pid, std::string_view name)
-    : val_(val), program_id_(pid), name_(name) {}
+    : val_(val), program_id_(pid), name_(name) {
+    DetermineBuiltinType();
+}
 
 Symbol::Symbol(const Symbol& o) = default;
 
@@ -60,4 +62,51 @@
     return std::string(name_);
 }
 
+void Symbol::DetermineBuiltinType() {
+    if (auto builtin_fn = builtin::ParseFunction(name_); builtin_fn != builtin::Function::kNone) {
+        builtin_type_ = BuiltinType::kFunction;
+        builtin_value_ = builtin_fn;
+        return;
+    }
+    if (auto builtin_ty = builtin::ParseBuiltin(name_);
+        builtin_ty != builtin::Builtin::kUndefined) {
+        builtin_type_ = BuiltinType::kBuiltin;
+        builtin_value_ = builtin_ty;
+        return;
+    }
+    if (auto builtin_val = builtin::ParseBuiltinValue(name_);
+        builtin_val != builtin::BuiltinValue::kUndefined) {
+        builtin_type_ = BuiltinType::kBuiltinValue;
+        builtin_value_ = builtin_val;
+        return;
+    }
+    if (auto addr = builtin::ParseAddressSpace(name_); addr != builtin::AddressSpace::kUndefined) {
+        builtin_type_ = BuiltinType::kAddressSpace;
+        builtin_value_ = addr;
+        return;
+    }
+    if (auto fmt = builtin::ParseTexelFormat(name_); fmt != builtin::TexelFormat::kUndefined) {
+        builtin_type_ = BuiltinType::kTexelFormat;
+        builtin_value_ = fmt;
+        return;
+    }
+    if (auto access = builtin::ParseAccess(name_); access != builtin::Access::kUndefined) {
+        builtin_type_ = BuiltinType::kAccess;
+        builtin_value_ = access;
+        return;
+    }
+    if (auto i_type = builtin::ParseInterpolationType(name_);
+        i_type != builtin::InterpolationType::kUndefined) {
+        builtin_type_ = BuiltinType::kInterpolationType;
+        builtin_value_ = i_type;
+        return;
+    }
+    if (auto i_smpl = builtin::ParseInterpolationSampling(name_);
+        i_smpl != builtin::InterpolationSampling::kUndefined) {
+        builtin_type_ = BuiltinType::kInterpolationSampling;
+        builtin_value_ = i_smpl;
+        return;
+    }
+}
+
 }  // namespace tint
diff --git a/src/tint/symbol.h b/src/tint/symbol.h
index 16d8409..ae29559 100644
--- a/src/tint/symbol.h
+++ b/src/tint/symbol.h
@@ -16,7 +16,16 @@
 #define SRC_TINT_SYMBOL_H_
 
 #include <string>
+#include <variant>
 
+#include "src/tint/builtin/access.h"
+#include "src/tint/builtin/address_space.h"
+#include "src/tint/builtin/builtin.h"
+#include "src/tint/builtin/builtin_value.h"
+#include "src/tint/builtin/function.h"
+#include "src/tint/builtin/interpolation_sampling.h"
+#include "src/tint/builtin/interpolation_type.h"
+#include "src/tint/builtin/texel_format.h"
 #include "src/tint/program_id.h"
 
 namespace tint {
@@ -24,6 +33,28 @@
 /// A symbol representing a string in the system
 class Symbol {
   public:
+    /// The type of builtin this symbol could represent, if any.
+    enum class BuiltinType {
+        /// No builtin matched
+        kNone = 0,
+        /// Builtin function
+        kFunction,
+        /// Builtin
+        kBuiltin,
+        /// Builtin value
+        kBuiltinValue,
+        /// Address space
+        kAddressSpace,
+        /// Texel format
+        kTexelFormat,
+        /// Access
+        kAccess,
+        /// Interpolation Type
+        kInterpolationType,
+        /// Interpolation Sampling
+        kInterpolationSampling,
+    };
+
     /// Constructor
     /// An invalid symbol
     Symbol();
@@ -87,10 +118,33 @@
     /// @returns the identifier of the Program that owns this symbol.
     tint::ProgramID ProgramID() const { return program_id_; }
 
+    /// @returns the builtin type
+    BuiltinType Type() const { return builtin_type_; }
+
+    /// @returns the builtin value
+    template <typename T>
+    T BuiltinValue() const {
+        return std::get<T>(builtin_value_);
+    }
+
   private:
+    void DetermineBuiltinType();
+
     uint32_t val_ = static_cast<uint32_t>(-1);
     tint::ProgramID program_id_;
     std::string_view name_;
+
+    BuiltinType builtin_type_ = BuiltinType::kNone;
+    std::variant<std::monostate,
+                 builtin::Function,
+                 builtin::Builtin,
+                 builtin::BuiltinValue,
+                 builtin::AddressSpace,
+                 builtin::TexelFormat,
+                 builtin::Access,
+                 builtin::InterpolationType,
+                 builtin::InterpolationSampling>
+        builtin_value_ = {};
 };
 
 /// @param sym the Symbol