aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-03-19 16:32:07 +0100
committerLuuk de Gram <luuk@degram.dev>2022-03-19 20:56:03 +0100
commit2041176c5e7d2b469c2fe0168e142fe8f322b9bc (patch)
tree1868288991f3288032fd38bb9674ec838b4b716e /src
parent69e6d455ce8e21835ec3ce268a0533e0e7666e8b (diff)
downloadzig-2041176c5e7d2b469c2fe0168e142fe8f322b9bc.tar.gz
zig-2041176c5e7d2b469c2fe0168e142fe8f322b9bc.zip
wasm: Implement `union_init` instruction
Implements the `@unionInit` builtin instruction.
Diffstat (limited to 'src')
-rw-r--r--src/arch/wasm/CodeGen.zig29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index 685528c05d..4f5855c93b 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -3221,7 +3221,34 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
fn airUnionInit(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
- return self.fail("TODO: Wasm backend: implement airUnionInit", .{});
+
+ const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
+ const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
+ const union_ty = self.air.typeOfIndex(inst);
+ const layout = union_ty.unionGetLayout(self.target);
+ if (layout.payload_size == 0) {
+ if (layout.tag_size == 0) {
+ return WValue{ .none = {} };
+ }
+ assert(!isByRef(union_ty, self.target));
+ return WValue{ .imm32 = extra.field_index };
+ }
+ assert(isByRef(union_ty, self.target));
+
+ const result_ptr = try self.allocStack(union_ty);
+ const payload = try self.resolveInst(extra.init);
+ const union_obj = union_ty.cast(Type.Payload.Union).?.data;
+ assert(union_obj.haveFieldTypes());
+ const field = union_obj.fields.values()[extra.field_index];
+
+ if (layout.tag_align >= layout.payload_align) {
+ const payload_ptr = try self.buildPointerOffset(result_ptr, layout.tag_size, .new);
+ try self.store(payload_ptr, payload, field.ty, 0);
+ } else {
+ try self.store(result_ptr, payload, field.ty, 0);
+ }
+
+ return result_ptr;
}
fn airPrefetch(self: *Self, inst: Air.Inst.Index) InnerError!WValue {