Support reflecting uninitialized pipeline overrideable constants

Also adds testing for constants type reporting

BUG=tint:852

Change-Id: Ic644f3a4e6687446a552ce755951966743c8ee97
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/65641
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/inspector/entry_point.h b/src/inspector/entry_point.h
index b652ba1..cf386a1 100644
--- a/src/inspector/entry_point.h
+++ b/src/inspector/entry_point.h
@@ -103,6 +103,9 @@
 
   /// Type of the scalar
   Type type;
+
+  /// Does this pipeline overridable constant have an initializer?
+  bool is_initialized = false;
 };
 
 /// Reflection data for an entry point in the shader.
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index 9118f39..196ebac 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -211,6 +211,9 @@
           TINT_UNREACHABLE(Inspector, diagnostics_);
         }
 
+        overridable_constant.is_initialized =
+            global->Declaration()->has_constructor();
+
         entry_point.overridable_constants.push_back(overridable_constant);
       }
     }
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc
index 9854f40..e02cf92 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -554,7 +554,7 @@
 }
 
 TEST_F(InspectorGetEntryPointTest, OverridableConstantUnreferenced) {
-  AddOverridableConstantWithoutID<float>("foo", ty.f32(), nullptr);
+  AddOverridableConstantWithoutID("foo", ty.f32(), nullptr);
   MakeEmptyBodyFunction(
       "ep_func", {Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
 
@@ -567,7 +567,7 @@
 }
 
 TEST_F(InspectorGetEntryPointTest, OverridableConstantReferencedByEntryPoint) {
-  AddOverridableConstantWithoutID<float>("foo", ty.f32(), nullptr);
+  AddOverridableConstantWithoutID("foo", ty.f32(), nullptr);
   MakePlainGlobalReferenceBodyFunction(
       "ep_func", "foo", ty.f32(),
       {Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
@@ -582,7 +582,7 @@
 }
 
 TEST_F(InspectorGetEntryPointTest, OverridableConstantReferencedByCallee) {
-  AddOverridableConstantWithoutID<float>("foo", ty.f32(), nullptr);
+  AddOverridableConstantWithoutID("foo", ty.f32(), nullptr);
   MakePlainGlobalReferenceBodyFunction("callee_func", "foo", ty.f32(), {});
   MakeCallerBodyFunction(
       "ep_func", {"callee_func"},
@@ -598,8 +598,8 @@
 }
 
 TEST_F(InspectorGetEntryPointTest, OverridableConstantSomeReferenced) {
-  AddOverridableConstantWithID<float>("foo", 1, ty.f32(), nullptr);
-  AddOverridableConstantWithID<float>("bar", 2, ty.f32(), nullptr);
+  AddOverridableConstantWithID("foo", 1, ty.f32(), nullptr);
+  AddOverridableConstantWithID("bar", 2, ty.f32(), nullptr);
   MakePlainGlobalReferenceBodyFunction("callee_func", "foo", ty.f32(), {});
   MakeCallerBodyFunction(
       "ep_func", {"callee_func"},
@@ -614,6 +614,74 @@
   EXPECT_EQ("foo", result[0].overridable_constants[0].name);
 }
 
+TEST_F(InspectorGetEntryPointTest, OverridableConstantTypes) {
+  AddOverridableConstantWithoutID("bool_var", ty.bool_(), nullptr);
+  AddOverridableConstantWithoutID("float_var", ty.f32(), nullptr);
+  AddOverridableConstantWithoutID("u32_var", ty.u32(), nullptr);
+  AddOverridableConstantWithoutID("i32_var", ty.i32(), nullptr);
+
+  MakePlainGlobalReferenceBodyFunction("bool_func", "bool_var", ty.bool_(), {});
+  MakePlainGlobalReferenceBodyFunction("float_func", "float_var", ty.f32(), {});
+  MakePlainGlobalReferenceBodyFunction("u32_func", "u32_var", ty.u32(), {});
+  MakePlainGlobalReferenceBodyFunction("i32_func", "i32_var", ty.i32(), {});
+
+  MakeCallerBodyFunction(
+      "ep_func", {"bool_func", "float_func", "u32_func", "i32_func"},
+      {Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
+
+  Inspector& inspector = Build();
+
+  auto result = inspector.GetEntryPoints();
+
+  ASSERT_EQ(1u, result.size());
+  ASSERT_EQ(4u, result[0].overridable_constants.size());
+  EXPECT_EQ("bool_var", result[0].overridable_constants[0].name);
+  EXPECT_EQ(inspector::OverridableConstant::Type::kBool,
+            result[0].overridable_constants[0].type);
+  EXPECT_EQ("float_var", result[0].overridable_constants[1].name);
+  EXPECT_EQ(inspector::OverridableConstant::Type::kFloat32,
+            result[0].overridable_constants[1].type);
+  EXPECT_EQ("u32_var", result[0].overridable_constants[2].name);
+  EXPECT_EQ(inspector::OverridableConstant::Type::kUint32,
+            result[0].overridable_constants[2].type);
+  EXPECT_EQ("i32_var", result[0].overridable_constants[3].name);
+  EXPECT_EQ(inspector::OverridableConstant::Type::kInt32,
+            result[0].overridable_constants[3].type);
+}
+
+TEST_F(InspectorGetEntryPointTest, OverridableConstantInitialized) {
+  AddOverridableConstantWithoutID("foo", ty.f32(), Expr(0.0f));
+  MakePlainGlobalReferenceBodyFunction(
+      "ep_func", "foo", ty.f32(),
+      {Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
+
+  Inspector& inspector = Build();
+
+  auto result = inspector.GetEntryPoints();
+
+  ASSERT_EQ(1u, result.size());
+  ASSERT_EQ(1u, result[0].overridable_constants.size());
+  EXPECT_EQ("foo", result[0].overridable_constants[0].name);
+  EXPECT_TRUE(result[0].overridable_constants[0].is_initialized);
+}
+
+TEST_F(InspectorGetEntryPointTest, OverridableConstantUninitialized) {
+  AddOverridableConstantWithoutID("foo", ty.f32(), nullptr);
+  MakePlainGlobalReferenceBodyFunction(
+      "ep_func", "foo", ty.f32(),
+      {Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
+
+  Inspector& inspector = Build();
+
+  auto result = inspector.GetEntryPoints();
+
+  ASSERT_EQ(1u, result.size());
+  ASSERT_EQ(1u, result[0].overridable_constants.size());
+  EXPECT_EQ("foo", result[0].overridable_constants[0].name);
+
+  EXPECT_FALSE(result[0].overridable_constants[0].is_initialized);
+}
+
 TEST_F(InspectorGetEntryPointTest, NonOverridableConstantSkipped) {
   ast::Struct* foo_struct_type = MakeUniformBufferType("foo_type", {ty.i32()});
   AddUniformBuffer("foo_ub", ty.Of(foo_struct_type), 0, 0);
@@ -991,11 +1059,9 @@
 }
 
 TEST_F(InspectorGetConstantIDsTest, Bool) {
-  bool val_true = true;
-  bool val_false = false;
-  AddOverridableConstantWithID<bool>("foo", 1, ty.bool_(), nullptr);
-  AddOverridableConstantWithID<bool>("bar", 20, ty.bool_(), &val_true);
-  AddOverridableConstantWithID<bool>("baz", 300, ty.bool_(), &val_false);
+  AddOverridableConstantWithID("foo", 1, ty.bool_(), nullptr);
+  AddOverridableConstantWithID("bar", 20, ty.bool_(), Expr(true));
+  AddOverridableConstantWithID("baz", 300, ty.bool_(), Expr(false));
 
   Inspector& inspector = Build();
 
@@ -1015,9 +1081,8 @@
 }
 
 TEST_F(InspectorGetConstantIDsTest, U32) {
-  uint32_t val = 42;
-  AddOverridableConstantWithID<uint32_t>("foo", 1, ty.u32(), nullptr);
-  AddOverridableConstantWithID<uint32_t>("bar", 20, ty.u32(), &val);
+  AddOverridableConstantWithID("foo", 1, ty.u32(), nullptr);
+  AddOverridableConstantWithID("bar", 20, ty.u32(), Expr(42u));
 
   Inspector& inspector = Build();
 
@@ -1033,11 +1098,9 @@
 }
 
 TEST_F(InspectorGetConstantIDsTest, I32) {
-  int32_t val_neg = -42;
-  int32_t val_pos = 42;
-  AddOverridableConstantWithID<int32_t>("foo", 1, ty.i32(), nullptr);
-  AddOverridableConstantWithID<int32_t>("bar", 20, ty.i32(), &val_neg);
-  AddOverridableConstantWithID<int32_t>("baz", 300, ty.i32(), &val_pos);
+  AddOverridableConstantWithID("foo", 1, ty.i32(), nullptr);
+  AddOverridableConstantWithID("bar", 20, ty.i32(), Expr(-42));
+  AddOverridableConstantWithID("baz", 300, ty.i32(), Expr(42));
 
   Inspector& inspector = Build();
 
@@ -1057,13 +1120,10 @@
 }
 
 TEST_F(InspectorGetConstantIDsTest, Float) {
-  float val_zero = 0.0f;
-  float val_neg = -10.0f;
-  float val_pos = 15.0f;
-  AddOverridableConstantWithID<float>("foo", 1, ty.f32(), nullptr);
-  AddOverridableConstantWithID<float>("bar", 20, ty.f32(), &val_zero);
-  AddOverridableConstantWithID<float>("baz", 300, ty.f32(), &val_neg);
-  AddOverridableConstantWithID<float>("x", 4000, ty.f32(), &val_pos);
+  AddOverridableConstantWithID("foo", 1, ty.f32(), nullptr);
+  AddOverridableConstantWithID("bar", 20, ty.f32(), Expr(0.0f));
+  AddOverridableConstantWithID("baz", 300, ty.f32(), Expr(-10.0f));
+  AddOverridableConstantWithID("x", 4000, ty.f32(), Expr(15.0f));
 
   Inspector& inspector = Build();
 
@@ -1087,12 +1147,12 @@
 }
 
 TEST_F(InspectorGetConstantNameToIdMapTest, WithAndWithoutIds) {
-  AddOverridableConstantWithID<float>("v1", 1, ty.f32(), nullptr);
-  AddOverridableConstantWithID<float>("v20", 20, ty.f32(), nullptr);
-  AddOverridableConstantWithID<float>("v300", 300, ty.f32(), nullptr);
-  auto* a = AddOverridableConstantWithoutID<float>("a", ty.f32(), nullptr);
-  auto* b = AddOverridableConstantWithoutID<float>("b", ty.f32(), nullptr);
-  auto* c = AddOverridableConstantWithoutID<float>("c", ty.f32(), nullptr);
+  AddOverridableConstantWithID("v1", 1, ty.f32(), nullptr);
+  AddOverridableConstantWithID("v20", 20, ty.f32(), nullptr);
+  AddOverridableConstantWithID("v300", 300, ty.f32(), nullptr);
+  auto* a = AddOverridableConstantWithoutID("a", ty.f32(), nullptr);
+  auto* b = AddOverridableConstantWithoutID("b", ty.f32(), nullptr);
+  auto* c = AddOverridableConstantWithoutID("c", ty.f32(), nullptr);
 
   Inspector& inspector = Build();
 
diff --git a/src/inspector/test_inspector_builder.h b/src/inspector/test_inspector_builder.h
index 03cf838..6d9554b 100644
--- a/src/inspector/test_inspector_builder.h
+++ b/src/inspector/test_inspector_builder.h
@@ -101,18 +101,13 @@
   /// @param name name of the variable to add
   /// @param id id number for the constant id
   /// @param type type of the variable
-  /// @param val value to initialize the variable with, if NULL no initializer
-  ///            will be added.
+  /// @param constructor val to initialize the constant with, if NULL no
+  ///             constructor will be added.
   /// @returns the constant that was created
-  template <class T>
   ast::Variable* AddOverridableConstantWithID(std::string name,
                                               uint32_t id,
                                               ast::Type* type,
-                                              T* val) {
-    ast::Expression* constructor = nullptr;
-    if (val) {
-      constructor = Expr(*val);
-    }
+                                              ast::Expression* constructor) {
     return GlobalConst(name, type, constructor,
                        ast::DecorationList{
                            Override(id),
@@ -122,17 +117,12 @@
   /// Add a pipeline constant to the global variables, without a specific ID.
   /// @param name name of the variable to add
   /// @param type type of the variable
-  /// @param val value to initialize the variable with, if NULL no initializer
-  ///            will be added.
+  /// @param constructor val to initialize the constant with, if NULL no
+  ///             constructor will be added.
   /// @returns the constant that was created
-  template <class T>
   ast::Variable* AddOverridableConstantWithoutID(std::string name,
                                                  ast::Type* type,
-                                                 T* val) {
-    ast::Expression* constructor = nullptr;
-    if (val) {
-      constructor = Expr(*val);
-    }
+                                                 ast::Expression* constructor) {
     return GlobalConst(name, type, constructor,
                        ast::DecorationList{
                            Override(),