HLSL-IR: workaround DXC bug when 'as' casting constant integral splats

DXC asserts because constant integral splats are 64-bit values, but 'as'
functions emit bitcasts that expect src and dst bit widths to be the
same. Work around this by wrapping the splat with an explicit
constructor call to make it 32-bit.

Bug: b/361794783
Change-Id: Ib33bb065f78a5c7cfd8f9c2b0dde330e0ad6b01c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/205915
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/tint/lang/core/type/type.cc b/src/tint/lang/core/type/type.cc
index dbb50f8..29069bd 100644
--- a/src/tint/lang/core/type/type.cc
+++ b/src/tint/lang/core/type/type.cc
@@ -108,6 +108,10 @@
     return IsAnyOf<U32, I32>();
 }
 
+bool Type::IsIntegerVector() const {
+    return Is([](const Vector* v) { return v->Type()->IsIntegerScalar(); });
+}
+
 bool Type::IsSignedIntegerScalar() const {
     return IsAnyOf<I32, AbstractInt>();
 }
diff --git a/src/tint/lang/core/type/type.h b/src/tint/lang/core/type/type.h
index 5124d76..d263428 100644
--- a/src/tint/lang/core/type/type.h
+++ b/src/tint/lang/core/type/type.h
@@ -139,6 +139,8 @@
     bool IsFloatScalarOrVector() const;
     /// @returns true if this type is an integer scalar
     bool IsIntegerScalar() const;
+    /// @returns true if this type is a integer vector
+    bool IsIntegerVector() const;
     /// @returns true if this type is an integer scalar or vector
     bool IsIntegerScalarOrVector() const;
     /// @returns true if this type is a signed integer scalar
diff --git a/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc b/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
index 7253143..79e4e0d 100644
--- a/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
@@ -551,8 +551,23 @@
             [&](const core::type::F32*) { fn = BuiltinFn::kAsfloat; },  //
             TINT_ICE_ON_NO_MATCH);
 
+        // TODO(crbug.com/361794783): work around DXC failing on 'as' casts of constant integral
+        // splats by wrapping it with an explicit vector constructor.
+        // e.g. asuint(123.xx) -> asuint(int2(123.xx)))
+        bool castToSrcType = false;
+        auto* src_type = bitcast->Val()->Type();
+        if (src_type->IsIntegerVector()) {
+            if (auto* c = bitcast->Val()->As<core::ir::Constant>()) {
+                castToSrcType = c->Value()->Is<core::constant::Splat>();
+            }
+        }
+
         b.InsertBefore(bitcast, [&] {
-            b.CallWithResult<hlsl::ir::BuiltinCall>(bitcast->DetachResult(), fn, bitcast->Val());
+            auto* source = bitcast->Val();
+            if (castToSrcType) {
+                source = b.Construct(src_type, source)->Result(0);
+            }
+            b.CallWithResult<hlsl::ir::BuiltinCall>(bitcast->DetachResult(), fn, source);
         });
         bitcast->Destroy();
     }
diff --git a/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.ir.dxc.hlsl b/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.ir.dxc.hlsl
index fae7a07..3a7f37f 100644
--- a/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.ir.dxc.hlsl
+++ b/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.ir.dxc.hlsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 struct main_inputs {
   uint idx : SV_GroupIndex;
 };
@@ -87,17 +85,17 @@
   uint v_14 = (16u + (uint(idx) * 544u));
   sb.Store2(v_14, asuint((0.0f).xx));
   uint v_15 = (24u + (uint(idx) * 544u));
-  sb.Store2(v_15, asuint((0).xx));
+  sb.Store2(v_15, asuint(int2((0).xx)));
   sb.Store2((32u + (uint(idx) * 544u)), (0u).xx);
   uint v_16 = (48u + (uint(idx) * 544u));
   sb.Store3(v_16, asuint((0.0f).xxx));
   uint v_17 = (64u + (uint(idx) * 544u));
