[tint][ir] Remove FunctionParam::Builtin, use core::BuiltinValue

Now that we have a separation of core and WGSL definitions, I don't think there's a good reason for having yet another copy this builtin enum.

Change-Id: Id8869e81627e89fc05c7561488a17a8b5eea0e8c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/165041
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/lang/core/ir/function_param.cc b/src/tint/lang/core/ir/function_param.cc
index 389942a..6dd00df 100644
--- a/src/tint/lang/core/ir/function_param.cc
+++ b/src/tint/lang/core/ir/function_param.cc
@@ -41,38 +41,6 @@
 
 FunctionParam::~FunctionParam() = default;
 
-std::string_view ToString(enum FunctionParam::Builtin value) {
-    switch (value) {
-        case FunctionParam::Builtin::kVertexIndex:
-            return "vertex_index";
-        case FunctionParam::Builtin::kInstanceIndex:
-            return "instance_index";
-        case FunctionParam::Builtin::kPosition:
-            return "position";
-        case FunctionParam::Builtin::kFrontFacing:
-            return "front_facing";
-        case FunctionParam::Builtin::kLocalInvocationId:
-            return "local_invocation_id";
-        case FunctionParam::Builtin::kLocalInvocationIndex:
-            return "local_invocation_index";
-        case FunctionParam::Builtin::kGlobalInvocationId:
-            return "global_invocation_id";
-        case FunctionParam::Builtin::kWorkgroupId:
-            return "workgroup_id";
-        case FunctionParam::Builtin::kNumWorkgroups:
-            return "num_workgroups";
-        case FunctionParam::Builtin::kSampleIndex:
-            return "sample_index";
-        case FunctionParam::Builtin::kSampleMask:
-            return "sample_mask";
-        case FunctionParam::Builtin::kSubgroupInvocationId:
-            return "subgroup_invocation_id";
-        case FunctionParam::Builtin::kSubgroupSize:
-            return "subgroup_size";
-    }
-    return "<unknown>";
-}
-
 FunctionParam* FunctionParam::Clone(CloneContext& ctx) {
     auto* out = ctx.ir.values.Create<FunctionParam>(type_);
     out->builtin_ = builtin_;
diff --git a/src/tint/lang/core/ir/function_param.h b/src/tint/lang/core/ir/function_param.h
index 4f8e22c..ea989b3 100644
--- a/src/tint/lang/core/ir/function_param.h
+++ b/src/tint/lang/core/ir/function_param.h
@@ -31,6 +31,7 @@
 #include <utility>
 
 #include "src/tint/api/common/binding_point.h"
+#include "src/tint/lang/core/builtin_value.h"
 #include "src/tint/lang/core/ir/location.h"
 #include "src/tint/lang/core/ir/value.h"
 #include "src/tint/utils/containers/vector.h"
@@ -42,36 +43,6 @@
 /// A function parameter in the IR.
 class FunctionParam : public Castable<FunctionParam, Value> {
   public:
-    /// Builtin attribute
-    enum class Builtin {
-        /// Builtin Vertex index
-        kVertexIndex,
-        /// Builtin Instance index
-        kInstanceIndex,
-        /// Builtin Position
-        kPosition,
-        /// Builtin FrontFacing
-        kFrontFacing,
-        /// Builtin Local invocation id
-        kLocalInvocationId,
-        /// Builtin Local invocation index
-        kLocalInvocationIndex,
-        /// Builtin Global invocation id
-        kGlobalInvocationId,
-        /// Builtin Workgroup id
-        kWorkgroupId,
-        /// Builtin Num workgroups
-        kNumWorkgroups,
-        /// Builtin Sample index
-        kSampleIndex,
-        /// Builtin Sample mask
-        kSampleMask,
-        /// Builtin Subgroup invocation id
-        kSubgroupInvocationId,
-        /// Builtin Subgroup size
-        kSubgroupSize,
-    };
-
     /// Constructor
     /// @param type the type of the var
     explicit FunctionParam(const core::type::Type* type);
@@ -85,12 +56,12 @@
 
     /// Sets the builtin information. Note, it is currently an error if the builtin is already set.
     /// @param val the builtin to set
-    void SetBuiltin(FunctionParam::Builtin val) {
+    void SetBuiltin(core::BuiltinValue val) {
         TINT_ASSERT(!builtin_.has_value());
         builtin_ = val;
     }
     /// @returns the builtin set for the parameter
-    std::optional<FunctionParam::Builtin> Builtin() const { return builtin_; }
+    std::optional<core::BuiltinValue> Builtin() const { return builtin_; }
     /// Clears the builtin attribute.
     void ClearBuiltin() { builtin_ = {}; }
 
@@ -120,24 +91,12 @@
 
   private:
     const core::type::Type* type_ = nullptr;
-    std::optional<enum FunctionParam::Builtin> builtin_;
+    std::optional<core::BuiltinValue> builtin_;
     std::optional<struct Location> location_;
     std::optional<struct BindingPoint> binding_point_;
     bool invariant_ = false;
 };
 
-/// @param value the enum value
-/// @returns the string for the given enum value
-std::string_view ToString(enum FunctionParam::Builtin value);
-
-/// @param out the stream to write to
-/// @param value the FunctionParam::Builtin
-/// @returns @p out so calls can be chained
-template <typename STREAM, typename = traits::EnableIfIsOStream<STREAM>>
-auto& operator<<(STREAM& out, enum FunctionParam::Builtin value) {
-    return out << ToString(value);
-}
-
 }  // namespace tint::core::ir
 
 #endif  // SRC_TINT_LANG_CORE_IR_FUNCTION_PARAM_H_
diff --git a/src/tint/lang/core/ir/function_param_test.cc b/src/tint/lang/core/ir/function_param_test.cc
index f4b709e..375e8a84 100644
--- a/src/tint/lang/core/ir/function_param_test.cc
+++ b/src/tint/lang/core/ir/function_param_test.cc
@@ -53,8 +53,8 @@
             Module mod;
             Builder b{mod};
             auto* fp = b.FunctionParam(mod.Types().f32());
-            fp->SetBuiltin(FunctionParam::Builtin::kVertexIndex);
-            fp->SetBuiltin(FunctionParam::Builtin::kSampleMask);
+            fp->SetBuiltin(BuiltinValue::kVertexIndex);
+            fp->SetBuiltin(BuiltinValue::kSampleMask);
         },
         "");
 }
