aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2022-02-23 23:43:51 +0100
committerLuuk de Gram <luuk@degram.dev>2022-02-25 09:33:15 +0100
commit0147eb9b5814379816524aa0c73685c49d12192d (patch)
tree092ef244769e0ef81891a3e1057151d6ce0cd6d3 /src
parentf4adb53bcfff18c24758bf4ea2968efd17911e02 (diff)
downloadzig-0147eb9b5814379816524aa0c73685c49d12192d.tar.gz
zig-0147eb9b5814379816524aa0c73685c49d12192d.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/arch/wasm/CodeGen.zig46
1 files 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);