From 1777fb25bc37c626fee91e88feeafa28f177628a Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Tue, 30 Nov 2021 20:12:34 +0100 Subject: wasm: Implement WrapErrorUnionErr(payload) --- src/arch/wasm/CodeGen.zig | 37 ++++++++++++++++++++++++++++--------- src/link/Wasm.zig | 12 +++++++----- 2 files changed, 35 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 3f75056e59..421c95846d 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1148,6 +1148,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .unwrap_errunion_payload => self.airUnwrapErrUnionPayload(inst), .unwrap_errunion_err => self.airUnwrapErrUnionError(inst), .wrap_errunion_payload => self.airWrapErrUnionPayload(inst), + .wrap_errunion_err => self.airWrapErrUnionErr(inst), .optional_payload => self.airOptionalPayload(inst), .optional_payload_ptr => self.airOptionalPayload(inst), @@ -1328,16 +1329,15 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro return; }, .local => { - // Load values from `rhs` stack position and store in `lhs` instead - const tag_local = try self.load(rhs, tag_ty, 0); - const payload_local = try self.load(rhs, payload_ty, payload_offset); - - try self.store(lhs, tag_local, tag_ty, 0); - return try self.store(lhs, payload_local, payload_ty, payload_offset); + if (payload_ty.hasCodeGenBits()) { + try self.store(lhs, rhs, payload_ty, payload_offset); + } + return try self.store(lhs, rhs, tag_ty, 0); }, .local_with_offset => |with_offset| { const tag_local = try self.allocLocal(tag_ty); try self.addImm32(0); + try self.addLabel(.local_set, tag_local.local); try self.store(lhs, tag_local, tag_ty, 0); return try self.store( @@ -1415,7 +1415,10 @@ fn load(self: *Self, operand: WValue, ty: Type, offset: u32) InnerError!WValue { // load local's value from memory by its stack position try self.emitWValue(operand); // Build the opcode with the right bitsize - const signedness: std.builtin.Signedness = if (ty.isUnsignedInt()) .unsigned else .signed; + const signedness: std.builtin.Signedness = if (ty.isUnsignedInt() or ty.zigTypeTag() == .ErrorSet) + .unsigned + else + .signed; // check if we should pass by pointer or value based on ABI size // TODO: Implement a way to get ABI values from a given type, // that is portable across the backend, rather than copying logic. @@ -2081,9 +2084,25 @@ fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue { } fn airWrapErrUnionPayload(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 operand = self.resolveInst(ty_op.operand); + + const op_ty = self.air.typeOf(ty_op.operand); + if (!op_ty.hasCodeGenBits()) return WValue.none; + const err_ty = self.air.getRefType(ty_op.ty); + const offset = err_ty.errorUnionSet().abiSize(self.target); + + return WValue{ .local_with_offset = .{ + .local = operand.local, + .offset = @intCast(u32, offset), + } }; +} + +fn airWrapErrUnionErr(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; - _ = ty_op; - return self.fail("TODO: wasm airWrapErrUnionPayload", .{}); + return self.resolveInst(ty_op.operand); } fn airIntcast(self: *Self, inst: Air.Inst.Index) InnerError!WValue { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 367f3376f0..9a1b016102 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -162,9 +162,8 @@ pub fn deinit(self: *Wasm) void { decl.link.wasm.deinit(self.base.allocator); } - for (self.func_types.items) |func_type| { - self.base.allocator.free(func_type.params); - self.base.allocator.free(func_type.returns); + for (self.func_types.items) |*func_type| { + func_type.deinit(self.base.allocator); } for (self.segment_info.items) |segment_info| { self.base.allocator.free(segment_info.name); @@ -574,7 +573,6 @@ fn resetState(self: *Wasm) void { self.segments.clearRetainingCapacity(); self.segment_info.clearRetainingCapacity(); self.data_segments.clearRetainingCapacity(); - self.function_table.clearRetainingCapacity(); self.atoms.clearRetainingCapacity(); self.code_section_index = null; } @@ -684,12 +682,16 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { ); } + // Table section if (self.function_table.count() > 0) { const header_offset = try reserveVecSectionHeader(file); const writer = file.writer(); try leb.writeULEB128(writer, wasm.reftype(.funcref)); - try emitLimits(writer, .{ .min = 1, .max = null }); + try emitLimits(writer, .{ + .min = @intCast(u32, self.function_table.count()), + .max = null, + }); try writeVecSectionHeader( file, -- cgit v1.2.3