| ... | @@ -702,16 +702,50 @@ pub fn generateSymbol( | ... | @@ -702,16 +702,50 @@ pub fn generateSymbol( |
| 702 | .ErrorUnion => { | 702 | .ErrorUnion => { |
| 703 | const error_ty = typed_value.ty.errorUnionSet(); | 703 | const error_ty = typed_value.ty.errorUnionSet(); |
| 704 | const payload_ty = typed_value.ty.errorUnionPayload(); | 704 | const payload_ty = typed_value.ty.errorUnionPayload(); |
| | 705 | |
| | 706 | if (error_ty.errorSetCardinality() == .zero) { |
| | 707 | const payload_val = typed_value.val.castTag(.eu_payload).?.data; |
| | 708 | return generateSymbol(bin_file, src_loc, .{ |
| | 709 | .ty = payload_ty, |
| | 710 | .val = payload_val, |
| | 711 | }, code, debug_output, reloc_info); |
| | 712 | } |
| | 713 | |
| 705 | const is_payload = typed_value.val.errorUnionIsPayload(); | 714 | const is_payload = typed_value.val.errorUnionIsPayload(); |
| 706 | | 715 | |
| | 716 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| | 717 | const err_val = if (!is_payload) typed_value.val else Value.initTag(.zero); |
| | 718 | return generateSymbol(bin_file, src_loc, .{ |
| | 719 | .ty = error_ty, |
| | 720 | .val = err_val, |
| | 721 | }, code, debug_output, reloc_info); |
| | 722 | } |
| | 723 | |
| | 724 | const payload_align = payload_ty.abiAlignment(target); |
| | 725 | const error_align = Type.anyerror.abiAlignment(target); |
| 707 | const abi_align = typed_value.ty.abiAlignment(target); | 726 | const abi_align = typed_value.ty.abiAlignment(target); |
| 708 | | 727 | |
| | 728 | // error value first when its type is larger than the error union's payload |
| | 729 | if (error_align > payload_align) { |
| | 730 | switch (try generateSymbol(bin_file, src_loc, .{ |
| | 731 | .ty = error_ty, |
| | 732 | .val = if (is_payload) Value.initTag(.zero) else typed_value.val, |
| | 733 | }, code, debug_output, reloc_info)) { |
| | 734 | .appended => {}, |
| | 735 | .externally_managed => |external_slice| { |
| | 736 | code.appendSliceAssumeCapacity(external_slice); |
| | 737 | }, |
| | 738 | .fail => |em| return Result{ .fail = em }, |
| | 739 | } |
| | 740 | } |
| | 741 | |
| | 742 | // emit payload part of the error union |
| 709 | { | 743 | { |
| 710 | const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero); | | |
| 711 | const begin = code.items.len; | 744 | const begin = code.items.len; |
| | 745 | const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef); |
| 712 | switch (try generateSymbol(bin_file, src_loc, .{ | 746 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 713 | .ty = error_ty, | 747 | .ty = payload_ty, |
| 714 | .val = error_val, | 748 | .val = payload_val, |
| 715 | }, code, debug_output, reloc_info)) { | 749 | }, code, debug_output, reloc_info)) { |
| 716 | .appended => {}, | 750 | .appended => {}, |
| 717 | .externally_managed => |external_slice| { | 751 | .externally_managed => |external_slice| { |
| ... | @@ -728,12 +762,12 @@ pub fn generateSymbol( | ... | @@ -728,12 +762,12 @@ pub fn generateSymbol( |
| 728 | } | 762 | } |
| 729 | } | 763 | } |
| 730 | | 764 | |
| 731 | if (payload_ty.hasRuntimeBits()) { | 765 | // Payload size is larger than error set, so emit our error set last |
| | 766 | if (error_align < payload_align) { |
| 732 | const begin = code.items.len; | 767 | const begin = code.items.len; |
| 733 | const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef); | | |
| 734 | switch (try generateSymbol(bin_file, src_loc, .{ | 768 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 735 | .ty = payload_ty, | 769 | .ty = error_ty, |
| 736 | .val = payload_val, | 770 | .val = if (is_payload) Value.initTag(.zero) else typed_value.val, |
| 737 | }, code, debug_output, reloc_info)) { | 771 | }, code, debug_output, reloc_info)) { |
| 738 | .appended => {}, | 772 | .appended => {}, |
| 739 | .externally_managed => |external_slice| { | 773 | .externally_managed => |external_slice| { |