aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-01-22 14:11:12 +0100
committerLuuk de Gram <luuk@degram.dev>2022-01-25 19:00:51 +0100
commit288b407fa9c40addafe521862c3eef08c878b1f6 (patch)
tree0867a8654ad1250dcd1f844e1ced953fbd28971a /src
parent4b939fb34d3707258789e3ef71ff698a7d6bf552 (diff)
downloadzig-288b407fa9c40addafe521862c3eef08c878b1f6.tar.gz
zig-288b407fa9c40addafe521862c3eef08c878b1f6.zip
wasm: Implement get_union_tag
Diffstat (limited to 'src')
-rw-r--r--src/arch/wasm/CodeGen.zig20
1 files changed, 19 insertions, 1 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index c0398fab4d..c0800982d6 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -1419,6 +1419,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.dbg_stmt => WValue.none,
.intcast => self.airIntcast(inst),
.float_to_int => self.airFloatToInt(inst),
+ .get_union_tag => self.airGetUnionTag(inst),
.is_err => self.airIsErr(inst, .i32_ne),
.is_non_err => self.airIsErr(inst, .i32_eq),
@@ -1496,7 +1497,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.unwrap_errunion_payload_ptr,
.unwrap_errunion_err_ptr,
- .get_union_tag,
.ptr_slice_len_ptr,
.ptr_slice_ptr_ptr,
.int_to_float,
@@ -3202,3 +3202,21 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
try self.store(union_ptr, new_tag, tag_ty, offset);
return WValue{ .none = {} };
}
+
+fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
+ if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
+
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const un_ty = self.air.typeOf(ty_op.operand);
+ const tag_ty = self.air.typeOfIndex(inst);
+ const layout = un_ty.unionGetLayout(self.target);
+ if (layout.tag_size == 0) return WValue{ .none = {} };
+ const operand = try self.resolveInst(ty_op.operand);
+
+ // when the tag alignment is smaller than the payload, the field will be stored
+ // after the payload.
+ const offset = if (layout.tag_align < layout.payload_align) blk: {
+ break :blk @intCast(u32, layout.payload_size);
+ } else @as(u32, 0);
+ return self.load(operand, tag_ty, offset);
+}