-  sb.Store3(v_17, asuint((0).xxx));
+  sb.Store3(v_17, asuint(int3((0).xxx)));
   sb.Store3((80u + (uint(idx) * 544u)), (0u).xxx);
   uint v_18 = (96u + (uint(idx) * 544u));
   sb.Store4(v_18, asuint((0.0f).xxxx));
   uint v_19 = (112u + (uint(idx) * 544u));
-  sb.Store4(v_19, asuint((0).xxxx));
+  sb.Store4(v_19, asuint(int4((0).xxxx)));
   sb.Store4((128u + (uint(idx) * 544u)), (0u).xxxx);
   v_11((144u + (uint(idx) * 544u)), float2x2((0.0f).xx, (0.0f).xx));
   v_10((160u + (uint(idx) * 544u)), float2x3((0.0f).xxx, (0.0f).xxx));
@@ -117,5 +115,3 @@
   main_inner(inputs.idx);
 }
 
-
-tint executable returned error: exit status 0xe0000001
diff --git a/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.ir.fxc.hlsl b/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.ir.fxc.hlsl
index c030f6a..3a7f37f 100644
--- a/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.ir.fxc.hlsl
+++ b/test/tint/buffer/storage/dynamic_index/write.wgsl.expected.ir.fxc.hlsl
@@ -85,17 +85,17 @@
   uint v_14 = (16u + (uint(idx) * 544u));
   sb.Store2(v_14, asuint((0.0f).xx));
   uint v_15 = (24u + (uint(idx) * 544u));
-  sb.Store2(v_15, asuint((0).xx));
+  sb.Store2(v_15, asuint(int2((0).xx)));
   sb.Store2((32u + (uint(idx) * 544u)), (0u).xx);
   uint v_16 = (48u + (uint(idx) * 544u));
   sb.Store3(v_16, asuint((0.0f).xxx));
   uint v_17 = (64u + (uint(idx) * 544u));
-  sb.Store3(v_17, asuint((0).xxx));
+  sb.Store3(v_17, asuint(int3((0).xxx)));
   sb.Store3((80u + (uint(idx) * 544u)), (0u).xxx);
   uint v_18 = (96u + (uint(idx) * 544u));
   sb.Store4(v_18, asuint((0.0f).xxxx));
   uint v_19 = (112u + (uint(idx) * 544u));
-  sb.Store4(v_19, asuint((0).xxxx));
+  sb.Store4(v_19, asuint(int4((0).xxxx)));
   sb.Store4((128u + (uint(idx) * 544u)), (0u).xxxx);
   v_11((144u + (uint(idx) * 544u)), float2x2((0.0f).xx, (0.0f).xx));
   v_10((160u + (uint(idx) * 544u)), float2x3((0.0f).xxx, (0.0f).xxx));
diff --git a/test/tint/buffer/storage/dynamic_index/write_f16.wgsl.expected.ir.dxc.hlsl b/test/tint/buffer/storage/dynamic_index/write_f16.wgsl.expected.ir.dxc.hlsl
index 8594b33..3061330 100644
--- a/test/tint/buffer/storage/dynamic_index/write_f16.wgsl.expected.ir.dxc.hlsl
+++ b/test/tint/buffer/storage/dynamic_index/write_f16.wgsl.expected.ir.dxc.hlsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 struct main_inputs {
   uint idx : SV_GroupIndex;
 };
@@ -160,19 +158,19 @@
   uint v_26 = (16u + (uint(idx) * 800u));
   sb.Store2(v_26, asuint((0.0f).xx));
   uint v_27 = (24u + (uint(idx) * 800u));
-  sb.Store2(v_27, asuint((0).xx));
+  sb.Store2(v_27, asuint(int2((0).xx)));
   sb.Store2((32u + (uint(idx) * 800u)), (0u).xx);
   sb.Store<vector<float16_t, 2> >((40u + (uint(idx) * 800u)), (float16_t(0.0h)).xx);
   uint v_28 = (48u + (uint(idx) * 800u));
   sb.Store3(v_28, asuint((0.0f).xxx));
   uint v_29 = (64u + (uint(idx) * 800u));