@@ -72,7 +72,7 @@
 
 TEST_F(IR_FunctionParamTest, Clone) {
     auto* fp = b.FunctionParam(mod.Types().f32());
-    fp->SetBuiltin(FunctionParam::Builtin::kVertexIndex);
+    fp->SetBuiltin(BuiltinValue::kVertexIndex);
     fp->SetLocation(
         1, Interpolation{core::InterpolationType::kFlat, core::InterpolationSampling::kCentroid});
     fp->SetInvariant(true);
@@ -84,7 +84,7 @@
     EXPECT_EQ(new_fp->Type(), mod.Types().f32());
 
     EXPECT_TRUE(new_fp->Builtin().has_value());
-    EXPECT_EQ(FunctionParam::Builtin::kVertexIndex, new_fp->Builtin().value());
+    EXPECT_EQ(BuiltinValue::kVertexIndex, new_fp->Builtin().value());
 
     EXPECT_TRUE(new_fp->Location().has_value());
     auto loc = new_fp->Location();
diff --git a/src/tint/lang/core/ir/transform/demote_to_helper_test.cc b/src/tint/lang/core/ir/transform/demote_to_helper_test.cc
index 19b04dc..effd5ea 100644
--- a/src/tint/lang/core/ir/transform/demote_to_helper_test.cc
+++ b/src/tint/lang/core/ir/transform/demote_to_helper_test.cc
@@ -82,7 +82,7 @@
     mod.root_block->Append(buffer);
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
@@ -167,7 +167,7 @@
     });
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
@@ -270,7 +270,7 @@
     });
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
@@ -370,7 +370,7 @@
     });
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
@@ -453,7 +453,7 @@
 TEST_F(IR_DemoteToHelperTest, WriteToInvocationPrivateAddressSpace) {
     auto* priv = mod.root_block->Append(b.Var("priv", ty.ptr<private_, i32>()));
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
@@ -537,7 +537,7 @@
     mod.root_block->Append(texture);
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(BuiltinValue::kFrontFacing);
     auto* coord = b.FunctionParam("coord", ty.vec2<i32>());
     auto* ep = b.Function("ep", ty.f32(), Function::PipelineStage::kFragment);
     ep->SetParams({front_facing, coord});
@@ -620,7 +620,7 @@
     mod.root_block->Append(buffer);
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
@@ -699,7 +699,7 @@
     mod.root_block->Append(buffer);
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
@@ -782,7 +782,7 @@
     mod.root_block->Append(buffer);
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
diff --git a/src/tint/lang/core/ir/transform/shader_io.cc b/src/tint/lang/core/ir/transform/shader_io.cc
index ce24b54..d509671 100644
--- a/src/tint/lang/core/ir/transform/shader_io.cc
+++ b/src/tint/lang/core/ir/transform/shader_io.cc
@@ -41,38 +41,6 @@
 
 namespace {
 
-core::BuiltinValue FunctionParamBuiltin(enum FunctionParam::Builtin builtin) {
-    switch (builtin) {
-        case FunctionParam::Builtin::kVertexIndex:
-            return core::BuiltinValue::kVertexIndex;
-        case FunctionParam::Builtin::kInstanceIndex:
-            return core::BuiltinValue::kInstanceIndex;
-        case FunctionParam::Builtin::kPosition:
-            return core::BuiltinValue::kPosition;
-        case FunctionParam::Builtin::kFrontFacing:
-            return core::BuiltinValue::kFrontFacing;
-        case FunctionParam::Builtin::kLocalInvocationId:
-            return core::BuiltinValue::kLocalInvocationId;
-        case FunctionParam::Builtin::kLocalInvocationIndex:
-            return core::BuiltinValue::kLocalInvocationIndex;
-        case FunctionParam::Builtin::kGlobalInvocationId:
-            return core::BuiltinValue::kGlobalInvocationId;
-        case FunctionParam::Builtin::kWorkgroupId:
-            return core::BuiltinValue::kWorkgroupId;
-        case FunctionParam::Builtin::kNumWorkgroups:
-            return core::BuiltinValue::kNumWorkgroups;
-        case FunctionParam::Builtin::kSampleIndex:
-            return core::BuiltinValue::kSampleIndex;
-        case FunctionParam::Builtin::kSampleMask:
-            return core::BuiltinValue::kSampleMask;
-        case FunctionParam::Builtin::kSubgroupInvocationId:
-            return core::BuiltinValue::kSubgroupInvocationId;
-        case FunctionParam::Builtin::kSubgroupSize:
-            return core::BuiltinValue::kSubgroupSize;
-    }
-    return core::BuiltinValue::kUndefined;
-}
-
 core::BuiltinValue ReturnBuiltin(enum Function::ReturnBuiltin builtin) {
     switch (builtin) {
         case Function::ReturnBuiltin::kPosition:
@@ -185,7 +153,7 @@
                     }
                     param->ClearLocation();
                 } else if (auto builtin = param->Builtin()) {
-                    attributes.builtin = FunctionParamBuiltin(*builtin);
+                    attributes.builtin = *builtin;
                     param->ClearBuiltin();
                 }
                 attributes.invariant = param->Invariant();
diff --git a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc
index 0e8c6a0..db902b4 100644
--- a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc
+++ b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc
@@ -285,7 +285,7 @@
             } else {
                 // Check if the parameter is the local invocation index.
                 if (param->Builtin() &&
-                    param->Builtin().value() == FunctionParam::Builtin::kLocalInvocationIndex) {
+                    param->Builtin().value() == BuiltinValue::kLocalInvocationIndex) {
                     return param;
                 }
             }
@@ -294,7 +294,7 @@
         // No local invocation index was found, so add one to the parameter list and use that.
         Vector<FunctionParam*, 4> params = func->Params();
         auto* param = b.FunctionParam("tint_local_index", ty.u32());
-        param->SetBuiltin(FunctionParam::Builtin::kLocalInvocationIndex);
+        param->SetBuiltin(BuiltinValue::kLocalInvocationIndex);
         params.Push(param);
         func->SetParams(params);
         return param;
diff --git a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
index d0a972e..37ba499 100644
--- a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
+++ b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
@@ -1434,9 +1434,9 @@
 
     auto* func = MakeEntryPoint("main", 1, 1, 1);
     auto* global_id = b.FunctionParam("global_id", ty.vec4<u32>());
-    global_id->SetBuiltin(FunctionParam::Builtin::kGlobalInvocationId);
+    global_id->SetBuiltin(BuiltinValue::kGlobalInvocationId);
     auto* index = b.FunctionParam("index", ty.u32());
-    index->SetBuiltin(FunctionParam::Builtin::kLocalInvocationIndex);
+    index->SetBuiltin(BuiltinValue::kLocalInvocationIndex);
     func->SetParams({global_id, index});
     b.Append(func->Block(), [&] {  //
         b.Load(var);
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc
index 2b6bda9..6cfa838 100644
--- a/src/tint/lang/msl/writer/printer/printer.cc
+++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -270,31 +270,31 @@
                 if (param->Builtin().has_value()) {
                     out << " [[";
                     switch (param->Builtin().value()) {
-                        case core::ir::FunctionParam::Builtin::kFrontFacing:
+                        case core::BuiltinValue::kFrontFacing:
                             out << "front_facing";
                             break;
-                        case core::ir::FunctionParam::Builtin::kGlobalInvocationId:
+                        case core::BuiltinValue::kGlobalInvocationId:
                             out << "thread_position_in_grid";
                             break;
-                        case core::ir::FunctionParam::Builtin::kLocalInvocationId:
+                        case core::BuiltinValue::kLocalInvocationId:
                             out << "thread_position_in_threadgroup";
                             break;
-                        case core::ir::FunctionParam::Builtin::kLocalInvocationIndex:
+                        case core::BuiltinValue::kLocalInvocationIndex:
                             out << "thread_index_in_threadgroup";
                             break;
-                        case core::ir::FunctionParam::Builtin::kNumWorkgroups:
+                        case core::BuiltinValue::kNumWorkgroups:
                             out << "threadgroups_per_grid";
                             break;
-                        case core::ir::FunctionParam::Builtin::kPosition:
+                        case core::BuiltinValue::kPosition:
                             out << "position";
                             break;
-                        case core::ir::FunctionParam::Builtin::kSampleIndex:
+                        case core::BuiltinValue::kSampleIndex:
                             out << "sample_id";
                             break;
-                        case core::ir::FunctionParam::Builtin::kSampleMask:
+                        case core::BuiltinValue::kSampleMask:
                             out << "sample_mask";
                             break;
-                        case core::ir::FunctionParam::Builtin::kWorkgroupId:
+                        case core::BuiltinValue::kWorkgroupId:
                             out << "threadgroup_position_in_grid";
                             break;
 
diff --git a/src/tint/lang/spirv/writer/discard_test.cc b/src/tint/lang/spirv/writer/discard_test.cc
index 5e9ccf9..843ffa6 100644
--- a/src/tint/lang/spirv/writer/discard_test.cc
+++ b/src/tint/lang/spirv/writer/discard_test.cc
@@ -39,7 +39,7 @@
     mod.root_block->Append(buffer);
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(core::ir::FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(core::BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), core::ir::Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
@@ -91,7 +91,7 @@
     mod.root_block->Append(buffer);
 
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(core::ir::FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(core::BuiltinValue::kFrontFacing);
     auto* ep = b.Function("ep", ty.f32(), core::ir::Function::PipelineStage::kFragment);
     ep->SetParams({front_facing});
     ep->SetReturnLocation(0_u, {});
diff --git a/src/tint/lang/spirv/writer/raise/shader_io_test.cc b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
index bfea71b..5899c91 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io_test.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
@@ -68,9 +68,9 @@
 TEST_F(SpirvWriter_ShaderIOTest, Parameters_NonStruct) {
     auto* ep = b.Function("foo", ty.void_());
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(core::ir::FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(core::BuiltinValue::kFrontFacing);
     auto* position = b.FunctionParam("position", ty.vec4<f32>());
-    position->SetBuiltin(core::ir::FunctionParam::Builtin::kPosition);
+    position->SetBuiltin(core::BuiltinValue::kPosition);
     position->SetInvariant(true);
     auto* color1 = b.FunctionParam("color1", ty.f32());
     color1->SetLocation(0, {});
@@ -328,7 +328,7 @@
 
     auto* ep = b.Function("foo", ty.void_());
     auto* front_facing = b.FunctionParam("front_facing", ty.bool_());
-    front_facing->SetBuiltin(core::ir::FunctionParam::Builtin::kFrontFacing);
+    front_facing->SetBuiltin(core::BuiltinValue::kFrontFacing);
     auto* str_param = b.FunctionParam("inputs", str_ty);
     auto* color2 = b.FunctionParam("color2", ty.f32());
     color2->SetLocation(1, core::Interpolation{core::InterpolationType::kLinear,
@@ -975,7 +975,7 @@
                              });
 
     auto* mask_in = b.FunctionParam("mask_in", ty.u32());
-    mask_in->SetBuiltin(core::ir::FunctionParam::Builtin::kSampleMask);
+    mask_in->SetBuiltin(core::BuiltinValue::kSampleMask);
 
     auto* ep = b.Function("foo", str_ty);
     ep->SetStage(core::ir::Function::PipelineStage::kFragment);
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
index 8e09859..f227efb 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
@@ -393,63 +393,7 @@
                                 program_.Sem()
                                     .Get(b)
                                     ->As<sem::BuiltinEnumExpression<core::BuiltinValue>>()) {
-                            switch (ident_sem->Value()) {
-                                case core::BuiltinValue::kVertexIndex:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kVertexIndex);
-                                    break;
-                                case core::BuiltinValue::kInstanceIndex:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kInstanceIndex);
-                                    break;
-                                case core::BuiltinValue::kPosition:
-                                    param->SetBuiltin(core::ir::FunctionParam::Builtin::kPosition);
-                                    break;
-                                case core::BuiltinValue::kFrontFacing:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kFrontFacing);
-                                    break;
-                                case core::BuiltinValue::kLocalInvocationId:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kLocalInvocationId);
-                                    break;
-                                case core::BuiltinValue::kLocalInvocationIndex:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kLocalInvocationIndex);
-                                    break;
-                                case core::BuiltinValue::kGlobalInvocationId:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kGlobalInvocationId);
-                                    break;
-                                case core::BuiltinValue::kWorkgroupId:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kWorkgroupId);
-                                    break;
-                                case core::BuiltinValue::kNumWorkgroups:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kNumWorkgroups);
-                                    break;
-                                case core::BuiltinValue::kSampleIndex:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kSampleIndex);
-                                    break;
-                                case core::BuiltinValue::kSampleMask:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kSampleMask);
-                                    break;
-                                case core::BuiltinValue::kSubgroupInvocationId:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kSubgroupInvocationId);
-                                    break;
-                                case core::BuiltinValue::kSubgroupSize:
-                                    param->SetBuiltin(
-                                        core::ir::FunctionParam::Builtin::kSubgroupSize);
-                                    break;
-                                default:
-                                    TINT_ICE() << "Unknown builtin value in parameter attributes "
-                                               << ident_sem->Value();
-                                    return;
-                            }
+                            param->SetBuiltin(ident_sem->Value());
                         } else {
                             TINT_ICE() << "Builtin attribute sem invalid";
                             return;
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index b195b30..09483c9 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -211,47 +211,50 @@
             // Emit parameter attributes.
             if (auto builtin = param->Builtin()) {
                 switch (builtin.value()) {
-                    case core::ir::FunctionParam::Builtin::kVertexIndex:
+                    case core::BuiltinValue::kVertexIndex:
                         attrs.Push(b.Builtin(core::BuiltinValue::kVertexIndex));
                         break;
-                    case core::ir::FunctionParam::Builtin::kInstanceIndex:
+                    case core::BuiltinValue::kInstanceIndex:
                         attrs.Push(b.Builtin(core::BuiltinValue::kInstanceIndex));
                         break;
-                    case core::ir::FunctionParam::Builtin::kPosition:
+                    case core::BuiltinValue::kPosition:
                         attrs.Push(b.Builtin(core::BuiltinValue::kPosition));
                         break;
-                    case core::ir::FunctionParam::Builtin::kFrontFacing:
+                    case core::BuiltinValue::kFrontFacing:
                         attrs.Push(b.Builtin(core::BuiltinValue::kFrontFacing));
                         break;
-                    case core::ir::FunctionParam::Builtin::kLocalInvocationId:
+                    case core::BuiltinValue::kLocalInvocationId:
                         attrs.Push(b.Builtin(core::BuiltinValue::kLocalInvocationId));
                         break;
-                    case core::ir::FunctionParam::Builtin::kLocalInvocationIndex:
+                    case core::BuiltinValue::kLocalInvocationIndex:
                         attrs.Push(b.Builtin(core::BuiltinValue::kLocalInvocationIndex));
                         break;
-                    case core::ir::FunctionParam::Builtin::kGlobalInvocationId:
+                    case core::BuiltinValue::kGlobalInvocationId:
                         attrs.Push(b.Builtin(core::BuiltinValue::kGlobalInvocationId));
                         break;
-                    case core::ir::FunctionParam::Builtin::kWorkgroupId:
+                    case core::BuiltinValue::kWorkgroupId:
                         attrs.Push(b.Builtin(core::BuiltinValue::kWorkgroupId));
                         break;
-                    case core::ir::FunctionParam::Builtin::kNumWorkgroups:
+                    case core::BuiltinValue::kNumWorkgroups:
                         attrs.Push(b.Builtin(core::BuiltinValue::kNumWorkgroups));
                         break;
-                    case core::ir::FunctionParam::Builtin::kSampleIndex:
+                    case core::BuiltinValue::kSampleIndex:
                         attrs.Push(b.Builtin(core::BuiltinValue::kSampleIndex));
                         break;
-                    case core::ir::FunctionParam::Builtin::kSampleMask:
+                    case core::BuiltinValue::kSampleMask:
                         attrs.Push(b.Builtin(core::BuiltinValue::kSampleMask));
                         break;
-                    case core::ir::FunctionParam::Builtin::kSubgroupInvocationId:
+                    case core::BuiltinValue::kSubgroupInvocationId:
                         Enable(wgsl::Extension::kChromiumExperimentalSubgroups);
                         attrs.Push(b.Builtin(core::BuiltinValue::kSubgroupInvocationId));
                         break;
-                    case core::ir::FunctionParam::Builtin::kSubgroupSize:
+                    case core::BuiltinValue::kSubgroupSize:
                         Enable(wgsl::Extension::kChromiumExperimentalSubgroups);
                         attrs.Push(b.Builtin(core::BuiltinValue::kSubgroupSize));
                         break;
+                    default:
+                        TINT_UNIMPLEMENTED() << builtin.value();
+                        break;
                 }
             }
             if (auto loc = param->Location()) {
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index 76acec6..a470fe3 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -216,7 +216,7 @@
 namespace {
 core::ir::FunctionParam* MakeBuiltinParam(core::ir::Builder& b,
                                           const core::type::Type* type,
-                                          enum core::ir::FunctionParam::Builtin builtin) {
+                                          enum core::BuiltinValue builtin) {
     auto* param = b.FunctionParam(type);
     param->SetBuiltin(builtin);
     return param;
@@ -227,13 +227,13 @@
     auto* fn = b.Function("f", ty.void_(), core::ir::Function::PipelineStage::kCompute,
                           std::array{3u, 4u, 5u});
     fn->SetParams({
-        MakeBuiltinParam(b, ty.vec3<u32>(), core::ir::FunctionParam::Builtin::kLocalInvocationId),
-        MakeBuiltinParam(b, ty.u32(), core::ir::FunctionParam::Builtin::kLocalInvocationIndex),
-        MakeBuiltinParam(b, ty.vec3<u32>(), core::ir::FunctionParam::Builtin::kGlobalInvocationId),
-        MakeBuiltinParam(b, ty.vec3<u32>(), core::ir::FunctionParam::Builtin::kWorkgroupId),
-        MakeBuiltinParam(b, ty.vec3<u32>(), core::ir::FunctionParam::Builtin::kNumWorkgroups),
-        MakeBuiltinParam(b, ty.u32(), core::ir::FunctionParam::Builtin::kSubgroupInvocationId),
-        MakeBuiltinParam(b, ty.u32(), core::ir::FunctionParam::Builtin::kSubgroupSize),
+        MakeBuiltinParam(b, ty.vec3<u32>(), core::BuiltinValue::kLocalInvocationId),
+        MakeBuiltinParam(b, ty.u32(), core::BuiltinValue::kLocalInvocationIndex),
+        MakeBuiltinParam(b, ty.vec3<u32>(), core::BuiltinValue::kGlobalInvocationId),
+        MakeBuiltinParam(b, ty.vec3<u32>(), core::BuiltinValue::kWorkgroupId),
+        MakeBuiltinParam(b, ty.vec3<u32>(), core::BuiltinValue::kNumWorkgroups),
+        MakeBuiltinParam(b, ty.u32(), core::BuiltinValue::kSubgroupInvocationId),
+        MakeBuiltinParam(b, ty.u32(), core::BuiltinValue::kSubgroupSize),
     });
 
     fn->Block()->Append(b.Return(fn));
@@ -250,9 +250,9 @@
 TEST_F(IRToProgramTest, EntryPoint_ParameterAttribute_Fragment) {
     auto* fn = b.Function("f", ty.void_(), core::ir::Function::PipelineStage::kFragment);
     fn->SetParams({
-        MakeBuiltinParam(b, ty.bool_(), core::ir::FunctionParam::Builtin::kFrontFacing),
-        MakeBuiltinParam(b, ty.u32(), core::ir::FunctionParam::Builtin::kSampleIndex),
-        MakeBuiltinParam(b, ty.u32(), core::ir::FunctionParam::Builtin::kSampleMask),
+        MakeBuiltinParam(b, ty.bool_(), core::BuiltinValue::kFrontFacing),
+        MakeBuiltinParam(b, ty.u32(), core::BuiltinValue::kSampleIndex),
+        MakeBuiltinParam(b, ty.u32(), core::BuiltinValue::kSampleMask),
     });
 
     fn->Block()->Append(b.Return(fn));