[ir] Validate vector construct instructions

Use the intrinsics table to check that the argument types match a
valid overload for the target vector type.

Fixed: 427964205
Change-Id: Iec44a31cafc370e69b38e78f55fc4363b37881d6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/255758
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index 18b7f0b..8750327 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -3157,8 +3157,16 @@
             AddError(construct, 0u) << "scalar construct argument type " << NameOf(args[0]->Type())
                                     << " does not match result type " << NameOf(result_type);
         }
-    } else if (result_type->Is<core::type::Vector>()) {
-        // TODO(crbug.com/427964205): This needs special handling as there are many cases.
+    } else if (auto* vec = result_type->As<core::type::Vector>()) {
+        auto table = intrinsic::Table<intrinsic::Dialect>(type_mgr_, symbols_);
+        auto ctor_conv = intrinsic::VectorCtorConv(vec->Width());
+        auto arg_types = Transform<4>(args, [&](auto* v) { return v->Type(); });
+        auto match = table.Lookup(ctor_conv, Vector{vec->Type()}, std::move(arg_types),
+                                  core::EvaluationStage::kConstant);
+        if (match != Success) {
+            AddError(construct) << "no matching overload for " << vec->FriendlyName()
+                                << " constructor";
+        }
     } else if (auto* mat = result_type->As<core::type::Matrix>()) {
         auto table = intrinsic::Table<intrinsic::Dialect>(type_mgr_, symbols_);
         auto ctor_conv = intrinsic::MatrixCtorConv(mat->Columns(), mat->Rows());
diff --git a/src/tint/lang/glsl/writer/constructor_test.cc b/src/tint/lang/glsl/writer/constructor_test.cc
index 2871d14..8c1dc40 100644
--- a/src/tint/lang/glsl/writer/constructor_test.cc
+++ b/src/tint/lang/glsl/writer/constructor_test.cc
@@ -283,7 +283,7 @@
     auto* func = b.Function("a", ty.vec3<f32>());
     b.Append(func->Block(), [&] {  //
         auto* v = b.Var("v", 2_f);
-        b.Return(func, b.Construct(ty.vec3<f32>(), v));
+        b.Return(func, b.Construct(ty.vec3<f32>(), b.Load(v)));
     });
 
     ASSERT_TRUE(Generate()) << err_ << output_.glsl;
@@ -302,7 +302,7 @@
     auto* func = b.Function("a", ty.vec3<f16>());
     b.Append(func->Block(), [&] {  //
         auto* v = b.Var("v", 2_h);
-        b.Return(func, b.Construct(ty.vec3<f16>(), v));
+        b.Return(func, b.Construct(ty.vec3<f16>(), b.Load(v)));
     });
 
     ASSERT_TRUE(Generate()) << err_ << output_.glsl;
diff --git a/src/tint/lang/glsl/writer/raise/texture_polyfill_test.cc b/src/tint/lang/glsl/writer/raise/texture_polyfill_test.cc
index ad52c24..7f9b763 100644
--- a/src/tint/lang/glsl/writer/raise/texture_polyfill_test.cc
+++ b/src/tint/lang/glsl/writer/raise/texture_polyfill_test.cc
@@ -4359,7 +4359,7 @@
 
     auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
     b.Append(func->Block(), [&] {
-        auto* coords = b.Construct(ty.vec3<f32>(), b.Value(1_f), b.Value(2_f), b.Value(3_i));
+        auto* coords = b.Construct(ty.vec3<f32>(), b.Value(1_f), b.Value(2_f), b.Value(3_f));
         auto* array_idx = b.Value(4_u);
 
         auto* t = b.Load(tex);
@@ -4376,7 +4376,7 @@
 
 %foo = @fragment func():void {
   $B2: {
-    %4:vec3<f32> = construct 1.0f, 2.0f, 3i
+    %4:vec3<f32> = construct 1.0f, 2.0f, 3.0f
     %5:texture_depth_cube_array = load %1
     %6:sampler = load %2
     %7:f32 = textureSampleLevel %5, %6, %4, 4u, 3i
@@ -4394,7 +4394,7 @@
 
 %foo = @fragment func():void {
   $B2: {
-    %3:vec3<f32> = construct 1.0f, 2.0f, 3i
+    %3:vec3<f32> = construct 1.0f, 2.0f, 3.0f
     %4:texture_depth_cube_array = load %t_s
     %5:f32 = convert 4u
     %6:vec4<f32> = construct %3, %5
diff --git a/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc b/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc
index d317dcc..ee58cf6 100644
--- a/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc
+++ b/src/tint/lang/hlsl/writer/raise/builtin_polyfill_test.cc
@@ -5598,7 +5598,7 @@
 
     auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kFragment);
     b.Append(func->Block(), [&] {
-        auto* coords = b.Construct(ty.vec3<f32>(), b.Value(1_f), b.Value(2_f), b.Value(3_i));
+        auto* coords = b.Construct(ty.vec3<f32>(), b.Value(1_f), b.Value(2_f), b.Value(3_f));
         auto* array_idx = b.Value(4_u);
 
         auto* t = b.Load(tex);
@@ -5615,7 +5615,7 @@
 
 %foo = @fragment func():void {
   $B2: {
-    %4:vec3<f32> = construct 1.0f, 2.0f, 3i
+    %4:vec3<f32> = construct 1.0f, 2.0f, 3.0f
     %5:texture_depth_cube_array = load %1
     %6:sampler = load %2
     %7:f32 = textureSampleLevel %5, %6, %4, 4u, 3i
@@ -5634,7 +5634,7 @@
 
 %foo = @fragment func():void {
   $B2: {
-    %4:vec3<f32> = construct 1.0f, 2.0f, 3i
+    %4:vec3<f32> = construct 1.0f, 2.0f, 3.0f
     %5:texture_depth_cube_array = load %1
     %6:sampler = load %2
     %7:f32 = convert 4u