@@ -6556,7 +6556,7 @@ fn zirFunc(
6556
6556
inst,
6557
6557
0,
6558
6558
target_util.defaultAddressSpace(target, .function),
6559
- null ,
6559
+ FuncLinkSection.default ,
6560
6560
cc,
6561
6561
ret_ty,
6562
6562
false,
@@ -6669,15 +6669,26 @@ fn handleExternLibName(
6669
6669
return sema.gpa.dupeZ(u8, lib_name);
6670
6670
}
6671
6671
6672
+ const FuncLinkSection = union(enum) {
6673
+ generic,
6674
+ default,
6675
+ explicit: [*:0]const u8,
6676
+ };
6677
+
6672
6678
fn funcCommon(
6673
6679
sema: *Sema,
6674
6680
block: *Block,
6675
6681
src_node_offset: i32,
6676
6682
func_inst: Zir.Inst.Index,
6677
- alignment: u32,
6678
- address_space: std.builtin.AddressSpace,
6679
- section: ?[*:0]const u8,
6680
- cc: std.builtin.CallingConvention,
6683
+ /// null means generic poison
6684
+ alignment: ?u32,
6685
+ /// null means generic poison
6686
+ address_space: ?std.builtin.AddressSpace,
6687
+ /// outer null means generic poison; inner null means default link section
6688
+ section: FuncLinkSection,
6689
+ /// null means generic poison
6690
+ cc: ?std.builtin.CallingConvention,
6691
+ /// this might be Type.generic_poison
6681
6692
bare_return_type: Type,
6682
6693
var_args: bool,
6683
6694
inferred_error_set: bool,
@@ -6688,7 +6699,11 @@ fn funcCommon(
6688
6699
) CompileError!Air.Inst.Ref {
6689
6700
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
6690
6701
6691
- var is_generic = bare_return_type.tag() == .generic_poison;
6702
+ var is_generic = bare_return_type.tag() == .generic_poison or
6703
+ alignment == null or
6704
+ address_space == null or
6705
+ section == .generic or
6706
+ cc == null;
6692
6707
// Check for generic params.
6693
6708
for (block.params.items) |param| {
6694
6709
if (param.ty.tag() == .generic_poison) is_generic = true;
@@ -6709,25 +6724,28 @@ fn funcCommon(
6709
6724
errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);
6710
6725
// Note: no need to errdefer since this will still be in its default state at the end of the function.
6711
6726
6727
+ const target = sema.mod.getTarget();
6712
6728
const fn_ty: Type = fn_ty: {
6713
6729
// Hot path for some common function types.
6714
6730
// TODO can we eliminate some of these Type tag values? seems unnecessarily complicated.
6715
- if (!is_generic and block.params.items.len == 0 and !var_args and
6716
- alignment == 0 and !inferred_error_set)
6731
+ if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and
6732
+ alignment.? == 0 and
6733
+ address_space.? == target_util.defaultAddressSpace(target, .function) and
6734
+ section == .default)
6717
6735
{
6718
- if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
6736
+ if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Unspecified) {
6719
6737
break :fn_ty Type.initTag(.fn_noreturn_no_args);
6720
6738
}
6721
6739
6722
- if (bare_return_type.zigTypeTag() == .Void and cc == .Unspecified) {
6740
+ if (bare_return_type.zigTypeTag() == .Void and cc.? == .Unspecified) {
6723
6741
break :fn_ty Type.initTag(.fn_void_no_args);
6724
6742
}
6725
6743
6726
- if (bare_return_type.zigTypeTag() == .NoReturn and cc == .Naked) {
6744
+ if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Naked) {
6727
6745
break :fn_ty Type.initTag(.fn_naked_noreturn_no_args);
6728
6746
}
6729
6747
6730
- if (bare_return_type.zigTypeTag() == .Void and cc == .C) {
6748
+ if (bare_return_type.zigTypeTag() == .Void and cc.? == .C) {
6731
6749
break :fn_ty Type.initTag(.fn_ccc_void_no_args);
6732
6750
}
6733
6751
}
@@ -6773,21 +6791,33 @@ fn funcCommon(
6773
6791
});
6774
6792
};
6775
6793
6794
+ // stage1 bug workaround
6795
+ const cc_workaround = cc orelse undefined;
6796
+ const align_workaround = alignment orelse @as(u32, undefined);
6797
+
6776
6798
break :fn_ty try Type.Tag.function.create(sema.arena, .{
6777
6799
.param_types = param_types,
6778
6800
.comptime_params = comptime_params.ptr,
6779
6801
.return_type = return_type,
6780
- .cc = cc,
6781
- .alignment = alignment,
6802
+ .cc = cc_workaround,
6803
+ .cc_is_generic = cc == null,
6804
+ .alignment = align_workaround,
6805
+ .align_is_generic = alignment == null,
6806
+ .section_is_generic = section == .generic,
6807
+ .addrspace_is_generic = address_space == null,
6782
6808
.is_var_args = var_args,
6783
6809
.is_generic = is_generic,
6784
6810
});
6785
6811
};
6786
6812
6787
6813
if (sema.owner_decl.owns_tv) {
6788
- sema.owner_decl.@"linksection" = section;
6789
- sema.owner_decl.@"align" = alignment;
6790
- sema.owner_decl.@"addrspace" = address_space;
6814
+ switch (section) {
6815
+ .generic => sema.owner_decl.@"linksection" = undefined,
6816
+ .default => sema.owner_decl.@"linksection" = null,
6817
+ .explicit => |s| sema.owner_decl.@"linksection" = s,
6818
+ }
6819
+ if (alignment) |a| sema.owner_decl.@"align" = a;
6820
+ if (address_space) |a| sema.owner_decl.@"addrspace" = a;
6791
6821
}
6792
6822
6793
6823
if (is_extern) {
@@ -16807,13 +16837,16 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
16807
16837
break :blk lib_name;
16808
16838
} else null;
16809
16839
16810
- const @"align": u32 = if (extra.data.bits.has_align_body) blk: {
16840
+ const @"align": ? u32 = if (extra.data.bits.has_align_body) blk: {
16811
16841
const body_len = sema.code.extra[extra_index];
16812
16842
extra_index += 1;
16813
16843
const body = sema.code.extra[extra_index..][0..body_len];
16814
16844
extra_index += body.len;
16815
16845
16816
16846
const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u16);
16847
+ if (val.tag() == .generic_poison) {
16848
+ break :blk null;
16849
+ }
16817
16850
const alignment = @intCast(u32, val.toUnsignedInt(target));
16818
16851
if (alignment == target_util.defaultFunctionAlignment(target)) {
16819
16852
break :blk 0;
@@ -16823,7 +16856,12 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
16823
16856
} else if (extra.data.bits.has_align_ref) blk: {
16824
16857
const align_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16825
16858
extra_index += 1;
16826
- const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
16859
+ const align_tv = sema.resolveInstConst(block, align_src, align_ref) catch |err| switch (err) {
16860
+ error.GenericPoison => {
16861
+ break :blk null;
16862
+ },
16863
+ else => |e| return e,
16864
+ };
16827
16865
const alignment = @intCast(u32, align_tv.val.toUnsignedInt(target));
16828
16866
if (alignment == target_util.defaultFunctionAlignment(target)) {
16829
16867
break :blk 0;
@@ -16832,54 +16870,78 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
16832
16870
}
16833
16871
} else 0;
16834
16872
16835
- const @"addrspace": std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: {
16873
+ const @"addrspace": ? std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: {
16836
16874
const body_len = sema.code.extra[extra_index];
16837
16875
extra_index += 1;
16838
16876
const body = sema.code.extra[extra_index..][0..body_len];
16839
16877
extra_index += body.len;
16840
16878
16841
16879
const addrspace_ty = try sema.getBuiltinType(block, addrspace_src, "AddressSpace");
16842
16880
const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty);
16881
+ if (val.tag() == .generic_poison) {
16882
+ break :blk null;
16883
+ }
16843
16884
break :blk val.toEnum(std.builtin.AddressSpace);
16844
16885
} else if (extra.data.bits.has_addrspace_ref) blk: {
16845
16886
const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16846
16887
extra_index += 1;
16847
- const addrspace_tv = try sema.resolveInstConst(block, addrspace_src, addrspace_ref);
16888
+ const addrspace_tv = sema.resolveInstConst(block, addrspace_src, addrspace_ref) catch |err| switch (err) {
16889
+ error.GenericPoison => {
16890
+ break :blk null;
16891
+ },
16892
+ else => |e| return e,
16893
+ };
16848
16894
break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace);
16849
16895
} else target_util.defaultAddressSpace(target, .function);
16850
16896
16851
- const @"linksection": ?[*:0]const u8 = if (extra.data.bits.has_section_body) {
16897
+ const @"linksection": FuncLinkSection = if (extra.data.bits.has_section_body) blk: {
16852
16898
const body_len = sema.code.extra[extra_index];
16853
16899
extra_index += 1;
16854
16900
const body = sema.code.extra[extra_index..][0..body_len];
16855
16901
extra_index += body.len;
16856
16902
16857
16903
const val = try sema.resolveGenericBody(block, section_src, body, inst, Type.initTag(.const_slice_u8));
16904
+ if (val.tag() == .generic_poison) {
16905
+ break :blk FuncLinkSection{ .generic = {} };
16906
+ }
16858
16907
_ = val;
16859
16908
return sema.fail(block, section_src, "TODO implement linksection on functions", .{});
16860
- } else if (extra.data.bits.has_section_ref) {
16909
+ } else if (extra.data.bits.has_section_ref) blk: {
16861
16910
const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16862
16911
extra_index += 1;
16863
- const section_tv = try sema.resolveInstConst(block, section_src, section_ref);
16912
+ const section_tv = sema.resolveInstConst(block, section_src, section_ref) catch |err| switch (err) {
16913
+ error.GenericPoison => {
16914
+ break :blk FuncLinkSection{ .generic = {} };
16915
+ },
16916
+ else => |e| return e,
16917
+ };
16864
16918
_ = section_tv;
16865
16919
return sema.fail(block, section_src, "TODO implement linksection on functions", .{});
16866
- } else null ;
16920
+ } else FuncLinkSection{ .default = {} } ;
16867
16921
16868
- const cc: std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
16922
+ const cc: ? std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
16869
16923
const body_len = sema.code.extra[extra_index];
16870
16924
extra_index += 1;
16871
16925
const body = sema.code.extra[extra_index..][0..body_len];
16872
16926
extra_index += body.len;
16873
16927
16874
16928
const cc_ty = try sema.getBuiltinType(block, addrspace_src, "CallingConvention");
16875
16929
const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty);
16930
+ if (val.tag() == .generic_poison) {
16931
+ break :blk null;
16932
+ }
16876
16933
break :blk val.toEnum(std.builtin.CallingConvention);
16877
16934
} else if (extra.data.bits.has_cc_ref) blk: {
16878
16935
const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
16879
16936
extra_index += 1;
16880
- const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);
16937
+ const cc_tv = sema.resolveInstConst(block, cc_src, cc_ref) catch |err| switch (err) {
16938
+ error.GenericPoison => {
16939
+ break :blk null;
16940
+ },
16941
+ else => |e| return e,
16942
+ };
16881
16943
break :blk cc_tv.val.toEnum(std.builtin.CallingConvention);
16882
- } else .Unspecified;
16944
+ } else std.builtin.CallingConvention .Unspecified;
16883
16945
16884
16946
const ret_ty: Type = if (extra.data.bits.has_ret_ty_body) blk: {
16885
16947
const body_len = sema.code.extra[extra_index];
0 commit comments