| ... | @@ -6547,7 +6547,7 @@ fn zirFunc( | ... | @@ -6547,7 +6547,7 @@ fn zirFunc( |
| 6547 | inst, | 6547 | inst, |
| 6548 | 0, | 6548 | 0, |
| 6549 | target_util.defaultAddressSpace(target, .function), | 6549 | target_util.defaultAddressSpace(target, .function), |
| 6550 | null, | 6550 | FuncLinkSection.default, |
| 6551 | cc, | 6551 | cc, |
| 6552 | ret_ty, | 6552 | ret_ty, |
| 6553 | false, | 6553 | false, |
| ... | @@ -6660,15 +6660,26 @@ fn handleExternLibName( | ... | @@ -6660,15 +6660,26 @@ fn handleExternLibName( |
| 6660 | return sema.gpa.dupeZ(u8, lib_name); | 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 | fn funcCommon( | 6669 | fn funcCommon( |
| 6664 | sema: *Sema, | 6670 | sema: *Sema, |
| 6665 | block: *Block, | 6671 | block: *Block, |
| 6666 | src_node_offset: i32, | 6672 | src_node_offset: i32, |
| 6667 | func_inst: Zir.Inst.Index, | 6673 | func_inst: Zir.Inst.Index, |
| 6668 | alignment: u32, | 6674 | /// null means generic poison |
| 6669 | address_space: std.builtin.AddressSpace, | 6675 | alignment: ?u32, |
| 6670 | section: ?[*:0]const u8, | 6676 | /// null means generic poison |
| 6671 | cc: std.builtin.CallingConvention, | 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 | bare_return_type: Type, | 6683 | bare_return_type: Type, |
| 6673 | var_args: bool, | 6684 | var_args: bool, |
| 6674 | inferred_error_set: bool, | 6685 | inferred_error_set: bool, |
| ... | @@ -6679,7 +6690,11 @@ fn funcCommon( | ... | @@ -6679,7 +6690,11 @@ fn funcCommon( |
| 6679 | ) CompileError!Air.Inst.Ref { | 6690 | ) CompileError!Air.Inst.Ref { |
| 6680 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; | 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 | // Check for generic params. | 6698 | // Check for generic params. |
| 6684 | for (block.params.items) |param| { | 6699 | for (block.params.items) |param| { |
| 6685 | if (param.ty.tag() == .generic_poison) is_generic = true; | 6700 | if (param.ty.tag() == .generic_poison) is_generic = true; |
| ... | @@ -6700,25 +6715,28 @@ fn funcCommon( | ... | @@ -6700,25 +6715,28 @@ fn funcCommon( |
| 6700 | errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node); | 6715 | errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node); |
| 6701 | // Note: no need to errdefer since this will still be in its default state at the end of the function. | 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 | const fn_ty: Type = fn_ty: { | 6719 | const fn_ty: Type = fn_ty: { |
| 6704 | // Hot path for some common function types. | 6720 | // Hot path for some common function types. |
| 6705 | // TODO can we eliminate some of these Type tag values? seems unnecessarily complicated. | 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 | 6722 | if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and |
| 6707 | alignment == 0 and !inferred_error_set) | 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 | break :fn_ty Type.initTag(.fn_noreturn_no_args); | 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 | break :fn_ty Type.initTag(.fn_void_no_args); | 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 | break :fn_ty Type.initTag(.fn_naked_noreturn_no_args); | 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 | break :fn_ty Type.initTag(.fn_ccc_void_no_args); | 6740 | break :fn_ty Type.initTag(.fn_ccc_void_no_args); |
| 6723 | } | 6741 | } |
| 6724 | } | 6742 | } |
| ... | @@ -6764,21 +6782,33 @@ fn funcCommon( | ... | @@ -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 | break :fn_ty try Type.Tag.function.create(sema.arena, .{ | 6789 | break :fn_ty try Type.Tag.function.create(sema.arena, .{ |
| 6768 | .param_types = param_types, | 6790 | .param_types = param_types, |
| 6769 | .comptime_params = comptime_params.ptr, | 6791 | .comptime_params = comptime_params.ptr, |
| 6770 | .return_type = return_type, | 6792 | .return_type = return_type, |
| 6771 | .cc = cc, | 6793 | .cc = cc_workaround, |
| 6772 | .alignment = alignment, | 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 | .is_var_args = var_args, | 6799 | .is_var_args = var_args, |
| 6774 | .is_generic = is_generic, | 6800 | .is_generic = is_generic, |
| 6775 | }); | 6801 | }); |
| 6776 | }; | 6802 | }; |
| 6777 | | 6803 | |
| 6778 | if (sema.owner_decl.owns_tv) { | 6804 | if (sema.owner_decl.owns_tv) { |
| 6779 | sema.owner_decl.@"linksection" = section; | 6805 | switch (section) { |
| 6780 | sema.owner_decl.@"align" = alignment; | 6806 | .generic => sema.owner_decl.@"linksection" = undefined, |
| 6781 | sema.owner_decl.@"addrspace" = address_space; | 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 | if (is_extern) { | 6814 | if (is_extern) { |
| ... | @@ -16780,13 +16810,16 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -16780,13 +16810,16 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16780 | break :blk lib_name; | 16810 | break :blk lib_name; |
| 16781 | } else null; | 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 | const body_len = sema.code.extra[extra_index]; | 16814 | const body_len = sema.code.extra[extra_index]; |
| 16785 | extra_index += 1; | 16815 | extra_index += 1; |
| 16786 | const body = sema.code.extra[extra_index..][0..body_len]; | 16816 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 16787 | extra_index += body.len; | 16817 | extra_index += body.len; |
| 16788 | | 16818 | |
| 16789 | const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u16); | 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 | const alignment = @intCast(u32, val.toUnsignedInt(target)); | 16823 | const alignment = @intCast(u32, val.toUnsignedInt(target)); |
| 16791 | if (alignment == target_util.defaultFunctionAlignment(target)) { | 16824 | if (alignment == target_util.defaultFunctionAlignment(target)) { |
| 16792 | break :blk 0; | 16825 | break :blk 0; |
| ... | @@ -16796,7 +16829,12 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -16796,7 +16829,12 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16796 | } else if (extra.data.bits.has_align_ref) blk: { | 16829 | } else if (extra.data.bits.has_align_ref) blk: { |
| 16797 | const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 16830 | const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 16798 | extra_index += 1; | 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 | const alignment = @intCast(u32, align_tv.val.toUnsignedInt(target)); | 16838 | const alignment = @intCast(u32, align_tv.val.toUnsignedInt(target)); |
| 16801 | if (alignment == target_util.defaultFunctionAlignment(target)) { | 16839 | if (alignment == target_util.defaultFunctionAlignment(target)) { |
| 16802 | break :blk 0; | 16840 | break :blk 0; |
| ... | @@ -16805,7 +16843,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -16805,7 +16843,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16805 | } | 16843 | } |
| 16806 | } else 0; | 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 | const body_len = sema.code.extra[extra_index]; | 16847 | const body_len = sema.code.extra[extra_index]; |
| 16810 | extra_index += 1; | 16848 | extra_index += 1; |
| 16811 | const body = sema.code.extra[extra_index..][0..body_len]; | 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,32 +16851,48 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16813 | | 16851 | |
| 16814 | const addrspace_ty = try sema.getBuiltinType(block, addrspace_src, "AddressSpace"); | 16852 | const addrspace_ty = try sema.getBuiltinType(block, addrspace_src, "AddressSpace"); |
| 16815 | const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty); | 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 | break :blk val.toEnum(std.builtin.AddressSpace); | 16857 | break :blk val.toEnum(std.builtin.AddressSpace); |
| 16817 | } else if (extra.data.bits.has_addrspace_ref) blk: { | 16858 | } else if (extra.data.bits.has_addrspace_ref) blk: { |
| 16818 | const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 16859 | const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 16819 | extra_index += 1; | 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 | break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace); | 16867 | break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace); |
| 16822 | } else target_util.defaultAddressSpace(target, .function); | 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 | const body_len = sema.code.extra[extra_index]; | 16871 | const body_len = sema.code.extra[extra_index]; |
| 16826 | extra_index += 1; | 16872 | extra_index += 1; |
| 16827 | const body = sema.code.extra[extra_index..][0..body_len]; | 16873 | const body = sema.code.extra[extra_index..][0..body_len]; |
| 16828 | extra_index += body.len; | 16874 | extra_index += body.len; |
| 16829 | | 16875 | |
| 16830 | const val = try sema.resolveGenericBody(block, section_src, body, inst, Type.initTag(.const_slice_u8)); | 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 | _ = val; | 16880 | _ = val; |
| 16832 | return sema.fail(block, section_src, "TODO implement linksection on functions", .{}); | 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 | const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 16883 | const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 16835 | extra_index += 1; | 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 | _ = section_tv; | 16891 | _ = section_tv; |
| 16838 | return sema.fail(block, section_src, "TODO implement linksection on functions", .{}); | 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 | const body_len = sema.code.extra[extra_index]; | 16896 | const body_len = sema.code.extra[extra_index]; |
| 16843 | extra_index += 1; | 16897 | extra_index += 1; |
| 16844 | const body = sema.code.extra[extra_index..][0..body_len]; | 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,13 +16900,21 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 16846 | | 16900 | |
| 16847 | const cc_ty = try sema.getBuiltinType(block, addrspace_src, "CallingConvention"); | 16901 | const cc_ty = try sema.getBuiltinType(block, addrspace_src, "CallingConvention"); |
| 16848 | const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty); | 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 | break :blk val.toEnum(std.builtin.CallingConvention); | 16906 | break :blk val.toEnum(std.builtin.CallingConvention); |
| 16850 | } else if (extra.data.bits.has_cc_ref) blk: { | 16907 | } else if (extra.data.bits.has_cc_ref) blk: { |
| 16851 | const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 16908 | const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 16852 | extra_index += 1; | 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 | break :blk cc_tv.val.toEnum(std.builtin.CallingConvention); | 16916 | break :blk cc_tv.val.toEnum(std.builtin.CallingConvention); |
| 16855 | } else .Unspecified; | 16917 | } else std.builtin.CallingConvention.Unspecified; |
| 16856 | | 16918 | |
| 16857 | const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: { | 16919 | const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: { |
| 16858 | const body_len = sema.code.extra[extra_index]; | 16920 | const body_len = sema.code.extra[extra_index]; |