-  sb.Store3(v_29, asuint((0).xxx));
+  sb.Store3(v_29, asuint(int3((0).xxx)));
   sb.Store3((80u + (uint(idx) * 800u)), (0u).xxx);
   sb.Store<vector<float16_t, 3> >((96u + (uint(idx) * 800u)), (float16_t(0.0h)).xxx);
   uint v_30 = (112u + (uint(idx) * 800u));
   sb.Store4(v_30, asuint((0.0f).xxxx));
   uint v_31 = (128u + (uint(idx) * 800u));
-  sb.Store4(v_31, asuint((0).xxxx));
+  sb.Store4(v_31, asuint(int4((0).xxxx)));
   sb.Store4((144u + (uint(idx) * 800u)), (0u).xxxx);
   sb.Store<vector<float16_t, 4> >((160u + (uint(idx) * 800u)), (float16_t(0.0h)).xxxx);
   v_23((168u + (uint(idx) * 800u)), float2x2((0.0f).xx, (0.0f).xx));
@@ -204,5 +202,3 @@
   main_inner(inputs.idx);
 }
 
-
-tint executable returned error: exit status 0xe0000001
diff --git a/test/tint/buffer/storage/static_index/write.wgsl.expected.ir.dxc.hlsl b/test/tint/buffer/storage/static_index/write.wgsl.expected.ir.dxc.hlsl
index b717b29..e1d50db 100644
--- a/test/tint/buffer/storage/static_index/write.wgsl.expected.ir.dxc.hlsl
+++ b/test/tint/buffer/storage/static_index/write.wgsl.expected.ir.dxc.hlsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 struct Inner {
   int scalar_i32;
   float scalar_f32;
@@ -109,13 +107,13 @@
   sb.Store(4u, asuint(0));
   sb.Store(8u, 0u);
   sb.Store2(16u, asuint((0.0f).xx));
-  sb.Store2(24u, asuint((0).xx));
+  sb.Store2(24u, asuint(int2((0).xx)));
   sb.Store2(32u, (0u).xx);
   sb.Store3(48u, asuint((0.0f).xxx));
-  sb.Store3(64u, asuint((0).xxx));
+  sb.Store3(64u, asuint(int3((0).xxx)));
   sb.Store3(80u, (0u).xxx);
   sb.Store4(96u, asuint((0.0f).xxxx));
-  sb.Store4(112u, asuint((0).xxxx));
+  sb.Store4(112u, asuint(int4((0).xxxx)));
   sb.Store4(128u, (0u).xxxx);
   v_16(144u, float2x2((0.0f).xx, (0.0f).xx));
   v_15(160u, float2x3((0.0f).xxx, (0.0f).xxx));
@@ -134,5 +132,3 @@
   v_1(552u, v_19);
 }
 
-
-tint executable returned error: exit status 0xe0000001
diff --git a/test/tint/buffer/storage/static_index/write.wgsl.expected.ir.fxc.hlsl b/test/tint/buffer/storage/static_index/write.wgsl.expected.ir.fxc.hlsl
index cc50f2f..e1d50db 100644
--- a/test/tint/buffer/storage/static_index/write.wgsl.expected.ir.fxc.hlsl
+++ b/test/tint/buffer/storage/static_index/write.wgsl.expected.ir.fxc.hlsl
@@ -107,13 +107,13 @@
   sb.Store(4u, asuint(0));
   sb.Store(8u, 0u);
   sb.Store2(16u, asuint((0.0f).xx));
-  sb.Store2(24u, asuint((0).xx));
+  sb.Store2(24u, asuint(int2((0).xx)));
   sb.Store2(32u, (0u).xx);
   sb.Store3(48u, asuint((0.0f).xxx));
