mirror of
https://github.com/ziglang/zig.git
synced 2025-12-15 18:53:07 +00:00
codegen: Order error union fields per alignment
Based on the size of the payload the native backends will lower the error union with its fields (errorset & payload) in the correct order. e.g. ErrorA!u8 will first lower the error set's value and then the payload. In the event of ErrorA!u32 will lower the payload first.
This commit is contained in:
parent
3264abe3d8
commit
c90a97f9be
@ -702,16 +702,50 @@ pub fn generateSymbol(
|
||||
.ErrorUnion => {
|
||||
const error_ty = typed_value.ty.errorUnionSet();
|
||||
const payload_ty = typed_value.ty.errorUnionPayload();
|
||||
|
||||
if (error_ty.errorSetCardinality() == .zero) {
|
||||
const payload_val = typed_value.val.castTag(.eu_payload).?.data;
|
||||
return generateSymbol(bin_file, src_loc, .{
|
||||
.ty = payload_ty,
|
||||
.val = payload_val,
|
||||
}, code, debug_output, reloc_info);
|
||||
}
|
||||
|
||||
const is_payload = typed_value.val.errorUnionIsPayload();
|
||||
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
const err_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
|
||||
return generateSymbol(bin_file, src_loc, .{
|
||||
.ty = error_ty,
|
||||
.val = err_val,
|
||||
}, code, debug_output, reloc_info);
|
||||
}
|
||||
|
||||
const payload_align = payload_ty.abiAlignment(target);
|
||||
const error_align = Type.anyerror.abiAlignment(target);
|
||||
const abi_align = typed_value.ty.abiAlignment(target);
|
||||
|
||||
{
|
||||
const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
|
||||
const begin = code.items.len;
|
||||
// error value first when its type is larger than the error union's payload
|
||||
if (error_align > payload_align) {
|
||||
switch (try generateSymbol(bin_file, src_loc, .{
|
||||
.ty = error_ty,
|
||||
.val = error_val,
|
||||
.val = if (is_payload) Value.initTag(.zero) else typed_value.val,
|
||||
}, code, debug_output, reloc_info)) {
|
||||
.appended => {},
|
||||
.externally_managed => |external_slice| {
|
||||
code.appendSliceAssumeCapacity(external_slice);
|
||||
},
|
||||
.fail => |em| return Result{ .fail = em },
|
||||
}
|
||||
}
|
||||
|
||||
// emit payload part of the error union
|
||||
{
|
||||
const begin = code.items.len;
|
||||
const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);
|
||||
switch (try generateSymbol(bin_file, src_loc, .{
|
||||
.ty = payload_ty,
|
||||
.val = payload_val,
|
||||
}, code, debug_output, reloc_info)) {
|
||||
.appended => {},
|
||||
.externally_managed => |external_slice| {
|
||||
@ -728,12 +762,12 @@ pub fn generateSymbol(
|
||||
}
|
||||
}
|
||||
|
||||
if (payload_ty.hasRuntimeBits()) {
|
||||
// Payload size is larger than error set, so emit our error set last
|
||||
if (error_align < payload_align) {
|
||||
const begin = code.items.len;
|
||||
const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);
|
||||
switch (try generateSymbol(bin_file, src_loc, .{
|
||||
.ty = payload_ty,
|
||||
.val = payload_val,
|
||||
.ty = error_ty,
|
||||
.val = if (is_payload) Value.initTag(.zero) else typed_value.val,
|
||||
}, code, debug_output, reloc_info)) {
|
||||
.appended => {},
|
||||
.externally_managed => |external_slice| {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user