aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-01-21 20:06:03 +0100
committerLuuk de Gram <luuk@degram.dev>2022-01-25 19:00:48 +0100
commit4b939fb34d3707258789e3ef71ff698a7d6bf552 (patch)
tree8546f676e6d5429eaba1e4b742b5aea81878a143 /src
parent0817d6b2150a00ab0d552888fc4822fced8e0f5f (diff)
downloadzig-4b939fb34d3707258789e3ef71ff698a7d6bf552.tar.gz
zig-4b939fb34d3707258789e3ef71ff698a7d6bf552.zip
wasm: Implement set_union_tag
Diffstat (limited to 'src')
-rw-r--r--src/arch/wasm/CodeGen.zig29
1 files changed, 27 insertions, 2 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index f69fea0b0a..c0398fab4d 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -1454,6 +1454,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.slice_ptr => self.airSlicePtr(inst),
.store => self.airStore(inst),
+ .set_union_tag => self.airSetUnionTag(inst),
.struct_field_ptr => self.airStructFieldPtr(inst),
.struct_field_ptr_index_0 => self.airStructFieldPtrIndex(inst, 0),
.struct_field_ptr_index_1 => self.airStructFieldPtrIndex(inst, 1),
@@ -1494,7 +1495,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.fpext,
.unwrap_errunion_payload_ptr,
.unwrap_errunion_err_ptr,
- .set_union_tag,
+
.get_union_tag,
.ptr_slice_len_ptr,
.ptr_slice_ptr_ptr,
@@ -1518,7 +1519,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
.sub_with_overflow,
.mul_with_overflow,
.shl_with_overflow,
- => |tag| self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
+ => |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}),
};
}
@@ -1596,6 +1597,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
break :blk func.data.owner_decl;
} else if (func_val.castTag(.extern_fn)) |ext_fn| {
break :blk ext_fn.data;
+ } else if (func_val.castTag(.decl_ref)) |decl_ref| {
+ break :blk decl_ref.data;
}
return self.fail("Expected a function, but instead found type '{s}'", .{func_val.tag()});
};
@@ -3177,3 +3180,25 @@ fn cmpBigInt(self: *Self, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.ma
try self.addLabel(.local_set, result.local);
return result;
}
+
+fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const un_ty = self.air.typeOf(bin_op.lhs).childType();
+ const tag_ty = self.air.typeOf(bin_op.rhs);
+ const layout = un_ty.unionGetLayout(self.target);
+ if (layout.tag_size == 0) return WValue{ .none = {} };
+ const union_ptr = try self.resolveInst(bin_op.lhs);
+ const new_tag = try self.resolveInst(bin_op.rhs);
+ if (layout.payload_size == 0) {
+ try self.store(union_ptr, new_tag, tag_ty, 0);
+ return WValue{ .none = {} };
+ }
+
+ // 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);
+ try self.store(union_ptr, new_tag, tag_ty, offset);
+ return WValue{ .none = {} };
+}