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 {...@@ -1217,19 +1217,37 @@ pub const DeclGen = struct {
1217 const error_ty = ty.errorUnionSet();1217 const error_ty = ty.errorUnionSet();
1218 const payload_ty = ty.errorUnionPayload();1218 const payload_ty = ty.errorUnionPayload();
1219 const is_pl = val.errorUnionIsPayload();1219 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 {
1222 switch (try self.genTypedValue(error_ty, err_val)) {1223 const err_val = if (!is_pl) val else Value.initTag(.zero);
1223 .externally_managed => |data| try writer.writeAll(data),1224 const start = self.code.items.len;
1224 .appended => {},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 }
1225 }1235 }
12261236
1227 if (payload_ty.hasRuntimeBits()) {1237 if (payload_ty.hasRuntimeBits()) {
1238 const start = self.code.items.len;
1228 const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);1239 const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
1229 switch (try self.genTypedValue(payload_ty, pl_val)) {1240 switch (try self.genTypedValue(payload_ty, pl_val)) {
1230 .externally_managed => |data| try writer.writeAll(data),1241 .externally_managed => |data| try writer.writeAll(data),
1231 .appended => {},1242 .appended => {},
1232 }1243 }
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 }
1233 }1251 }
12341252
1235 return Result{ .appended = {} };1253 return Result{ .appended = {} };
...@@ -2065,15 +2083,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {...@@ -2065,15 +2083,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
2065 decl.markAlive();2083 decl.markAlive();
2066 const target_sym_index = decl.link.wasm.sym_index;2084 const target_sym_index = decl.link.wasm.sym_index;
2067 if (ty.isSlice()) {2085 if (ty.isSlice()) {
2068 var slice_len: Value.Payload.U64 = .{2086 return WValue{ .memory = try self.bin_file.lowerUnnamedConst(self.decl, .{ .ty = ty, .val = val }) };
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);
2077 } else if (decl.ty.zigTypeTag() == .Fn) {2087 } else if (decl.ty.zigTypeTag() == .Fn) {
2078 try self.bin_file.addTableFunction(target_sym_index);2088 try self.bin_file.addTableFunction(target_sym_index);
2079 return WValue{ .function_index = target_sym_index };2089 return WValue{ .function_index = target_sym_index };
...@@ -2702,11 +2712,13 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue...@@ -2702,11 +2712,13 @@ fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue
2702 const err_ty = self.air.typeOf(ty_op.operand);2712 const err_ty = self.air.typeOf(ty_op.operand);
2703 const payload_ty = err_ty.errorUnionPayload();2713 const payload_ty = err_ty.errorUnionPayload();
2704 if (!payload_ty.hasRuntimeBits()) return WValue{ .none = {} };2714 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);
2706 if (isByRef(payload_ty, self.target)) {2718 if (isByRef(payload_ty, self.target)) {
2707 return self.buildPointerOffset(operand, offset, .new);2719 return self.buildPointerOffset(operand, offset, .new);
2708 }2720 }
2709 return self.load(operand, payload_ty, offset);2721 return self.load(operand, payload_ty, @intCast(u32, offset));
2710}2722}
27112723
2712fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue {2724fn airUnwrapErrUnionError(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
...@@ -2732,7 +2744,9 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {...@@ -2732,7 +2744,9 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
2732 const op_ty = self.air.typeOf(ty_op.operand);2744 const op_ty = self.air.typeOf(ty_op.operand);
2733 if (!op_ty.hasRuntimeBits()) return operand;2745 if (!op_ty.hasRuntimeBits()) return operand;
2734 const err_ty = self.air.getRefType(ty_op.ty);2746 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
2737 const err_union = try self.allocStack(err_ty);2751 const err_union = try self.allocStack(err_ty);
2738 const payload_ptr = try self.buildPointerOffset(err_union, offset, .new);2752 const payload_ptr = try self.buildPointerOffset(err_union, offset, .new);