mirror of
https://github.com/ziglang/zig.git
synced 2025-12-14 10:13:07 +00:00
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.
This commit is contained in:
parent
f4adb53bcf
commit
0147eb9b58
@ -1217,19 +1217,37 @@ pub const DeclGen = struct {
|
|||||||
const error_ty = ty.errorUnionSet();
|
const error_ty = ty.errorUnionSet();
|
||||||
const payload_ty = ty.errorUnionPayload();
|
const payload_ty = ty.errorUnionPayload();
|
||||||
const is_pl = val.errorUnionIsPayload();
|
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)) {
|
const err_val = if (!is_pl) val else Value.initTag(.zero);
|
||||||
.externally_managed => |data| try writer.writeAll(data),
|
const start = self.code.items.len;
|
||||||
.appended => {},
|
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()) {
|
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);
|
const pl_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
|
||||||
switch (try self.genTypedValue(payload_ty, pl_val)) {
|
switch (try self.genTypedValue(payload_ty, pl_val)) {
|
||||||
.externally_managed => |data| try writer.writeAll(data),
|
.externally_managed => |data| try writer.writeAll(data),
|
||||||
.appended => {},
|
.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 = {} };
|
return Result{ .appended = {} };
|
||||||
@ -2065,15 +2083,7 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
|
|||||||
decl.markAlive();
|
decl.markAlive();
|
||||||
const target_sym_index = decl.link.wasm.sym_index;
|
const target_sym_index = decl.link.wasm.sym_index;
|
||||||
if (ty.isSlice()) {
|
if (ty.isSlice()) {
|
||||||
var slice_len: Value.Payload.U64 = .{
|
return WValue{ .memory = try self.bin_file.lowerUnnamedConst(self.decl, .{ .ty = ty, .val = val }) };
|
||||||
.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);
|
|
||||||
} else if (decl.ty.zigTypeTag() == .Fn) {
|
} else if (decl.ty.zigTypeTag() == .Fn) {
|
||||||
try self.bin_file.addTableFunction(target_sym_index);
|
try self.bin_file.addTableFunction(target_sym_index);
|
||||||
return WValue{ .function_index = 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 err_ty = self.air.typeOf(ty_op.operand);
|
||||||
const payload_ty = err_ty.errorUnionPayload();
|
const payload_ty = err_ty.errorUnionPayload();
|
||||||
if (!payload_ty.hasRuntimeBits()) return WValue{ .none = {} };
|
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)) {
|
if (isByRef(payload_ty, self.target)) {
|
||||||
return self.buildPointerOffset(operand, offset, .new);
|
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 {
|
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);
|
const op_ty = self.air.typeOf(ty_op.operand);
|
||||||
if (!op_ty.hasRuntimeBits()) return operand;
|
if (!op_ty.hasRuntimeBits()) return operand;
|
||||||
const err_ty = self.air.getRefType(ty_op.ty);
|
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 err_union = try self.allocStack(err_ty);
|
||||||
const payload_ptr = try self.buildPointerOffset(err_union, offset, .new);
|
const payload_ptr = try self.buildPointerOffset(err_union, offset, .new);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user