[tint][ir] Serialize Bitcast instructions

Change-Id: Ibc4e812367b10268c4bc431e3f47e7a63ecec443
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/165061
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/lang/core/ir/binary/decode.cc b/src/tint/lang/core/ir/binary/decode.cc
index 99ff03c..ef0c385 100644
--- a/src/tint/lang/core/ir/binary/decode.cc
+++ b/src/tint/lang/core/ir/binary/decode.cc
@@ -245,6 +245,9 @@
             case pb::Instruction::KindCase::kBinary:
                 inst_out = CreateInstructionBinary(inst_in.binary());
                 break;
+            case pb::Instruction::KindCase::kBitcast:
+                inst_out = CreateInstructionBitcast(inst_in.bitcast());
+                break;
             case pb::Instruction::KindCase::kBreakIf:
                 inst_out = CreateInstructionBreakIf(inst_in.break_if());
                 break;
@@ -345,6 +348,10 @@
         return binary_out;
     }
 
+    ir::Bitcast* CreateInstructionBitcast(const pb::InstructionBitcast&) {
+        return mod_out_.instructions.Create<ir::Bitcast>();
+    }
+
     ir::BreakIf* CreateInstructionBreakIf(const pb::InstructionBreakIf&) {
         auto* break_if_out = mod_out_.instructions.Create<ir::BreakIf>();
         break_ifs_.Push(break_if_out);
diff --git a/src/tint/lang/core/ir/binary/encode.cc b/src/tint/lang/core/ir/binary/encode.cc
index f87005f..ab00cd7 100644
--- a/src/tint/lang/core/ir/binary/encode.cc
+++ b/src/tint/lang/core/ir/binary/encode.cc
@@ -36,6 +36,7 @@
 #include "src/tint/lang/core/constant/splat.h"
 #include "src/tint/lang/core/ir/access.h"
 #include "src/tint/lang/core/ir/binary.h"
+#include "src/tint/lang/core/ir/bitcast.h"
 #include "src/tint/lang/core/ir/break_if.h"
 #include "src/tint/lang/core/ir/construct.h"
 #include "src/tint/lang/core/ir/continue.h"
@@ -195,6 +196,7 @@
             inst_in,  //
             [&](const ir::Access* i) { InstructionAccess(*inst_out.mutable_access(), i); },
             [&](const ir::Binary* i) { InstructionBinary(*inst_out.mutable_binary(), i); },
+            [&](const ir::Bitcast* i) { InstructionBitcast(*inst_out.mutable_bitcast(), i); },
             [&](const ir::BreakIf* i) { InstructionBreakIf(*inst_out.mutable_break_if(), i); },
             [&](const ir::CoreBuiltinCall* i) {
                 InstructionBuiltinCall(*inst_out.mutable_builtin_call(), i);
@@ -243,6 +245,8 @@
         binary_out.set_op(BinaryOp(binary_in->Op()));
     }
 
+    void InstructionBitcast(pb::InstructionBitcast&, const ir::Bitcast*) {}
+
     void InstructionBreakIf(pb::InstructionBreakIf&, const ir::BreakIf*) {}
 
     void InstructionBuiltinCall(pb::InstructionBuiltinCall& call_out,
diff --git a/src/tint/lang/core/ir/binary/ir.proto b/src/tint/lang/core/ir/binary/ir.proto
index c6aad49..7bef497 100644
--- a/src/tint/lang/core/ir/binary/ir.proto
+++ b/src/tint/lang/core/ir/binary/ir.proto
@@ -240,25 +240,26 @@
         InstructionDiscard discard = 7;
         InstructionLet let = 8;
         InstructionVar var = 9;
-        InstructionConstruct construct = 10;
-        InstructionConvert convert = 11;
-        InstructionAccess access = 12;
-        InstructionUserCall user_call = 13;
-        InstructionBuiltinCall builtin_call = 14;
-        InstructionLoad load = 15;
-        InstructionStore store = 16;
-        InstructionLoadVectorElement load_vector_element = 17;
-        InstructionStoreVectorElement store_vector_element = 18;
-        InstructionSwizzle swizzle = 19;
-        InstructionIf if = 20;
-        InstructionSwitch switch = 21;
-        InstructionLoop loop = 22;
-        InstructionExitIf exit_if = 23;
-        InstructionExitSwitch exit_switch = 24;
-        InstructionExitLoop exit_loop = 25;
-        InstructionNextIteration next_iteration = 26;
-        InstructionContinue continue = 27;
-        InstructionBreakIf break_if = 28;
+        InstructionBitcast bitcast = 10;
+        InstructionConstruct construct = 11;
+        InstructionConvert convert = 12;
+        InstructionAccess access = 13;
+        InstructionUserCall user_call = 14;
+        InstructionBuiltinCall builtin_call = 15;
+        InstructionLoad load = 16;
+        InstructionStore store = 17;
+        InstructionLoadVectorElement load_vector_element = 18;
+        InstructionStoreVectorElement store_vector_element = 19;
+        InstructionSwizzle swizzle = 20;
+        InstructionIf if = 21;
+        InstructionSwitch switch = 22;
+        InstructionLoop loop = 23;
+        InstructionExitIf exit_if = 24;
+        InstructionExitSwitch exit_switch = 25;
+        InstructionExitLoop exit_loop = 26;
+        InstructionNextIteration next_iteration = 27;
+        InstructionContinue continue = 28;
+        InstructionBreakIf break_if = 29;
     }
 }
 
