@@ -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,54 +16843,78 @@ 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];
16812
16850
extra_index += body.len;
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];
16845
16899
extra_index += body.len;
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];
0 commit comments