| ... | ... | @@ -6547,7 +6547,7 @@ fn zirFunc( |
| 6547 | 6547 | inst, |
| 6548 | 6548 | 0, |
| 6549 | 6549 | target_util.defaultAddressSpace(target, .function), |
| 6550 | | null, |
| 6550 | FuncLinkSection.default, |
| 6551 | 6551 | cc, |
| 6552 | 6552 | ret_ty, |
| 6553 | 6553 | false, |
| ... | ... | @@ -6660,15 +6660,26 @@ fn handleExternLibName( |
| 6660 | 6660 | return sema.gpa.dupeZ(u8, lib_name); |
| 6661 | 6661 | } |
| 6662 | 6662 | |
| 6663 | const FuncLinkSection = union(enum) { |
| 6664 | generic, |
| 6665 | default, |
| 6666 | explicit: [*:0]const u8, |
| 6667 | }; |
| 6668 | |
| 6663 | 6669 | fn funcCommon( |
| 6664 | 6670 | sema: *Sema, |
| 6665 | 6671 | block: *Block, |
| 6666 | 6672 | src_node_offset: i32, |
| 6667 | 6673 | func_inst: Zir.Inst.Index, |
| 6668 | | alignment: u32, |
| 6669 | | address_space: std.builtin.AddressSpace, |
| 6670 | | section: ?[*:0]const u8, |
| 6671 | | cc: std.builtin.CallingConvention, |
| 6674 | /// null means generic poison |
| 6675 | alignment: ?u32, |
| 6676 | /// null means generic poison |
| 6677 | address_space: ?std.builtin.AddressSpace, |
| 6678 | /// outer null means generic poison; inner null means default link section |
| 6679 | section: FuncLinkSection, |
| 6680 | /// null means generic poison |
| 6681 | cc: ?std.builtin.CallingConvention, |
| 6682 | /// this might be Type.generic_poison |
| 6672 | 6683 | bare_return_type: Type, |
| 6673 | 6684 | var_args: bool, |
| 6674 | 6685 | inferred_error_set: bool, |
| ... | ... | @@ -6679,7 +6690,11 @@ fn funcCommon( |
| 6679 | 6690 | ) CompileError!Air.Inst.Ref { |
| 6680 | 6691 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; |
| 6681 | 6692 | |
| 6682 | | var is_generic = bare_return_type.tag() == .generic_poison; |
| 6693 | var is_generic = bare_return_type.tag() == .generic_poison or |
| 6694 | alignment == null or |
| 6695 | address_space == null or |
| 6696 | section == .generic or |
| 6697 | cc == null; |
| 6683 | 6698 | // Check for generic params. |
| 6684 | 6699 | for (block.params.items) |param| { |
| 6685 | 6700 | if (param.ty.tag() == .generic_poison) is_generic = true; |
| ... | ... | @@ -6700,25 +6715,28 @@ fn funcCommon( |
| 6700 | 6715 | errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node); |
| 6701 | 6716 | // Note: no need to errdefer since this will still be in its default state at the end of the function. |
| 6702 | 6717 | |
| 6718 | const target = sema.mod.getTarget(); |
| 6703 | 6719 | const fn_ty: Type = fn_ty: { |
| 6704 | 6720 | // Hot path for some common function types. |
| 6705 | 6721 | // TODO can we eliminate some of these Type tag values? seems unnecessarily complicated. |
| 6706 | | if (!is_generic and block.params.items.len == 0 and !var_args and |
| 6707 | | alignment == 0 and !inferred_error_set) |
| 6722 | if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and |
| 6723 | alignment.? == 0 and |
| 6724 | address_space.? == target_util.defaultAddressSpace(target, .function) and |
| 6725 | section == .default) |
| 6708 | 6726 | { |
| 6709 | | if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) { |
| 6727 | if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Unspecified) { |
| 6710 | 6728 | break :fn_ty Type.initTag(.fn_noreturn_no_args); |
| 6711 | 6729 | } |
| 6712 | 6730 | |
| 6713 | | if (bare_return_type.zigTypeTag() == .Void and cc == .Unspecified) { |
| 6731 | if (bare_return_type.zigTypeTag() == .Void and cc.? == .Unspecified) { |
| 6714 | 6732 | break :fn_ty Type.initTag(.fn_void_no_args); |
| 6715 | 6733 | } |
| 6716 | 6734 | |
| 6717 | | if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Naked) { |
| 6735 | if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Naked) { |
| 6718 | 6736 | break :fn_ty Type.initTag(.fn_naked_noreturn_no_args); |
| 6719 | 6737 | } |
| 6720 | 6738 | |
| 6721 | | if (bare_return_type.zigTypeTag() == .Void and cc == .C) { |
| 6739 | if (bare_return_type.zigTypeTag() == .Void and cc.? == .C) { |
| 6722 | 6740 | break :fn_ty Type.initTag(.fn_ccc_void_no_args); |
| 6723 | 6741 | } |
| 6724 | 6742 | } |
| ... | ... | @@ -6764,21 +6782,33 @@ fn funcCommon( |
| 6764 | 6782 | }); |
| 6765 | 6783 | }; |
| 6766 | 6784 | |
| 6785 | // stage1 bug workaround |
| 6786 | const cc_workaround = cc orelse undefined; |
| 6787 | const align_workaround = alignment orelse @as(u32, undefined); |
| 6788 | |
| 6767 | 6789 | break :fn_ty try Type.Tag.function.create(sema.arena, .{ |
| 6768 | 6790 | .param_types = param_types, |
| 6769 | 6791 | .comptime_params = comptime_params.ptr, |
| 6770 | 6792 | .return_type = return_type, |
| 6771 | | .cc = cc, |
| 6772 | | .alignment = alignment, |
| 6793 | .cc = cc_workaround, |
| 6794 | .cc_is_generic = cc == null, |
| 6795 | .alignment = align_workaround, |
| 6796 | .align_is_generic = alignment == null, |
| 6797 | .section_is_generic = section == .generic, |
| 6798 | .addrspace_is_generic = address_space == null, |
| 6773 | 6799 | .is_var_args = var_args, |
| 6774 | 6800 | .is_generic = is_generic, |
| 6775 | 6801 | }); |
| 6776 | 6802 | }; |
| 6777 | 6803 | |
| 6778 | 6804 | if (sema.owner_decl.owns_tv) { |
| 6779 | | sema.owner_decl.@"linksection" = section; |
| 6780 | | sema.owner_decl.@"align" = alignment; |
| 6781 | | sema.owner_decl.@"addrspace" = address_space; |
| 6805 | switch (section) { |
| 6806 | .generic => sema.owner_decl.@"linksection" = undefined, |
| 6807 | .default => sema.owner_decl.@"linksection" = null, |
| 6808 | .explicit => |s| sema.owner_decl.@"linksection" = s, |
| 6809 | } |
| 6810 | if (alignment) |a| sema.owner_decl.@"align" = a; |
| 6811 | if (address_space) |a| sema.owner_decl.@"addrspace" = a; |
| 6782 | 6812 | } |
| 6783 | 6813 | |
| 6784 | 6814 | if (is_extern) { |
| ... | ... | @@ -16780,13 +16810,16 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16780 | 16810 | break :blk lib_name; |
| 16781 | 16811 | } else null; |
| 16782 | 16812 | |
| 16783 | | const @"align": u32 = if (extra.data.bits.has_align_body) blk: { |
| 16813 | const @"align": ?u32 = if (extra.data.bits.has_align_body) blk: { |
| 16784 | 16814 | const body_len = sema.code.extra[extra_index]; |
| 16785 | 16815 | extra_index += 1; |
| 16786 | 16816 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 16787 | 16817 | extra_index += body.len; |
| 16788 | 16818 | |
| 16789 | 16819 | const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u16); |
| 16820 | if (val.tag() == .generic_poison) { |
| 16821 | break :blk null; |
| 16822 | } |
| 16790 | 16823 | const alignment = @intCast(u32, val.toUnsignedInt(target)); |
| 16791 | 16824 | if (alignment == target_util.defaultFunctionAlignment(target)) { |
| 16792 | 16825 | break :blk 0; |
| ... | ... | @@ -16796,7 +16829,12 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16796 | 16829 | } else if (extra.data.bits.has_align_ref) blk: { |
| 16797 | 16830 | const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 16798 | 16831 | extra_index += 1; |
| 16799 | | const align_tv = try sema.resolveInstConst(block, align_src, align_ref); |
| 16832 | const align_tv = sema.resolveInstConst(block, align_src, align_ref) catch |err| switch (err) { |
| 16833 | error.GenericPoison => { |
| 16834 | break :blk null; |
| 16835 | }, |
| 16836 | else => |e| return e, |
| 16837 | }; |
| 16800 | 16838 | const alignment = @intCast(u32, align_tv.val.toUnsignedInt(target)); |
| 16801 | 16839 | if (alignment == target_util.defaultFunctionAlignment(target)) { |
| 16802 | 16840 | break :blk 0; |
| ... | ... | @@ -16805,7 +16843,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16805 | 16843 | } |
| 16806 | 16844 | } else 0; |
| 16807 | 16845 | |
| 16808 | | const @"addrspace": std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: { |
| 16846 | const @"addrspace": ?std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: { |
| 16809 | 16847 | const body_len = sema.code.extra[extra_index]; |
| 16810 | 16848 | extra_index += 1; |
| 16811 | 16849 | const body = sema.code.extra[extra_index..][0..body_len]; |
| ... | ... | @@ -16813,32 +16851,48 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16813 | 16851 | |
| 16814 | 16852 | const addrspace_ty = try sema.getBuiltinType(block, addrspace_src, "AddressSpace"); |
| 16815 | 16853 | const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty); |
| 16854 | if (val.tag() == .generic_poison) { |
| 16855 | break :blk null; |
| 16856 | } |
| 16816 | 16857 | break :blk val.toEnum(std.builtin.AddressSpace); |
| 16817 | 16858 | } else if (extra.data.bits.has_addrspace_ref) blk: { |
| 16818 | 16859 | const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 16819 | 16860 | extra_index += 1; |
| 16820 | | const addrspace_tv = try sema.resolveInstConst(block, addrspace_src, addrspace_ref); |
| 16861 | const addrspace_tv = sema.resolveInstConst(block, addrspace_src, addrspace_ref) catch |err| switch (err) { |
| 16862 | error.GenericPoison => { |
| 16863 | break :blk null; |
| 16864 | }, |
| 16865 | else => |e| return e, |
| 16866 | }; |
| 16821 | 16867 | break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace); |
| 16822 | 16868 | } else target_util.defaultAddressSpace(target, .function); |
| 16823 | 16869 | |
| 16824 | | const @"linksection": ?[*:0]const u8 = if (extra.data.bits.has_section_body) { |
| 16870 | const @"linksection": FuncLinkSection = if (extra.data.bits.has_section_body) blk: { |
| 16825 | 16871 | const body_len = sema.code.extra[extra_index]; |
| 16826 | 16872 | extra_index += 1; |
| 16827 | 16873 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 16828 | 16874 | extra_index += body.len; |
| 16829 | 16875 | |
| 16830 | 16876 | const val = try sema.resolveGenericBody(block, section_src, body, inst, Type.initTag(.const_slice_u8)); |
| 16877 | if (val.tag() == .generic_poison) { |
| 16878 | break :blk FuncLinkSection{ .generic = {} }; |
| 16879 | } |
| 16831 | 16880 | _ = val; |
| 16832 | 16881 | return sema.fail(block, section_src, "TODO implement linksection on functions", .{}); |
| 16833 | | } else if (extra.data.bits.has_section_ref) { |
| 16882 | } else if (extra.data.bits.has_section_ref) blk: { |
| 16834 | 16883 | const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 16835 | 16884 | extra_index += 1; |
| 16836 | | const section_tv = try sema.resolveInstConst(block, section_src, section_ref); |
| 16885 | const section_tv = sema.resolveInstConst(block, section_src, section_ref) catch |err| switch (err) { |
| 16886 | error.GenericPoison => { |
| 16887 | break :blk FuncLinkSection{ .generic = {} }; |
| 16888 | }, |
| 16889 | else => |e| return e, |
| 16890 | }; |
| 16837 | 16891 | _ = section_tv; |
| 16838 | 16892 | return sema.fail(block, section_src, "TODO implement linksection on functions", .{}); |
| 16839 | | } else null; |
| 16893 | } else FuncLinkSection{ .default = {} }; |
| 16840 | 16894 | |
| 16841 | | const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: { |
| 16895 | const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: { |
| 16842 | 16896 | const body_len = sema.code.extra[extra_index]; |
| 16843 | 16897 | extra_index += 1; |
| 16844 | 16898 | const body = sema.code.extra[extra_index..][0..body_len]; |
| ... | ... | @@ -16846,13 +16900,21 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16846 | 16900 | |
| 16847 | 16901 | const cc_ty = try sema.getBuiltinType(block, addrspace_src, "CallingConvention"); |
| 16848 | 16902 | const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty); |
| 16903 | if (val.tag() == .generic_poison) { |
| 16904 | break :blk null; |
| 16905 | } |
| 16849 | 16906 | break :blk val.toEnum(std.builtin.CallingConvention); |
| 16850 | 16907 | } else if (extra.data.bits.has_cc_ref) blk: { |
| 16851 | 16908 | const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 16852 | 16909 | extra_index += 1; |
| 16853 | | const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref); |
| 16910 | const cc_tv = sema.resolveInstConst(block, cc_src, cc_ref) catch |err| switch (err) { |
| 16911 | error.GenericPoison => { |
| 16912 | break :blk null; |
| 16913 | }, |
| 16914 | else => |e| return e, |
| 16915 | }; |
| 16854 | 16916 | break :blk cc_tv.val.toEnum(std.builtin.CallingConvention); |
| 16855 | | } else .Unspecified; |
| 16917 | } else std.builtin.CallingConvention.Unspecified; |
| 16856 | 16918 | |
| 16857 | 16919 | const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: { |
| 16858 | 16920 | const body_len = sema.code.extra[extra_index]; |