authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-02-23 23:43:51+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-02-25 09:33:15+01:00
log0147eb9b5814379816524aa0c73685c49d12192d
tree092ef244769e0ef81891a3e1057151d6ce0cd6d3
parentf4adb53bcfff18c24758bf4ea2968efd17911e02

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.

1 files changed, 30 insertions(+), 16 deletions(-)

src/arch/wasm/CodeGen.zig+30-16
......@@ -1217,19 +1217,37 @@ pub const DeclGen = struct {
12171217 const error_ty = ty.errorUnionSet();
12181218 const payload_ty = ty.errorUnionPayload();
12191219 const is_pl = val.errorUnionIsPayload();
1220 const abi_align = ty.abiAlignment(self.target());
12201221
1221 const err_val = if (!is_pl) val else Value.initTag(.zero);
1222 switch (try self.genTypedValue(error_ty, err_val)) {
1223 .externally_managed => |data| try writer.writeAll(data),
1224 .appended => {},
1222 {
1223 const err_val = if (!is_pl) val else Value.initTag(.zero);
1224 const start = self.code.items.len;
1225 switch (try self.genTypedValue(error_ty, err_val)) {
1226 .externally_managed => |data| try writer.writeAll(data),
1227 .appended => {},
1228 }
1229 const unpadded_end = self.code.items.len - start;
1230 const padded_end = mem.alignForwardGeneric(usize, unpadded_end, abi_align);
1231 const padding = padded_end - unpadded_end;
1232 if (padding > 0) {
1233 try writer.writeByteNTimes(0, padding);
1234 }
12251235 }
12261236
12271237 if (payload_ty.hasRuntimeBits()) {
1238 const start = self.code.items.len;
12281239 const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
12291240 switch (try self.genTypedValue(payload_ty, pl_val)) {
12301241 .externally_managed => |data| try writer.writeAll(data),
12311242 .appended => {},
12321243 }
1244
1245 const unpadded_end = self.code.items.len - start;
1246 const padded_end = mem.alignForwardGeneric(usize, unpadded_end, abi_align);
1247 const padding = padded_end - unpadded_end;
1248 if (padding > 0) {
1249 try writer.writeByteNTimes(0, padding);
1250 }
12331251 }
12341252
12351253 return Result{ .appended = {} };
......@@ -2065,15 +2083,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
20652083 decl.markAlive();
20662084 const target_sym_index = decl.link.wasm.sym_index;
20672085 if (ty.isSlice()) {
2068 var slice_len: Value.Payload.U64 = .{
2069 .base = .{ .tag = .int_u64 },
2070 .data = val.sliceLen(),
2071 };
2072 var slice_val: Value.Payload.Slice = .{
2073 .base = .{ .tag = .slice },
2074 .data = .{ .ptr = val.slicePtr(), .len = Value.initPayload(&slice_len.base) },
2075 };
2076 return self.lowerConstant(Value.initPayload(&slice_val.base), ty);
2086 return WValue{ .memory = try self.bin_file.lowerUnnamedConst(self.decl, .{ .ty = ty, .val = val }) };
20772087 } else if (decl.ty.zigTypeTag() == .Fn) {
20782088 try self.bin_file.addTableFunction(target_sym_index);
20792089 return WValue{ .function_index = target_sym_index };
......@@ -2702,11 +2712,13 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue
27022712 const err_ty = self.air.typeOf(ty_op.operand);
27032713 const payload_ty = err_ty.errorUnionPayload();
27042714 if (!payload_ty.hasRuntimeBits()) return WValue{ .none = {} };
2705 const offset = @intCast(u32, err_ty.errorUnionSet().abiSize(self.target));
2715 const err_align = err_ty.abiAlignment(self.target);
2716 const set_size = err_ty.errorUnionSet().abiSize(self.target);
2717 const offset = mem.alignForwardGeneric(u64, set_size, err_align);
27062718 if (isByRef(payload_ty, self.target)) {
27072719 return self.buildPointerOffset(operand, offset, .new);
27082720 }
2709 return self.load(operand, payload_ty, offset);
2721 return self.load(operand, payload_ty, @intCast(u32, offset));
27102722}
27112723
27122724fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
......@@ -2732,7 +2744,9 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
27322744 const op_ty = self.air.typeOf(ty_op.operand);
27332745 if (!op_ty.hasRuntimeBits()) return operand;
27342746 const err_ty = self.air.getRefType(ty_op.ty);
2735 const offset = err_ty.errorUnionSet().abiSize(self.target);
2747 const err_align = err_ty.abiAlignment(self.target);
2748 const set_size = err_ty.errorUnionSet().abiSize(self.target);
2749 const offset = mem.alignForwardGeneric(u64, set_size, err_align);
27362750
27372751 const err_union = try self.allocStack(err_ty);
27382752 const payload_ptr = try self.buildPointerOffset(err_union, offset, .new);