diff options
| author | Luuk de Gram <luuk@degram.dev> | 2022-01-21 20:06:03 +0100 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2022-01-25 19:00:48 +0100 |
| commit | 4b939fb34d3707258789e3ef71ff698a7d6bf552 (patch) | |
| tree | 8546f676e6d5429eaba1e4b742b5aea81878a143 /src | |
| parent | 0817d6b2150a00ab0d552888fc4822fced8e0f5f (diff) | |
| download | zig-4b939fb34d3707258789e3ef71ff698a7d6bf552.tar.gz zig-4b939fb34d3707258789e3ef71ff698a7d6bf552.zip | |
wasm: Implement set_union_tag
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 29 |
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 = {} }; +} |