@@ -274,7 +275,9 @@
 
 message InstructionBuiltin {}
 
-message InstructionConstructor {}
+message InstructionBitcast {}
+
+message InstructionConstruct {}
 
 message InstructionDiscard {}
 
@@ -284,8 +287,6 @@
     optional BindingPoint binding_point = 1;
 }
 
-message InstructionConstruct {}
-
 message InstructionConvert {}
 
 message InstructionAccess {}
diff --git a/src/tint/lang/core/ir/binary/roundtrip_test.cc b/src/tint/lang/core/ir/binary/roundtrip_test.cc
index 1647965..3caae35 100644
--- a/src/tint/lang/core/ir/binary/roundtrip_test.cc
+++ b/src/tint/lang/core/ir/binary/roundtrip_test.cc
@@ -532,6 +532,14 @@
     RUN_TEST();
 }
 
+TEST_F(IRBinaryRoundtripTest, Bitcast) {
+    auto* x = b.FunctionParam<vec4<f32>>("x");
+    auto* fn = b.Function("Function", ty.vec4<u32>());
+    fn->SetParams({x});
+    b.Append(fn->Block(), [&] { b.Return(fn, b.Bitcast<vec4<u32>>(x)); });
+    RUN_TEST();
+}
+
 TEST_F(IRBinaryRoundtripTest, Convert) {
     auto* x = b.FunctionParam<vec4<f32>>("x");
     auto* fn = b.Function("Function", ty.vec4<u32>());
diff --git a/src/tint/lang/core/ir/bitcast.cc b/src/tint/lang/core/ir/bitcast.cc
index 26031a47..8c6ece5 100644
--- a/src/tint/lang/core/ir/bitcast.cc
+++ b/src/tint/lang/core/ir/bitcast.cc
@@ -34,6 +34,8 @@
 
 namespace tint::core::ir {
 
+Bitcast::Bitcast() = default;
+
 Bitcast::Bitcast(InstructionResult* result, Value* val) {
     AddOperand(Bitcast::kValueOperandOffset, val);
     AddResult(result);
diff --git a/src/tint/lang/core/ir/bitcast.h b/src/tint/lang/core/ir/bitcast.h
index 3526681..ad30e92 100644
--- a/src/tint/lang/core/ir/bitcast.h
+++ b/src/tint/lang/core/ir/bitcast.h
@@ -41,6 +41,9 @@
     /// The offset in Operands() for the value
     static constexpr size_t kValueOperandOffset = 0;
 
+    /// Constructor (no results, no operands)
+    Bitcast();
+
     /// Constructor
     /// @param result the result value
     /// @param val the value being bitcast