-  sb.Store3(64u, asuint((0).xxx));
+  sb.Store3(64u, asuint(int3((0).xxx)));
   sb.Store3(80u, (0u).xxx);
   sb.Store4(96u, asuint((0.0f).xxxx));
-  sb.Store4(112u, asuint((0).xxxx));
+  sb.Store4(112u, asuint(int4((0).xxxx)));
   sb.Store4(128u, (0u).xxxx);
   v_16(144u, float2x2((0.0f).xx, (0.0f).xx));
   v_15(160u, float2x3((0.0f).xxx, (0.0f).xxx));
diff --git a/test/tint/buffer/storage/static_index/write_f16.wgsl.expected.ir.dxc.hlsl b/test/tint/buffer/storage/static_index/write_f16.wgsl.expected.ir.dxc.hlsl
index 4bbe1ea..b9cd59f 100644
--- a/test/tint/buffer/storage/static_index/write_f16.wgsl.expected.ir.dxc.hlsl
+++ b/test/tint/buffer/storage/static_index/write_f16.wgsl.expected.ir.dxc.hlsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 struct Inner {
   int scalar_i32;
   float scalar_f32;
@@ -184,15 +182,15 @@
   sb.Store(8u, 0u);
   sb.Store<float16_t>(12u, float16_t(0.0h));
   sb.Store2(16u, asuint((0.0f).xx));
-  sb.Store2(24u, asuint((0).xx));
+  sb.Store2(24u, asuint(int2((0).xx)));
   sb.Store2(32u, (0u).xx);
   sb.Store<vector<float16_t, 2> >(40u, (float16_t(0.0h)).xx);
   sb.Store3(48u, asuint((0.0f).xxx));
-  sb.Store3(64u, asuint((0).xxx));
+  sb.Store3(64u, asuint(int3((0).xxx)));
   sb.Store3(80u, (0u).xxx);
   sb.Store<vector<float16_t, 3> >(96u, (float16_t(0.0h)).xxx);
   sb.Store4(112u, asuint((0.0f).xxxx));
-  sb.Store4(128u, asuint((0).xxxx));
+  sb.Store4(128u, asuint(int4((0).xxxx)));
   sb.Store4(144u, (0u).xxxx);
   sb.Store<vector<float16_t, 4> >(160u, (float16_t(0.0h)).xxxx);
   v_28(168u, float2x2((0.0f).xx, (0.0f).xx));
@@ -223,5 +221,3 @@
   v_1(812u, v_32);
 }
 
-
-tint executable returned error: exit status 0xe0000001
diff --git a/test/tint/bug/tint/2029.wgsl.expected.ir.dxc.hlsl b/test/tint/bug/tint/2029.wgsl.expected.ir.dxc.hlsl
index bb5ad50..fe52f09 100644
--- a/test/tint/bug/tint/2029.wgsl.expected.ir.dxc.hlsl
+++ b/test/tint/bug/tint/2029.wgsl.expected.ir.dxc.hlsl
@@ -1,11 +1,7 @@
-SKIP: FAILED
-
 
 RWByteAddressBuffer s : register(u0);
 [numthreads(1, 1, 1)]
 void main() {
-  s.Store3(0u, asuint((1).xxx));
+  s.Store3(0u, asuint(int3((1).xxx)));
 }
 
-
-tint executable returned error: exit status 0xe0000001
diff --git a/test/tint/bug/tint/2029.wgsl.expected.ir.fxc.hlsl b/test/tint/bug/tint/2029.wgsl.expected.ir.fxc.hlsl
index 22c8d7b..fe52f09 100644
--- a/test/tint/bug/tint/2029.wgsl.expected.ir.fxc.hlsl
+++ b/test/tint/bug/tint/2029.wgsl.expected.ir.fxc.hlsl
@@ -2,6 +2,6 @@
 RWByteAddressBuffer s : register(u0);
 [numthreads(1, 1, 1)]
 void main() {
-  s.Store3(0u, asuint((1).xxx));
+  s.Store3(0u, asuint(int3((1).xxx)));
 }