From 0147eb9b5814379816524aa0c73685c49d12192d Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Wed, 23 Feb 2022 23:43:51 +0100 Subject: [PATCH] wasm: Fix error union's size/alignment Previously error unions were packed in memory. Now each 'field' is correctly aligned to the error union's alignment. --- src/arch/wasm/CodeGen.zig | 46 +++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 01b297d9e8..c99b44e612 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1217,19 +1217,37 @@ pub const DeclGen = struct { const error_ty = ty.errorUnionSet(); const payload_ty = ty.errorUnionPayload(); const is_pl = val.errorUnionIsPayload(); + const abi_align = ty.abiAlignment(self.target()); - const err_val = if (!is_pl) val else Value.initTag(.zero); - switch (try self.genTypedValue(error_ty, err_val)) { - .externally_managed => |data| try writer.writeAll(data), - .appended => {}, + { + const err_val = if (!is_pl) val else Value.initTag(.zero); + const start = self.code.items.len; + switch (try self.genTypedValue(error_ty, err_val)) { + .externally_managed => |data| try writer.writeAll(data), + .appended => {}, + } + const unpadded_end = self.code.items.len - start; + const padded_end = mem.alignForwardGeneric(usize, unpadded_end, abi_align); + const padding = padded_end - unpadded_end; + if (padding > 0) { + try writer.writeByteNTimes(0, padding); + } } if (payload_ty.hasRuntimeBits()) { + const start = self.code.items.len; const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef); switch (try self.genTypedValue(payload_ty, pl_val)) { .externally_managed => |data| try writer.writeAll(data), .appended => {}, } + + const unpadded_end = self.code.items.len - start; + const padded_end = mem.alignForwardGeneric(usize, unpadded_end, abi_align); + const padding = padded_end - unpadded_end; + if (padding > 0) { + try writer.writeByteNTimes(0, padding); + } } return Result{ .appended = {} }; @@ -2065,15 +2083,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue { decl.markAlive(); const target_sym_index = decl.link.wasm.sym_index; if (ty.isSlice()) { - var slice_len: Value.Payload.U64 = .{ - .base = .{ .tag = .int_u64 }, - .data = val.sliceLen(), - }; - var slice_val: Value.Payload.Slice = .{ - .base = .{ .tag = .slice }, - .data = .{ .ptr = val.slicePtr(), .len = Value.initPayload(&slice_len.base) }, - }; - return self.lowerConstant(Value.initPayload(&slice_val.base), ty); + return WValue{ .memory = try self.bin_file.lowerUnnamedConst(self.decl, .{ .ty = ty, .val = val }) }; } else if (decl.ty.zigTypeTag() == .Fn) { try self.bin_file.addTableFunction(target_sym_index); return WValue{ .function_index = target_sym_index }; @@ -2702,11 +2712,13 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue const err_ty = self.air.typeOf(ty_op.operand); const payload_ty = err_ty.errorUnionPayload(); if (!payload_ty.hasRuntimeBits()) return WValue{ .none = {} }; - const offset = @intCast(u32, err_ty.errorUnionSet().abiSize(self.target)); + const err_align = err_ty.abiAlignment(self.target); + const set_size = err_ty.errorUnionSet().abiSize(self.target); + const offset = mem.alignForwardGeneric(u64, set_size, err_align); if (isByRef(payload_ty, self.target)) { return self.buildPointerOffset(operand, offset, .new); } - return self.load(operand, payload_ty, offset); + return self.load(operand, payload_ty, @intCast(u32, offset)); } fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue { @@ -2732,7 +2744,9 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue { const op_ty = self.air.typeOf(ty_op.operand); if (!op_ty.hasRuntimeBits()) return operand; const err_ty = self.air.getRefType(ty_op.ty); - const offset = err_ty.errorUnionSet().abiSize(self.target); + const err_align = err_ty.abiAlignment(self.target); + const set_size = err_ty.errorUnionSet().abiSize(self.target); + const offset = mem.alignForwardGeneric(u64, set_size, err_align); const err_union = try self.allocStack(err_ty); const payload_ptr = try self.buildPointerOffset(err_union, offset, .new);