authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-19 09:36:57-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-07-19 09:36:57-07:00
log0aacb6369fdf3762b7ab6069955684abb63f1459
tree8a84783f2dd008e3e0aef59cbe6b9ad0e36c0831
parent70c71935c7c9f20353dc2a50b497b752d70d3452
parentd5d067211b55a9afbbe3ac52daa0f09d37e5f335
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #16318 from ziglang/rework-generics

rework generic function calls

43 files changed, 3840 insertions(+), 2923 deletions(-)

lib/std/array_hash_map.zig+6-4
......@@ -1669,8 +1669,9 @@ pub fn ArrayHashMapUnmanaged(
16691669
16701670 inline fn checkedHash(ctx: anytype, key: anytype) u32 {
16711671 comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(key), K, u32, true);
1672 // If you get a compile error on the next line, it means that
1673 const hash = ctx.hash(key); // your generic hash function doesn't accept your key
1672 // If you get a compile error on the next line, it means that your
1673 // generic hash function doesn't accept your key.
1674 const hash = ctx.hash(key);
16741675 if (@TypeOf(hash) != u32) {
16751676 @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic hash function that returns the wrong type!\n" ++
16761677 @typeName(u32) ++ " was expected, but found " ++ @typeName(@TypeOf(hash)));
......@@ -1679,8 +1680,9 @@ pub fn ArrayHashMapUnmanaged(
16791680 }
16801681 inline fn checkedEql(ctx: anytype, a: anytype, b: K, b_index: usize) bool {
16811682 comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(a), K, u32, true);
1682 // If you get a compile error on the next line, it means that
1683 const eql = ctx.eql(a, b, b_index); // your generic eql function doesn't accept (self, adapt key, K, index)
1683 // If you get a compile error on the next line, it means that your
1684 // generic eql function doesn't accept (self, adapt key, K, index).
1685 const eql = ctx.eql(a, b, b_index);
16841686 if (@TypeOf(eql) != bool) {
16851687 @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic eql function that returns the wrong type!\n" ++
16861688 @typeName(bool) ++ " was expected, but found " ++ @typeName(@TypeOf(eql)));
src/Air.zig+3-2
......@@ -946,6 +946,7 @@ pub const Inst = struct {
946946 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
947947 optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),
948948 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),
949 adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type),
949950 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
950951 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),
951952 undef = @intFromEnum(InternPool.Index.undef),
......@@ -1003,7 +1004,7 @@ pub const Inst = struct {
10031004 },
10041005 ty_fn: struct {
10051006 ty: Ref,
1006 func: Module.Fn.Index,
1007 func: InternPool.Index,
10071008 },
10081009 br: struct {
10091010 block_inst: Index,
......@@ -1436,7 +1437,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
14361437
14371438 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
14381439 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1439 return ip.funcReturnType(callee_ty.toIntern()).toType();
1440 return ip.funcTypeReturnType(callee_ty.toIntern()).toType();
14401441 },
14411442
14421443 .slice_elem_val, .ptr_elem_val, .array_elem_val => {
src/AstGen.zig+4-1
......@@ -12095,7 +12095,10 @@ const GenZir = struct {
1209512095 return gz.addAsIndex(.{
1209612096 .tag = .save_err_ret_index,
1209712097 .data = .{ .save_err_ret_index = .{
12098 .operand = if (cond == .if_of_error_type) cond.if_of_error_type else .none,
12098 .operand = switch (cond) {
12099 .if_of_error_type => |x| x,
12100 else => .none,
12101 },
1209912102 } },
1210012103 });
1210112104 }
src/Autodoc.zig+1
......@@ -281,6 +281,7 @@ pub fn generateZirData(self: *Autodoc) !void {
281281 // Poison and special tag
282282 .generic_poison_type,
283283 .var_args_param_type,
284 .adhoc_inferred_error_set_type,
284285 => .{
285286 .Type = .{ .name = try tmpbuf.toOwnedSlice() },
286287 },
src/Compilation.zig+5-10
......@@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig");
2929const fatal = @import("main.zig").fatal;
3030const clangMain = @import("main.zig").clangMain;
3131const Module = @import("Module.zig");
32const InternPool = @import("InternPool.zig");
3233const BuildId = std.Build.CompileStep.BuildId;
3334const Cache = std.Build.Cache;
3435const translate_c = @import("translate_c.zig");
......@@ -227,7 +228,8 @@ const Job = union(enum) {
227228 /// Write the constant value for a Decl to the output file.
228229 codegen_decl: Module.Decl.Index,
229230 /// Write the machine code for a function to the output file.
230 codegen_func: Module.Fn.Index,
231 /// This will either be a non-generic `func_decl` or a `func_instance`.
232 codegen_func: InternPool.Index,
231233 /// Render the .h file snippet for the Decl.
232234 emit_h_decl: Module.Decl.Index,
233235 /// The Decl needs to be analyzed and possibly export itself.
......@@ -2053,15 +2055,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
20532055 const decl = module.declPtr(decl_index);
20542056 assert(decl.deletion_flag);
20552057 assert(decl.dependants.count() == 0);
2056 const is_anon = if (decl.zir_decl_index == 0) blk: {
2057 break :blk module.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index);
2058 } else false;
2058 assert(decl.zir_decl_index != 0);
20592059
20602060 try module.clearDecl(decl_index, null);
2061
2062 if (is_anon) {
2063 module.destroyDecl(decl_index);
2064 }
20652061 }
20662062
20672063 try module.processExports();
......@@ -3216,8 +3212,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
32163212 // Tests are always emitted in test binaries. The decl_refs are created by
32173213 // Module.populateTestFunctions, but this will not queue body analysis, so do
32183214 // that now.
3219 const func_index = module.intern_pool.indexToFunc(decl.val.ip_index).unwrap().?;
3220 try module.ensureFuncBodyAnalysisQueued(func_index);
3215 try module.ensureFuncBodyAnalysisQueued(decl.val.toIntern());
32213216 }
32223217 },
32233218 .update_embed_file => |embed_file| {
src/InternPool.zig+1679-574
......@@ -20,6 +20,25 @@ limbs: std.ArrayListUnmanaged(u64) = .{},
2020/// `string_bytes` array is agnostic to either usage.
2121string_bytes: std.ArrayListUnmanaged(u8) = .{},
2222
23/// Rather than allocating Decl objects with an Allocator, we instead allocate
24/// them with this SegmentedList. This provides four advantages:
25/// * Stable memory so that one thread can access a Decl object while another
26/// thread allocates additional Decl objects from this list.
27/// * It allows us to use u32 indexes to reference Decl objects rather than
28/// pointers, saving memory in Type, Value, and dependency sets.
29/// * Using integers to reference Decl objects rather than pointers makes
30/// serialization trivial.
31/// * It provides a unique integer to be used for anonymous symbol names, avoiding
32/// multi-threaded contention on an atomic counter.
33allocated_decls: std.SegmentedList(Module.Decl, 0) = .{},
34/// When a Decl object is freed from `allocated_decls`, it is pushed into this stack.
35decls_free_list: std.ArrayListUnmanaged(Module.Decl.Index) = .{},
36
37/// Same pattern as with `allocated_decls`.
38allocated_namespaces: std.SegmentedList(Module.Namespace, 0) = .{},
39/// Same pattern as with `decls_free_list`.
40namespaces_free_list: std.ArrayListUnmanaged(Module.Namespace.Index) = .{},
41
2342/// Struct objects are stored in this data structure because:
2443/// * They contain pointers such as the field maps.
2544/// * They need to be mutated after creation.
......@@ -34,25 +53,11 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},
3453/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.
3554unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},
3655
37/// Fn objects are stored in this data structure because:
38/// * They need to be mutated after creation.
39allocated_funcs: std.SegmentedList(Module.Fn, 0) = .{},
40/// When a Fn object is freed from `allocated_funcs`, it is pushed into this stack.
41funcs_free_list: std.ArrayListUnmanaged(Module.Fn.Index) = .{},
42
43/// InferredErrorSet objects are stored in this data structure because:
44/// * They contain pointers such as the errors map and the set of other inferred error sets.
45/// * They need to be mutated after creation.
46allocated_inferred_error_sets: std.SegmentedList(Module.Fn.InferredErrorSet, 0) = .{},
47/// When a Struct object is freed from `allocated_inferred_error_sets`, it is
48/// pushed into this stack.
49inferred_error_sets_free_list: std.ArrayListUnmanaged(Module.Fn.InferredErrorSet.Index) = .{},
50
5156/// Some types such as enums, structs, and unions need to store mappings from field names
5257/// to field index, or value to field index. In such cases, they will store the underlying
5358/// field names and values directly, relying on one of these maps, stored separately,
5459/// to provide lookup.
55maps: std.ArrayListUnmanaged(std.AutoArrayHashMapUnmanaged(void, void)) = .{},
60maps: std.ArrayListUnmanaged(FieldMap) = .{},
5661
5762/// Used for finding the index inside `string_bytes`.
5863string_table: std.HashMapUnmanaged(
......@@ -62,6 +67,10 @@ string_table: std.HashMapUnmanaged(
6267 std.hash_map.default_max_load_percentage,
6368) = .{},
6469
70/// TODO: after https://github.com/ziglang/zig/issues/10618 is solved,
71/// change store_hash to false.
72const FieldMap = std.ArrayHashMapUnmanaged(void, void, std.array_hash_map.AutoContext(void), true);
73
6574const builtin = @import("builtin");
6675const std = @import("std");
6776const Allocator = std.mem.Allocator;
......@@ -73,6 +82,7 @@ const Hash = std.hash.Wyhash;
7382
7483const InternPool = @This();
7584const Module = @import("Module.zig");
85const Zir = @import("Zir.zig");
7686const Sema = @import("Sema.zig");
7787
7888const KeyAdapter = struct {
......@@ -129,12 +139,24 @@ pub const NullTerminatedString = enum(u32) {
129139 empty = 0,
130140 _,
131141
142 /// An array of `NullTerminatedString` existing within the `extra` array.
143 /// This type exists to provide a struct with lifetime that is
144 /// not invalidated when items are added to the `InternPool`.
145 pub const Slice = struct {
146 start: u32,
147 len: u32,
148
149 pub fn get(slice: Slice, ip: *const InternPool) []NullTerminatedString {
150 return @ptrCast(ip.extra.items[slice.start..][0..slice.len]);
151 }
152 };
153
132154 pub fn toString(self: NullTerminatedString) String {
133 return @as(String, @enumFromInt(@intFromEnum(self)));
155 return @enumFromInt(@intFromEnum(self));
134156 }
135157
136158 pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString {
137 return @as(OptionalNullTerminatedString, @enumFromInt(@intFromEnum(self)));
159 return @enumFromInt(@intFromEnum(self));
138160 }
139161
140162 const Adapter = struct {
......@@ -224,7 +246,8 @@ pub const Key = union(enum) {
224246 enum_type: EnumType,
225247 func_type: FuncType,
226248 error_set_type: ErrorSetType,
227 inferred_error_set_type: Module.Fn.InferredErrorSet.Index,
249 /// The payload is the function body, either a `func_decl` or `func_instance`.
250 inferred_error_set_type: Index,
228251
229252 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
230253 /// via `simple_value` and has a named `Index` tag for it.
......@@ -273,16 +296,16 @@ pub const Key = union(enum) {
273296
274297 pub const ErrorSetType = struct {
275298 /// Set of error names, sorted by null terminated string index.
276 names: []const NullTerminatedString,
299 names: NullTerminatedString.Slice,
277300 /// This is ignored by `get` but will always be provided by `indexToKey`.
278301 names_map: OptionalMapIndex = .none,
279302
280303 /// Look up field index based on field name.
281304 pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
282305 const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)];
283 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names };
306 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };
284307 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
285 return @as(u32, @intCast(field_index));
308 return @intCast(field_index);
286309 }
287310 };
288311
......@@ -487,7 +510,7 @@ pub const Key = union(enum) {
487510 };
488511
489512 pub const FuncType = struct {
490 param_types: []Index,
513 param_types: Index.Slice,
491514 return_type: Index,
492515 /// Tells whether a parameter is comptime. See `paramIsComptime` helper
493516 /// method for accessing this.
......@@ -518,6 +541,32 @@ pub const Key = union(enum) {
518541 assert(i < self.param_types.len);
519542 return @as(u1, @truncate(self.noalias_bits >> i)) != 0;
520543 }
544
545 pub fn eql(a: FuncType, b: FuncType, ip: *const InternPool) bool {
546 return std.mem.eql(Index, a.param_types.get(ip), b.param_types.get(ip)) and
547 a.return_type == b.return_type and
548 a.comptime_bits == b.comptime_bits and
549 a.noalias_bits == b.noalias_bits and
550 a.alignment == b.alignment and
551 a.cc == b.cc and
552 a.is_var_args == b.is_var_args and
553 a.is_generic == b.is_generic and
554 a.is_noinline == b.is_noinline;
555 }
556
557 pub fn hash(self: FuncType, hasher: *Hash, ip: *const InternPool) void {
558 for (self.param_types.get(ip)) |param_type| {
559 std.hash.autoHash(hasher, param_type);
560 }
561 std.hash.autoHash(hasher, self.return_type);
562 std.hash.autoHash(hasher, self.comptime_bits);
563 std.hash.autoHash(hasher, self.noalias_bits);
564 std.hash.autoHash(hasher, self.alignment);
565 std.hash.autoHash(hasher, self.cc);
566 std.hash.autoHash(hasher, self.is_var_args);
567 std.hash.autoHash(hasher, self.is_generic);
568 std.hash.autoHash(hasher, self.is_noinline);
569 }
521570 };
522571
523572 pub const Variable = struct {
......@@ -541,10 +590,73 @@ pub const Key = union(enum) {
541590 lib_name: OptionalNullTerminatedString,
542591 };
543592
544 /// Extern so it can be hashed by reinterpreting memory.
545 pub const Func = extern struct {
593 pub const Func = struct {
594 /// In the case of a generic function, this type will potentially have fewer parameters
595 /// than the generic owner's type, because the comptime parameters will be deleted.
546596 ty: Index,
547 index: Module.Fn.Index,
597 /// Index into extra array of the `FuncAnalysis` corresponding to this function.
598 /// Used for mutating that data.
599 analysis_extra_index: u32,
600 /// Index into extra array of the `zir_body_inst` corresponding to this function.
601 /// Used for mutating that data.
602 zir_body_inst_extra_index: u32,
603 /// Index into extra array of the resolved inferred error set for this function.
604 /// Used for mutating that data.
605 /// 0 when the function does not have an inferred error set.
606 resolved_error_set_extra_index: u32,
607 /// When a generic function is instantiated, branch_quota is inherited from the
608 /// active Sema context. Importantly, this value is also updated when an existing
609 /// generic function instantiation is found and called.
610 /// This field contains the index into the extra array of this value,
611 /// so that it can be mutated.
612 /// This will be 0 when the function is not a generic function instantiation.
613 branch_quota_extra_index: u32,
614 /// The Decl that corresponds to the function itself.
615 owner_decl: Module.Decl.Index,
616 /// The ZIR instruction that is a function instruction. Use this to find
617 /// the body. We store this rather than the body directly so that when ZIR
618 /// is regenerated on update(), we can map this to the new corresponding
619 /// ZIR instruction.
620 zir_body_inst: Zir.Inst.Index,
621 /// Relative to owner Decl.
622 lbrace_line: u32,
623 /// Relative to owner Decl.
624 rbrace_line: u32,
625 lbrace_column: u32,
626 rbrace_column: u32,
627
628 /// The `func_decl` which is the generic function from whence this instance was spawned.
629 /// If this is `none` it means the function is not a generic instantiation.
630 generic_owner: Index,
631 /// If this is a generic function instantiation, this will be non-empty.
632 /// Corresponds to the parameters of the `generic_owner` type, which
633 /// may have more parameters than `ty`.
634 /// Each element is the comptime-known value the generic function was instantiated with,
635 /// or `none` if the element is runtime-known.
636 /// TODO: as a follow-up optimization, don't store `none` values here since that data
637 /// is redundant with `comptime_bits` stored elsewhere.
638 comptime_args: Index.Slice,
639
640 /// Returns a pointer that becomes invalid after any additions to the `InternPool`.
641 pub fn analysis(func: *const Func, ip: *const InternPool) *FuncAnalysis {
642 return @ptrCast(&ip.extra.items[func.analysis_extra_index]);
643 }
644
645 /// Returns a pointer that becomes invalid after any additions to the `InternPool`.
646 pub fn zirBodyInst(func: *const Func, ip: *const InternPool) *Zir.Inst.Index {
647 return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]);
648 }
649
650 /// Returns a pointer that becomes invalid after any additions to the `InternPool`.
651 pub fn branchQuota(func: *const Func, ip: *const InternPool) *u32 {
652 return &ip.extra.items[func.branch_quota_extra_index];
653 }
654
655 /// Returns a pointer that becomes invalid after any additions to the `InternPool`.
656 pub fn resolvedErrorSet(func: *const Func, ip: *const InternPool) *Index {
657 assert(func.analysis(ip).inferred_error_set);
658 return @ptrCast(&ip.extra.items[func.resolved_error_set_extra_index]);
659 }
548660 };
549661
550662 pub const Int = struct {
......@@ -679,13 +791,13 @@ pub const Key = union(enum) {
679791 };
680792
681793 pub const MemoizedCall = struct {
682 func: Module.Fn.Index,
794 func: Index,
683795 arg_values: []const Index,
684796 result: Index,
685797 };
686798
687799 pub fn hash32(key: Key, ip: *const InternPool) u32 {
688 return @as(u32, @truncate(key.hash64(ip)));
800 return @truncate(key.hash64(ip));
689801 }
690802
691803 pub fn hash64(key: Key, ip: *const InternPool) u64 {
......@@ -695,7 +807,6 @@ pub const Key = union(enum) {
695807 return switch (key) {
696808 // TODO: assert no padding in these types
697809 inline .ptr_type,
698 .func,
699810 .array_type,
700811 .vector_type,
701812 .opt_type,
......@@ -723,20 +834,11 @@ pub const Key = union(enum) {
723834 },
724835
725836 .runtime_value => |x| Hash.hash(seed, asBytes(&x.val)),
726 .opaque_type => |x| Hash.hash(seed, asBytes(&x.decl)),
727
728 .enum_type => |enum_type| {
729 var hasher = Hash.init(seed);
730 std.hash.autoHash(&hasher, enum_type.decl);
731 return hasher.final();
732 },
733837
734 .variable => |variable| {
735 var hasher = Hash.init(seed);
736 std.hash.autoHash(&hasher, variable.decl);
737 return hasher.final();
738 },
739 .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)),
838 inline .opaque_type,
839 .enum_type,
840 .variable,
841 => |x| Hash.hash(seed, asBytes(&x.decl)),
740842
741843 .int => |int| {
742844 var hasher = Hash.init(seed);
......@@ -859,11 +961,7 @@ pub const Key = union(enum) {
859961 return hasher.final();
860962 },
861963
862 .error_set_type => |error_set_type| {
863 var hasher = Hash.init(seed);
864 for (error_set_type.names) |elem| std.hash.autoHash(&hasher, elem);
865 return hasher.final();
866 },
964 .error_set_type => |x| Hash.hash(seed, std.mem.sliceAsBytes(x.names.get(ip))),
867965
868966 .anon_struct_type => |anon_struct_type| {
869967 var hasher = Hash.init(seed);
......@@ -875,15 +973,7 @@ pub const Key = union(enum) {
875973
876974 .func_type => |func_type| {
877975 var hasher = Hash.init(seed);
878 for (func_type.param_types) |param_type| std.hash.autoHash(&hasher, param_type);
879 std.hash.autoHash(&hasher, func_type.return_type);
880 std.hash.autoHash(&hasher, func_type.comptime_bits);
881 std.hash.autoHash(&hasher, func_type.noalias_bits);
882 std.hash.autoHash(&hasher, func_type.alignment);
883 std.hash.autoHash(&hasher, func_type.cc);
884 std.hash.autoHash(&hasher, func_type.is_var_args);
885 std.hash.autoHash(&hasher, func_type.is_generic);
886 std.hash.autoHash(&hasher, func_type.is_noinline);
976 func_type.hash(&hasher, ip);
887977 return hasher.final();
888978 },
889979
......@@ -893,6 +983,30 @@ pub const Key = union(enum) {
893983 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg);
894984 return hasher.final();
895985 },
986
987 .func => |func| {
988 // In the case of a function with an inferred error set, we
989 // must not include the inferred error set type in the hash,
990 // otherwise we would get false negatives for interning generic
991 // function instances which have inferred error sets.
992
993 if (func.generic_owner == .none and func.resolved_error_set_extra_index == 0)
994 return Hash.hash(seed, asBytes(&func.owner_decl) ++ asBytes(&func.ty));
995
996 var hasher = Hash.init(seed);
997 std.hash.autoHash(&hasher, func.generic_owner);
998 for (func.comptime_args.get(ip)) |arg| std.hash.autoHash(&hasher, arg);
999 if (func.resolved_error_set_extra_index == 0) {
1000 std.hash.autoHash(&hasher, func.ty);
1001 } else {
1002 var ty_info = ip.indexToFuncType(func.ty).?;
1003 ty_info.return_type = ip.errorUnionPayload(ty_info.return_type);
1004 ty_info.hash(&hasher, ip);
1005 }
1006 return hasher.final();
1007 },
1008
1009 .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)),
8961010 };
8971011 }
8981012
......@@ -993,7 +1107,41 @@ pub const Key = union(enum) {
9931107 },
9941108 .func => |a_info| {
9951109 const b_info = b.func;
996 return a_info.ty == b_info.ty and a_info.index == b_info.index;
1110
1111 if (a_info.generic_owner != b_info.generic_owner)
1112 return false;
1113
1114 if (a_info.generic_owner == .none) {
1115 if (a_info.owner_decl != b_info.owner_decl)
1116 return false;
1117 } else {
1118 if (!std.mem.eql(
1119 Index,
1120 a_info.comptime_args.get(ip),
1121 b_info.comptime_args.get(ip),
1122 )) return false;
1123 }
1124
1125 if (a_info.ty == b_info.ty)
1126 return true;
1127
1128 // There is one case where the types may be inequal but we
1129 // still want to find the same function body instance. In the
1130 // case of the functions having an inferred error set, the key
1131 // used to find an existing function body will necessarily have
1132 // a unique inferred error set type, because it refers to the
1133 // function body InternPool Index. To make this case work we
1134 // omit the inferred error set from the equality check.
1135 if (a_info.resolved_error_set_extra_index == 0 or
1136 b_info.resolved_error_set_extra_index == 0)
1137 {
1138 return false;
1139 }
1140 var a_ty_info = ip.indexToFuncType(a_info.ty).?;
1141 a_ty_info.return_type = ip.errorUnionPayload(a_ty_info.return_type);
1142 var b_ty_info = ip.indexToFuncType(b_info.ty).?;
1143 b_ty_info.return_type = ip.errorUnionPayload(b_ty_info.return_type);
1144 return a_ty_info.eql(b_ty_info, ip);
9971145 },
9981146
9991147 .ptr => |a_info| {
......@@ -1145,7 +1293,7 @@ pub const Key = union(enum) {
11451293 },
11461294 .error_set_type => |a_info| {
11471295 const b_info = b.error_set_type;
1148 return std.mem.eql(NullTerminatedString, a_info.names, b_info.names);
1296 return std.mem.eql(NullTerminatedString, a_info.names.get(ip), b_info.names.get(ip));
11491297 },
11501298 .inferred_error_set_type => |a_info| {
11511299 const b_info = b.inferred_error_set_type;
......@@ -1154,16 +1302,7 @@ pub const Key = union(enum) {
11541302
11551303 .func_type => |a_info| {
11561304 const b_info = b.func_type;
1157
1158 return std.mem.eql(Index, a_info.param_types, b_info.param_types) and
1159 a_info.return_type == b_info.return_type and
1160 a_info.comptime_bits == b_info.comptime_bits and
1161 a_info.noalias_bits == b_info.noalias_bits and
1162 a_info.alignment == b_info.alignment and
1163 a_info.cc == b_info.cc and
1164 a_info.is_var_args == b_info.is_var_args and
1165 a_info.is_generic == b_info.is_generic and
1166 a_info.is_noinline == b_info.is_noinline;
1305 return Key.FuncType.eql(a_info, b_info, ip);
11671306 },
11681307
11691308 .memoized_call => |a_info| {
......@@ -1311,6 +1450,8 @@ pub const Index = enum(u32) {
13111450 slice_const_u8_sentinel_0_type,
13121451 optional_noreturn_type,
13131452 anyerror_void_error_union_type,
1453 /// Used for the inferred error set of inline/comptime function calls.
1454 adhoc_inferred_error_set_type,
13141455 generic_poison_type,
13151456 /// `@TypeOf(.{})`
13161457 empty_struct_type,
......@@ -1360,6 +1501,18 @@ pub const Index = enum(u32) {
13601501
13611502 _,
13621503
1504 /// An array of `Index` existing within the `extra` array.
1505 /// This type exists to provide a struct with lifetime that is
1506 /// not invalidated when items are added to the `InternPool`.
1507 pub const Slice = struct {
1508 start: u32,
1509 len: u32,
1510
1511 pub fn get(slice: Slice, ip: *const InternPool) []Index {
1512 return @ptrCast(ip.extra.items[slice.start..][0..slice.len]);
1513 }
1514 };
1515
13631516 pub fn toType(i: Index) @import("type.zig").Type {
13641517 assert(i != .none);
13651518 return .{ .ip_index = i };
......@@ -1390,6 +1543,7 @@ pub const Index = enum(u32) {
13901543
13911544 /// This function is used in the debugger pretty formatters in tools/ to fetch the
13921545 /// Tag to encoding mapping to facilitate fancy debug printing for this type.
1546 /// TODO merge this with `Tag.Payload`.
13931547 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {
13941548 const DataIsIndex = struct { data: Index };
13951549 const DataIsExtraIndexOfEnumExplicit = struct {
......@@ -1425,13 +1579,14 @@ pub const Index = enum(u32) {
14251579 type_optional: DataIsIndex,
14261580 type_anyframe: DataIsIndex,
14271581 type_error_union: struct { data: *Key.ErrorUnionType },
1582 type_anyerror_union: DataIsIndex,
14281583 type_error_set: struct {
14291584 const @"data.names_len" = opaque {};
1430 data: *ErrorSet,
1585 data: *Tag.ErrorSet,
14311586 @"trailing.names.len": *@"data.names_len",
14321587 trailing: struct { names: []NullTerminatedString },
14331588 },
1434 type_inferred_error_set: struct { data: Module.Fn.InferredErrorSet.Index },
1589 type_inferred_error_set: DataIsIndex,
14351590 type_enum_auto: struct {
14361591 const @"data.fields_len" = opaque {};
14371592 data: *EnumAuto,
......@@ -1450,10 +1605,14 @@ pub const Index = enum(u32) {
14501605 type_union_untagged: struct { data: Module.Union.Index },
14511606 type_union_safety: struct { data: Module.Union.Index },
14521607 type_function: struct {
1608 const @"data.flags.has_comptime_bits" = opaque {};
1609 const @"data.flags.has_noalias_bits" = opaque {};
14531610 const @"data.params_len" = opaque {};
1454 data: *TypeFunction,
1611 data: *Tag.TypeFunction,
1612 @"trailing.comptime_bits.len": *@"data.flags.has_comptime_bits",
1613 @"trailing.noalias_bits.len": *@"data.flags.has_noalias_bits",
14551614 @"trailing.param_types.len": *@"data.params_len",
1456 trailing: struct { param_types: []Index },
1615 trailing: struct { comptime_bits: []u32, noalias_bits: []u32, param_types: []Index },
14571616 },
14581617
14591618 undef: DataIsIndex,
......@@ -1497,7 +1656,23 @@ pub const Index = enum(u32) {
14971656 float_comptime_float: struct { data: *Float128 },
14981657 variable: struct { data: *Tag.Variable },
14991658 extern_func: struct { data: *Key.ExternFunc },
1500 func: struct { data: *Tag.Func },
1659 func_decl: struct {
1660 const @"data.analysis.inferred_error_set" = opaque {};
1661 data: *Tag.FuncDecl,
1662 @"trailing.resolved_error_set.len": *@"data.analysis.inferred_error_set",
1663 trailing: struct { resolved_error_set: []Index },
1664 },
1665 func_instance: struct {
1666 const @"data.analysis.inferred_error_set" = opaque {};
1667 const @"data.generic_owner.data.ty.data.params_len" = opaque {};
1668 data: *Tag.FuncInstance,
1669 @"trailing.resolved_error_set.len": *@"data.analysis.inferred_error_set",
1670 @"trailing.comptime_args.len": *@"data.generic_owner.data.ty.data.params_len",
1671 trailing: struct { resolved_error_set: []Index, comptime_args: []Index },
1672 },
1673 func_coerced: struct {
1674 data: *Tag.FuncCoerced,
1675 },
15011676 only_possible_value: DataIsIndex,
15021677 union_value: struct { data: *Key.Union },
15031678 bytes: struct { data: *Bytes },
......@@ -1716,6 +1891,8 @@ pub const static_keys = [_]Key{
17161891 .payload_type = .void_type,
17171892 } },
17181893
1894 // adhoc_inferred_error_set_type
1895 .{ .simple_type = .adhoc_inferred_error_set },
17191896 // generic_poison_type
17201897 .{ .simple_type = .generic_poison },
17211898
......@@ -1822,11 +1999,14 @@ pub const Tag = enum(u8) {
18221999 /// An error union type.
18232000 /// data is payload to `Key.ErrorUnionType`.
18242001 type_error_union,
2002 /// An error union type of the form `anyerror!T`.
2003 /// data is `Index` of payload type.
2004 type_anyerror_union,
18252005 /// An error set type.
18262006 /// data is payload to `ErrorSet`.
18272007 type_error_set,
18282008 /// The inferred error set type of a function.
1829 /// data is `Module.Fn.InferredErrorSet.Index`.
2009 /// data is `Index` of a `func_decl` or `func_instance`.
18302010 type_inferred_error_set,
18312011 /// An enum type with auto-numbered tag values.
18322012 /// The enum is exhaustive.
......@@ -2005,11 +2185,19 @@ pub const Tag = enum(u8) {
20052185 /// data is extra index to Variable.
20062186 variable,
20072187 /// An extern function.
2008 /// data is extra index to Key.ExternFunc.
2188 /// data is extra index to ExternFunc.
20092189 extern_func,
2010 /// A regular function.
2011 /// data is extra index to Func.
2012 func,
2190 /// A non-extern function corresponding directly to the AST node from whence it originated.
2191 /// data is extra index to `FuncDecl`.
2192 /// Only the owner Decl is used for hashing and equality because the other
2193 /// fields can get patched up during incremental compilation.
2194 func_decl,
2195 /// A generic function instantiation.
2196 /// data is extra index to `FuncInstance`.
2197 func_instance,
2198 /// A `func_decl` or a `func_instance` that has been coerced to a different type.
2199 /// data is extra index to `FuncCoerced`.
2200 func_coerced,
20132201 /// This represents the only possible value for *some* types which have
20142202 /// only one possible value. Not all only-possible-values are encoded this way;
20152203 /// for example structs which have all comptime fields are not encoded this way.
......@@ -2041,7 +2229,6 @@ pub const Tag = enum(u8) {
20412229 const Error = Key.Error;
20422230 const EnumTag = Key.EnumTag;
20432231 const ExternFunc = Key.ExternFunc;
2044 const Func = Key.Func;
20452232 const Union = Key.Union;
20462233 const TypePointer = Key.PtrType;
20472234
......@@ -2057,6 +2244,7 @@ pub const Tag = enum(u8) {
20572244 .type_optional => unreachable,
20582245 .type_anyframe => unreachable,
20592246 .type_error_union => ErrorUnionType,
2247 .type_anyerror_union => unreachable,
20602248 .type_error_set => ErrorSet,
20612249 .type_inferred_error_set => unreachable,
20622250 .type_enum_auto => EnumAuto,
......@@ -2114,7 +2302,9 @@ pub const Tag = enum(u8) {
21142302 .float_comptime_float => unreachable,
21152303 .variable => Variable,
21162304 .extern_func => ExternFunc,
2117 .func => Func,
2305 .func_decl => FuncDecl,
2306 .func_instance => FuncInstance,
2307 .func_coerced => FuncCoerced,
21182308 .only_possible_value => unreachable,
21192309 .union_value => Union,
21202310 .bytes => Bytes,
......@@ -2150,36 +2340,107 @@ pub const Tag = enum(u8) {
21502340 /// The type of the aggregate.
21512341 ty: Index,
21522342 };
2153};
21542343
2155/// Trailing:
2156/// 0. name: NullTerminatedString for each names_len
2157pub const ErrorSet = struct {
2158 names_len: u32,
2159 /// Maps error names to declaration index.
2160 names_map: MapIndex,
2161};
2344 /// Trailing:
2345 /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which
2346 /// is a regular error set corresponding to the finished inferred error set.
2347 /// A `none` value marks that the inferred error set is not resolved yet.
2348 pub const FuncDecl = struct {
2349 analysis: FuncAnalysis,
2350 owner_decl: Module.Decl.Index,
2351 ty: Index,
2352 zir_body_inst: Zir.Inst.Index,
2353 lbrace_line: u32,
2354 rbrace_line: u32,
2355 lbrace_column: u32,
2356 rbrace_column: u32,
2357 };
21622358
2163/// Trailing:
2164/// 0. param_type: Index for each params_len
2165pub const TypeFunction = struct {
2166 params_len: u32,
2167 return_type: Index,
2168 comptime_bits: u32,
2169 noalias_bits: u32,
2170 flags: Flags,
2359 /// Trailing:
2360 /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which
2361 /// is a regular error set corresponding to the finished inferred error set.
2362 /// A `none` value marks that the inferred error set is not resolved yet.
2363 /// 1. For each parameter of generic_owner: `Index` if comptime, otherwise `none`
2364 pub const FuncInstance = struct {
2365 analysis: FuncAnalysis,
2366 // Needed by the linker for codegen. Not part of hashing or equality.
2367 owner_decl: Module.Decl.Index,
2368 ty: Index,
2369 branch_quota: u32,
2370 /// Points to a `FuncDecl`.
2371 generic_owner: Index,
2372 };
21712373
2172 pub const Flags = packed struct(u32) {
2173 alignment: Alignment,
2174 cc: std.builtin.CallingConvention,
2175 is_var_args: bool,
2176 is_generic: bool,
2177 is_noinline: bool,
2178 align_is_generic: bool,
2179 cc_is_generic: bool,
2180 section_is_generic: bool,
2181 addrspace_is_generic: bool,
2182 _: u11 = 0,
2374 pub const FuncCoerced = struct {
2375 ty: Index,
2376 func: Index,
2377 };
2378
2379 /// Trailing:
2380 /// 0. name: NullTerminatedString for each names_len
2381 pub const ErrorSet = struct {
2382 names_len: u32,
2383 /// Maps error names to declaration index.
2384 names_map: MapIndex,
2385 };
2386
2387 /// Trailing:
2388 /// 0. comptime_bits: u32, // if has_comptime_bits
2389 /// 1. noalias_bits: u32, // if has_noalias_bits
2390 /// 2. param_type: Index for each params_len
2391 pub const TypeFunction = struct {
2392 params_len: u32,
2393 return_type: Index,
2394 flags: Flags,
2395
2396 pub const Flags = packed struct(u32) {
2397 alignment: Alignment,
2398 cc: std.builtin.CallingConvention,
2399 is_var_args: bool,
2400 is_generic: bool,
2401 has_comptime_bits: bool,
2402 has_noalias_bits: bool,
2403 is_noinline: bool,
2404 align_is_generic: bool,
2405 cc_is_generic: bool,
2406 section_is_generic: bool,
2407 addrspace_is_generic: bool,
2408 _: u9 = 0,
2409 };
2410 };
2411};
2412
2413/// State that is mutable during semantic analysis. This data is not used for
2414/// equality or hashing, except for `inferred_error_set` which is considered
2415/// to be part of the type of the function.
2416pub const FuncAnalysis = packed struct(u32) {
2417 state: State,
2418 is_cold: bool,
2419 is_noinline: bool,
2420 calls_or_awaits_errorable_fn: bool,
2421 stack_alignment: Alignment,
2422
2423 /// True if this function has an inferred error set.
2424 inferred_error_set: bool,
2425
2426 _: u14 = 0,
2427
2428 pub const State = enum(u8) {
2429 /// This function has not yet undergone analysis, because we have not
2430 /// seen a potential runtime call. It may be analyzed in future.
2431 none,
2432 /// Analysis for this function has been queued, but not yet completed.
2433 queued,
2434 /// This function intentionally only has ZIR generated because it is marked
2435 /// inline, which means no runtime version of the function will be generated.
2436 inline_only,
2437 in_progress,
2438 /// There will be a corresponding ErrorMsg in Module.failed_decls
2439 sema_failure,
2440 /// This function might be OK but it depends on another Decl which did not
2441 /// successfully complete semantic analysis.
2442 dependency_failure,
2443 success,
21832444 };
21842445};
21852446
......@@ -2251,6 +2512,7 @@ pub const SimpleType = enum(u32) {
22512512 extern_options,
22522513 type_info,
22532514
2515 adhoc_inferred_error_set,
22542516 generic_poison,
22552517};
22562518
......@@ -2499,7 +2761,7 @@ pub const Float128 = struct {
24992761/// Trailing:
25002762/// 0. arg value: Index for each args_len
25012763pub const MemoizedCall = struct {
2502 func: Module.Fn.Index,
2764 func: Index,
25032765 args_len: u32,
25042766 result: Index,
25052767};
......@@ -2553,11 +2815,11 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
25532815 ip.unions_free_list.deinit(gpa);
25542816 ip.allocated_unions.deinit(gpa);
25552817
2556 ip.funcs_free_list.deinit(gpa);
2557 ip.allocated_funcs.deinit(gpa);
2818 ip.decls_free_list.deinit(gpa);
2819 ip.allocated_decls.deinit(gpa);
25582820
2559 ip.inferred_error_sets_free_list.deinit(gpa);
2560 ip.allocated_inferred_error_sets.deinit(gpa);
2821 ip.namespaces_free_list.deinit(gpa);
2822 ip.allocated_namespaces.deinit(gpa);
25612823
25622824 for (ip.maps.items) |*map| map.deinit(gpa);
25632825 ip.maps.deinit(gpa);
......@@ -2620,26 +2882,22 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
26202882 return .{ .ptr_type = ptr_info };
26212883 },
26222884
2623 .type_optional => .{ .opt_type = @as(Index, @enumFromInt(data)) },
2624 .type_anyframe => .{ .anyframe_type = @as(Index, @enumFromInt(data)) },
2885 .type_optional => .{ .opt_type = @enumFromInt(data) },
2886 .type_anyframe => .{ .anyframe_type = @enumFromInt(data) },
26252887
26262888 .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) },
2627 .type_error_set => {
2628 const error_set = ip.extraDataTrail(ErrorSet, data);
2629 const names_len = error_set.data.names_len;
2630 const names = ip.extra.items[error_set.end..][0..names_len];
2631 return .{ .error_set_type = .{
2632 .names = @as([]const NullTerminatedString, @ptrCast(names)),
2633 .names_map = error_set.data.names_map.toOptional(),
2634 } };
2635 },
2889 .type_anyerror_union => .{ .error_union_type = .{
2890 .error_set_type = .anyerror_type,
2891 .payload_type = @enumFromInt(data),
2892 } },
2893 .type_error_set => .{ .error_set_type = ip.extraErrorSet(data) },
26362894 .type_inferred_error_set => .{
2637 .inferred_error_set_type = @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(data)),
2895 .inferred_error_set_type = @enumFromInt(data),
26382896 },
26392897
26402898 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
26412899 .type_struct => {
2642 const struct_index = @as(Module.Struct.OptionalIndex, @enumFromInt(data));
2900 const struct_index: Module.Struct.OptionalIndex = @enumFromInt(data);
26432901 const namespace = if (struct_index.unwrap()) |i|
26442902 ip.structPtrConst(i).namespace.toOptional()
26452903 else
......@@ -2661,9 +2919,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
26612919 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
26622920 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];
26632921 return .{ .anon_struct_type = .{
2664 .types = @as([]const Index, @ptrCast(types)),
2665 .values = @as([]const Index, @ptrCast(values)),
2666 .names = @as([]const NullTerminatedString, @ptrCast(names)),
2922 .types = @ptrCast(types),
2923 .values = @ptrCast(values),
2924 .names = @ptrCast(names),
26672925 } };
26682926 },
26692927 .type_tuple_anon => {
......@@ -2672,8 +2930,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
26722930 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
26732931 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
26742932 return .{ .anon_struct_type = .{
2675 .types = @as([]const Index, @ptrCast(types)),
2676 .values = @as([]const Index, @ptrCast(values)),
2933 .types = @ptrCast(types),
2934 .values = @ptrCast(values),
26772935 .names = &.{},
26782936 } };
26792937 },
......@@ -2710,7 +2968,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
27102968 },
27112969 .type_enum_explicit => ip.indexToKeyEnum(data, .explicit),
27122970 .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive),
2713 .type_function => .{ .func_type = ip.indexToKeyFuncType(data) },
2971 .type_function => .{ .func_type = ip.extraFuncType(data) },
27142972
27152973 .undef => .{ .undef = @as(Index, @enumFromInt(data)) },
27162974 .runtime_value => .{ .runtime_value = ip.extraData(Tag.TypeValue, data) },
......@@ -2957,7 +3215,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
29573215 } };
29583216 },
29593217 .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) },
2960 .func => .{ .func = ip.extraData(Tag.Func, data) },
3218 .func_instance => .{ .func = ip.extraFuncInstance(data) },
3219 .func_decl => .{ .func = ip.extraFuncDecl(data) },
3220 .func_coerced => .{ .func = ip.extraFuncCoerced(data) },
29613221 .only_possible_value => {
29623222 const ty = @as(Index, @enumFromInt(data));
29633223 const ty_item = ip.items.get(@intFromEnum(ty));
......@@ -3062,27 +3322,104 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
30623322 };
30633323}
30643324
3065fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType {
3066 const type_function = ip.extraDataTrail(TypeFunction, data);
3067 const param_types = @as(
3068 []Index,
3069 @ptrCast(ip.extra.items[type_function.end..][0..type_function.data.params_len]),
3070 );
3325fn extraErrorSet(ip: *const InternPool, extra_index: u32) Key.ErrorSetType {
3326 const error_set = ip.extraDataTrail(Tag.ErrorSet, extra_index);
3327 return .{
3328 .names = .{
3329 .start = @intCast(error_set.end),
3330 .len = error_set.data.names_len,
3331 },
3332 .names_map = error_set.data.names_map.toOptional(),
3333 };
3334}
3335
3336fn extraFuncType(ip: *const InternPool, extra_index: u32) Key.FuncType {
3337 const type_function = ip.extraDataTrail(Tag.TypeFunction, extra_index);
3338 var index: usize = type_function.end;
3339 const comptime_bits: u32 = if (!type_function.data.flags.has_comptime_bits) 0 else b: {
3340 const x = ip.extra.items[index];
3341 index += 1;
3342 break :b x;
3343 };
3344 const noalias_bits: u32 = if (!type_function.data.flags.has_noalias_bits) 0 else b: {
3345 const x = ip.extra.items[index];
3346 index += 1;
3347 break :b x;
3348 };
30713349 return .{
3072 .param_types = param_types,
3350 .param_types = .{
3351 .start = @intCast(index),
3352 .len = type_function.data.params_len,
3353 },
30733354 .return_type = type_function.data.return_type,
3074 .comptime_bits = type_function.data.comptime_bits,
3075 .noalias_bits = type_function.data.noalias_bits,
3355 .comptime_bits = comptime_bits,
3356 .noalias_bits = noalias_bits,
30763357 .alignment = type_function.data.flags.alignment,
30773358 .cc = type_function.data.flags.cc,
30783359 .is_var_args = type_function.data.flags.is_var_args,
3079 .is_generic = type_function.data.flags.is_generic,
30803360 .is_noinline = type_function.data.flags.is_noinline,
30813361 .align_is_generic = type_function.data.flags.align_is_generic,
30823362 .cc_is_generic = type_function.data.flags.cc_is_generic,
30833363 .section_is_generic = type_function.data.flags.section_is_generic,
30843364 .addrspace_is_generic = type_function.data.flags.addrspace_is_generic,
3365 .is_generic = type_function.data.flags.is_generic,
3366 };
3367}
3368
3369fn extraFuncDecl(ip: *const InternPool, extra_index: u32) Key.Func {
3370 const P = Tag.FuncDecl;
3371 const func_decl = ip.extraDataTrail(P, extra_index);
3372 return .{
3373 .ty = func_decl.data.ty,
3374 .analysis_extra_index = extra_index + std.meta.fieldIndex(P, "analysis").?,
3375 .zir_body_inst_extra_index = extra_index + std.meta.fieldIndex(P, "zir_body_inst").?,
3376 .resolved_error_set_extra_index = if (func_decl.data.analysis.inferred_error_set) func_decl.end else 0,
3377 .branch_quota_extra_index = 0,
3378 .owner_decl = func_decl.data.owner_decl,
3379 .zir_body_inst = func_decl.data.zir_body_inst,
3380 .lbrace_line = func_decl.data.lbrace_line,
3381 .rbrace_line = func_decl.data.rbrace_line,
3382 .lbrace_column = func_decl.data.lbrace_column,
3383 .rbrace_column = func_decl.data.rbrace_column,
3384 .generic_owner = .none,
3385 .comptime_args = .{ .start = 0, .len = 0 },
3386 };
3387}
3388
3389fn extraFuncInstance(ip: *const InternPool, extra_index: u32) Key.Func {
3390 const P = Tag.FuncInstance;
3391 const fi = ip.extraDataTrail(P, extra_index);
3392 const func_decl = ip.funcDeclInfo(fi.data.generic_owner);
3393 return .{
3394 .ty = fi.data.ty,
3395 .analysis_extra_index = extra_index + std.meta.fieldIndex(P, "analysis").?,
3396 .zir_body_inst_extra_index = func_decl.zir_body_inst_extra_index,
3397 .resolved_error_set_extra_index = if (fi.data.analysis.inferred_error_set) fi.end else 0,
3398 .branch_quota_extra_index = extra_index + std.meta.fieldIndex(P, "branch_quota").?,
3399 .owner_decl = fi.data.owner_decl,
3400 .zir_body_inst = func_decl.zir_body_inst,
3401 .lbrace_line = func_decl.lbrace_line,
3402 .rbrace_line = func_decl.rbrace_line,
3403 .lbrace_column = func_decl.lbrace_column,
3404 .rbrace_column = func_decl.rbrace_column,
3405 .generic_owner = fi.data.generic_owner,
3406 .comptime_args = .{
3407 .start = fi.end + @intFromBool(fi.data.analysis.inferred_error_set),
3408 .len = ip.funcTypeParamsLen(func_decl.ty),
3409 },
3410 };
3411}
3412
3413fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func {
3414 const func_coerced = ip.extraData(Tag.FuncCoerced, extra_index);
3415 const sub_item = ip.items.get(@intFromEnum(func_coerced.func));
3416 var func: Key.Func = switch (sub_item.tag) {
3417 .func_instance => ip.extraFuncInstance(sub_item.data),
3418 .func_decl => ip.extraFuncDecl(sub_item.data),
3419 else => unreachable,
30853420 };
3421 func.ty = func_coerced.ty;
3422 return func;
30863423}
30873424
30883425fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
......@@ -3122,7 +3459,7 @@ fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key
31223459pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
31233460 const adapter: KeyAdapter = .{ .intern_pool = ip };
31243461 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
3125 if (gop.found_existing) return @as(Index, @enumFromInt(gop.index));
3462 if (gop.found_existing) return @enumFromInt(gop.index);
31263463 try ip.items.ensureUnusedCapacity(gpa, 1);
31273464 switch (key) {
31283465 .int_type => |int_type| {
......@@ -3213,26 +3550,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
32133550 });
32143551 },
32153552 .error_union_type => |error_union_type| {
3216 ip.items.appendAssumeCapacity(.{
3553 ip.items.appendAssumeCapacity(if (error_union_type.error_set_type == .anyerror_type) .{
3554 .tag = .type_anyerror_union,
3555 .data = @intFromEnum(error_union_type.payload_type),
3556 } else .{
32173557 .tag = .type_error_union,
32183558 .data = try ip.addExtra(gpa, error_union_type),
32193559 });
32203560 },
32213561 .error_set_type => |error_set_type| {
32223562 assert(error_set_type.names_map == .none);
3223 assert(std.sort.isSorted(NullTerminatedString, error_set_type.names, {}, NullTerminatedString.indexLessThan));
3563 assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan));
32243564 const names_map = try ip.addMap(gpa);
3225 try addStringsToMap(ip, gpa, names_map, error_set_type.names);
3226 const names_len = @as(u32, @intCast(error_set_type.names.len));
3227 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(ErrorSet).Struct.fields.len + names_len);
3565 try addStringsToMap(ip, gpa, names_map, error_set_type.names.get(ip));
3566 const names_len = error_set_type.names.len;
3567 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.ErrorSet).Struct.fields.len + names_len);
32283568 ip.items.appendAssumeCapacity(.{
32293569 .tag = .type_error_set,
3230 .data = ip.addExtraAssumeCapacity(ErrorSet{
3570 .data = ip.addExtraAssumeCapacity(Tag.ErrorSet{
32313571 .names_len = names_len,
32323572 .names_map = names_map,
32333573 }),
32343574 });
3235 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(error_set_type.names)));
3575 ip.extra.appendSliceAssumeCapacity(@ptrCast(error_set_type.names.get(ip)));
32363576 },
32373577 .inferred_error_set_type => |ies_index| {
32383578 ip.items.appendAssumeCapacity(.{
......@@ -3369,36 +3709,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
33693709 }
33703710 },
33713711
3372 .func_type => |func_type| {
3373 assert(func_type.return_type != .none);
3374 for (func_type.param_types) |param_type| assert(param_type != .none);
3375
3376 const params_len = @as(u32, @intCast(func_type.param_types.len));
3377
3378 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(TypeFunction).Struct.fields.len +
3379 params_len);
3380 ip.items.appendAssumeCapacity(.{
3381 .tag = .type_function,
3382 .data = ip.addExtraAssumeCapacity(TypeFunction{
3383 .params_len = params_len,
3384 .return_type = func_type.return_type,
3385 .comptime_bits = func_type.comptime_bits,
3386 .noalias_bits = func_type.noalias_bits,
3387 .flags = .{
3388 .alignment = func_type.alignment,
3389 .cc = func_type.cc,
3390 .is_var_args = func_type.is_var_args,
3391 .is_generic = func_type.is_generic,
3392 .is_noinline = func_type.is_noinline,
3393 .align_is_generic = func_type.align_is_generic,
3394 .cc_is_generic = func_type.cc_is_generic,
3395 .section_is_generic = func_type.section_is_generic,
3396 .addrspace_is_generic = func_type.addrspace_is_generic,
3397 },
3398 }),
3399 });
3400 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(func_type.param_types)));
3401 },
3712 .func_type => unreachable, // use getFuncType() instead
3713 .extern_func => unreachable, // use getExternFunc() instead
3714 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead
34023715
34033716 .variable => |variable| {
34043717 const has_init = variable.init != .none;
......@@ -3420,16 +3733,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
34203733 });
34213734 },
34223735
3423 .extern_func => |extern_func| ip.items.appendAssumeCapacity(.{
3424 .tag = .extern_func,
3425 .data = try ip.addExtra(gpa, @as(Tag.ExternFunc, extern_func)),
3426 }),
3427
3428 .func => |func| ip.items.appendAssumeCapacity(.{
3429 .tag = .func,
3430 .data = try ip.addExtra(gpa, @as(Tag.Func, func)),
3431 }),
3432
34333736 .ptr => |ptr| {
34343737 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
34353738 switch (ptr.len) {
......@@ -4065,108 +4368,705 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
40654368 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values)));
40664369 },
40674370 }
4068 return @as(Index, @enumFromInt(ip.items.len - 1));
4371 return @enumFromInt(ip.items.len - 1);
40694372}
40704373
4071/// Provides API for completing an enum type after calling `getIncompleteEnum`.
4072pub const IncompleteEnumType = struct {
4073 index: Index,
4074 tag_ty_index: u32,
4075 names_map: MapIndex,
4076 names_start: u32,
4077 values_map: OptionalMapIndex,
4078 values_start: u32,
4374/// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`.
4375pub const GetFuncTypeKey = struct {
4376 param_types: []Index,
4377 return_type: Index,
4378 comptime_bits: u32,
4379 noalias_bits: u32,
4380 /// `null` means generic.
4381 alignment: ?Alignment,
4382 /// `null` means generic.
4383 cc: ?std.builtin.CallingConvention,
4384 is_var_args: bool,
4385 is_generic: bool,
4386 is_noinline: bool,
4387 section_is_generic: bool,
4388 addrspace_is_generic: bool,
4389};
40794390
4080 pub fn setTagType(self: @This(), ip: *InternPool, tag_ty: Index) void {
4081 assert(tag_ty == .noreturn_type or ip.isIntegerType(tag_ty));
4082 ip.extra.items[self.tag_ty_index] = @intFromEnum(tag_ty);
4083 }
4391pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocator.Error!Index {
4392 // Validate input parameters.
4393 assert(key.return_type != .none);
4394 for (key.param_types) |param_type| assert(param_type != .none);
4395
4396 // The strategy here is to add the function type unconditionally, then to
4397 // ask if it already exists, and if so, revert the lengths of the mutated
4398 // arrays. This is similar to what `getOrPutTrailingString` does.
4399 const prev_extra_len = ip.extra.items.len;
4400 const params_len: u32 = @intCast(key.param_types.len);
4401
4402 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeFunction).Struct.fields.len +
4403 @intFromBool(key.comptime_bits != 0) +
4404 @intFromBool(key.noalias_bits != 0) +
4405 params_len);
4406 try ip.items.ensureUnusedCapacity(gpa, 1);
40844407
4085 /// Returns the already-existing field with the same name, if any.
4086 pub fn addFieldName(
4087 self: @This(),
4088 ip: *InternPool,
4089 gpa: Allocator,
4090 name: NullTerminatedString,
4091 ) Allocator.Error!?u32 {
4092 const map = &ip.maps.items[@intFromEnum(self.names_map)];
4093 const field_index = map.count();
4094 const strings = ip.extra.items[self.names_start..][0..field_index];
4095 const adapter: NullTerminatedString.Adapter = .{
4096 .strings = @as([]const NullTerminatedString, @ptrCast(strings)),
4097 };
4098 const gop = try map.getOrPutAdapted(gpa, name, adapter);
4099 if (gop.found_existing) return @as(u32, @intCast(gop.index));
4100 ip.extra.items[self.names_start + field_index] = @intFromEnum(name);
4101 return null;
4102 }
4408 const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{
4409 .params_len = params_len,
4410 .return_type = key.return_type,
4411 .flags = .{
4412 .alignment = key.alignment orelse .none,
4413 .cc = key.cc orelse .Unspecified,
4414 .is_var_args = key.is_var_args,
4415 .has_comptime_bits = key.comptime_bits != 0,
4416 .has_noalias_bits = key.noalias_bits != 0,
4417 .is_generic = key.is_generic,
4418 .is_noinline = key.is_noinline,
4419 .align_is_generic = key.alignment == null,
4420 .cc_is_generic = key.cc == null,
4421 .section_is_generic = key.section_is_generic,
4422 .addrspace_is_generic = key.addrspace_is_generic,
4423 },
4424 });
41034425
4104 /// Returns the already-existing field with the same value, if any.
4105 /// Make sure the type of the value has the integer tag type of the enum.
4106 pub fn addFieldValue(
4107 self: @This(),
4108 ip: *InternPool,
4109 gpa: Allocator,
4110 value: Index,
4111 ) Allocator.Error!?u32 {
4112 assert(ip.typeOf(value) == @as(Index, @enumFromInt(ip.extra.items[self.tag_ty_index])));
4113 const map = &ip.maps.items[@intFromEnum(self.values_map.unwrap().?)];
4114 const field_index = map.count();
4115 const indexes = ip.extra.items[self.values_start..][0..field_index];
4116 const adapter: Index.Adapter = .{
4117 .indexes = @as([]const Index, @ptrCast(indexes)),
4118 };
4119 const gop = try map.getOrPutAdapted(gpa, value, adapter);
4120 if (gop.found_existing) return @as(u32, @intCast(gop.index));
4121 ip.extra.items[self.values_start + field_index] = @intFromEnum(value);
4122 return null;
4123 }
4124};
4426 if (key.comptime_bits != 0) ip.extra.appendAssumeCapacity(key.comptime_bits);
4427 if (key.noalias_bits != 0) ip.extra.appendAssumeCapacity(key.noalias_bits);
4428 ip.extra.appendSliceAssumeCapacity(@ptrCast(key.param_types));
41254429
4126/// This is used to create an enum type in the `InternPool`, with the ability
4127/// to update the tag type, field names, and field values later.
4128pub fn getIncompleteEnum(
4129 ip: *InternPool,
4130 gpa: Allocator,
4131 enum_type: Key.IncompleteEnumType,
4132) Allocator.Error!IncompleteEnumType {
4133 switch (enum_type.tag_mode) {
4134 .auto => return getIncompleteEnumAuto(ip, gpa, enum_type),
4135 .explicit => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_explicit),
4136 .nonexhaustive => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_nonexhaustive),
4430 const adapter: KeyAdapter = .{ .intern_pool = ip };
4431 const gop = try ip.map.getOrPutAdapted(gpa, Key{
4432 .func_type = extraFuncType(ip, func_type_extra_index),
4433 }, adapter);
4434 if (gop.found_existing) {
4435 ip.extra.items.len = prev_extra_len;
4436 return @enumFromInt(gop.index);
41374437 }
4138}
41394438
4140fn getIncompleteEnumAuto(
4141 ip: *InternPool,
4142 gpa: Allocator,
4143 enum_type: Key.IncompleteEnumType,
4144) Allocator.Error!IncompleteEnumType {
4145 const int_tag_type = if (enum_type.tag_ty != .none)
4146 enum_type.tag_ty
4147 else
4148 try ip.get(gpa, .{ .int_type = .{
4149 .bits = if (enum_type.fields_len == 0) 0 else std.math.log2_int_ceil(u32, enum_type.fields_len),
4150 .signedness = .unsigned,
4151 } });
4439 ip.items.appendAssumeCapacity(.{
4440 .tag = .type_function,
4441 .data = func_type_extra_index,
4442 });
4443 return @enumFromInt(ip.items.len - 1);
4444}
41524445
4153 // We must keep the map in sync with `items`. The hash and equality functions
4154 // for enum types only look at the decl field, which is present even in
4155 // an `IncompleteEnumType`.
4446pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Allocator.Error!Index {
41564447 const adapter: KeyAdapter = .{ .intern_pool = ip };
4157 const gop = try ip.map.getOrPutAdapted(gpa, enum_type.toKey(), adapter);
4158 assert(!gop.found_existing);
4448 const gop = try ip.map.getOrPutAdapted(gpa, Key{ .extern_func = key }, adapter);
4449 if (gop.found_existing) return @enumFromInt(gop.index);
4450 errdefer _ = ip.map.pop();
4451 const prev_extra_len = ip.extra.items.len;
4452 const extra_index = try ip.addExtra(gpa, @as(Tag.ExternFunc, key));
4453 errdefer ip.extra.items.len = prev_extra_len;
4454 try ip.items.append(gpa, .{
4455 .tag = .extern_func,
4456 .data = extra_index,
4457 });
4458 errdefer ip.items.len -= 1;
4459 return @enumFromInt(ip.items.len - 1);
4460}
41594461
4160 const names_map = try ip.addMap(gpa);
4462pub const GetFuncDeclKey = struct {
4463 owner_decl: Module.Decl.Index,
4464 ty: Index,
4465 zir_body_inst: Zir.Inst.Index,
4466 lbrace_line: u32,
4467 rbrace_line: u32,
4468 lbrace_column: u32,
4469 rbrace_column: u32,
4470 cc: ?std.builtin.CallingConvention,
4471 is_noinline: bool,
4472};
41614473
4162 const extra_fields_len: u32 = @typeInfo(EnumAuto).Struct.fields.len;
4163 try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.fields_len);
4474pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index {
4475 // The strategy here is to add the function type unconditionally, then to
4476 // ask if it already exists, and if so, revert the lengths of the mutated
4477 // arrays. This is similar to what `getOrPutTrailingString` does.
4478 const prev_extra_len = ip.extra.items.len;
4479
4480 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncDecl).Struct.fields.len);
41644481 try ip.items.ensureUnusedCapacity(gpa, 1);
4482 try ip.map.ensureUnusedCapacity(gpa, 1);
4483
4484 const func_decl_extra_index = ip.addExtraAssumeCapacity(Tag.FuncDecl{
4485 .analysis = .{
4486 .state = if (key.cc == .Inline) .inline_only else .none,
4487 .is_cold = false,
4488 .is_noinline = key.is_noinline,
4489 .calls_or_awaits_errorable_fn = false,
4490 .stack_alignment = .none,
4491 .inferred_error_set = false,
4492 },
4493 .owner_decl = key.owner_decl,
4494 .ty = key.ty,
4495 .zir_body_inst = key.zir_body_inst,
4496 .lbrace_line = key.lbrace_line,
4497 .rbrace_line = key.rbrace_line,
4498 .lbrace_column = key.lbrace_column,
4499 .rbrace_column = key.rbrace_column,
4500 });
41654501
4166 const extra_index = ip.addExtraAssumeCapacity(EnumAuto{
4167 .decl = enum_type.decl,
4168 .namespace = enum_type.namespace,
4169 .int_tag_type = int_tag_type,
4502 const adapter: KeyAdapter = .{ .intern_pool = ip };
4503 const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{
4504 .func = extraFuncDecl(ip, func_decl_extra_index),
4505 }, adapter);
4506
4507 if (gop.found_existing) {
4508 ip.extra.items.len = prev_extra_len;
4509 return @enumFromInt(gop.index);
4510 }
4511
4512 ip.items.appendAssumeCapacity(.{
4513 .tag = .func_decl,
4514 .data = func_decl_extra_index,
4515 });
4516 return @enumFromInt(ip.items.len - 1);
4517}
4518
4519pub const GetFuncDeclIesKey = struct {
4520 owner_decl: Module.Decl.Index,
4521 param_types: []Index,
4522 noalias_bits: u32,
4523 comptime_bits: u32,
4524 bare_return_type: Index,
4525 /// null means generic.
4526 cc: ?std.builtin.CallingConvention,
4527 /// null means generic.
4528 alignment: ?Alignment,
4529 section_is_generic: bool,
4530 addrspace_is_generic: bool,
4531 is_var_args: bool,
4532 is_generic: bool,
4533 is_noinline: bool,
4534 zir_body_inst: Zir.Inst.Index,
4535 lbrace_line: u32,
4536 rbrace_line: u32,
4537 lbrace_column: u32,
4538 rbrace_column: u32,
4539};
4540
4541pub fn getFuncDeclIes(ip: *InternPool, gpa: Allocator, key: GetFuncDeclIesKey) Allocator.Error!Index {
4542 // Validate input parameters.
4543 assert(key.bare_return_type != .none);
4544 for (key.param_types) |param_type| assert(param_type != .none);
4545
4546 // The strategy here is to add the function decl unconditionally, then to
4547 // ask if it already exists, and if so, revert the lengths of the mutated
4548 // arrays. This is similar to what `getOrPutTrailingString` does.
4549 const prev_extra_len = ip.extra.items.len;
4550 const params_len: u32 = @intCast(key.param_types.len);
4551
4552 try ip.map.ensureUnusedCapacity(gpa, 4);
4553 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncDecl).Struct.fields.len +
4554 1 + // inferred_error_set
4555 @typeInfo(Tag.ErrorUnionType).Struct.fields.len +
4556 @typeInfo(Tag.TypeFunction).Struct.fields.len +
4557 @intFromBool(key.comptime_bits != 0) +
4558 @intFromBool(key.noalias_bits != 0) +
4559 params_len);
4560 try ip.items.ensureUnusedCapacity(gpa, 4);
4561
4562 const func_decl_extra_index = ip.addExtraAssumeCapacity(Tag.FuncDecl{
4563 .analysis = .{
4564 .state = if (key.cc == .Inline) .inline_only else .none,
4565 .is_cold = false,
4566 .is_noinline = key.is_noinline,
4567 .calls_or_awaits_errorable_fn = false,
4568 .stack_alignment = .none,
4569 .inferred_error_set = true,
4570 },
4571 .owner_decl = key.owner_decl,
4572 .ty = @enumFromInt(ip.items.len + 3),
4573 .zir_body_inst = key.zir_body_inst,
4574 .lbrace_line = key.lbrace_line,
4575 .rbrace_line = key.rbrace_line,
4576 .lbrace_column = key.lbrace_column,
4577 .rbrace_column = key.rbrace_column,
4578 });
4579
4580 ip.items.appendAssumeCapacity(.{
4581 .tag = .func_decl,
4582 .data = func_decl_extra_index,
4583 });
4584 ip.extra.appendAssumeCapacity(@intFromEnum(Index.none));
4585
4586 ip.items.appendAssumeCapacity(.{
4587 .tag = .type_error_union,
4588 .data = ip.addExtraAssumeCapacity(Tag.ErrorUnionType{
4589 .error_set_type = @enumFromInt(ip.items.len + 1),
4590 .payload_type = key.bare_return_type,
4591 }),
4592 });
4593
4594 ip.items.appendAssumeCapacity(.{
4595 .tag = .type_inferred_error_set,
4596 .data = @intCast(ip.items.len - 2),
4597 });
4598
4599 const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{
4600 .params_len = params_len,
4601 .return_type = @enumFromInt(ip.items.len - 2),
4602 .flags = .{
4603 .alignment = key.alignment orelse .none,
4604 .cc = key.cc orelse .Unspecified,
4605 .is_var_args = key.is_var_args,
4606 .has_comptime_bits = key.comptime_bits != 0,
4607 .has_noalias_bits = key.noalias_bits != 0,
4608 .is_generic = key.is_generic,
4609 .is_noinline = key.is_noinline,
4610 .align_is_generic = key.alignment == null,
4611 .cc_is_generic = key.cc == null,
4612 .section_is_generic = key.section_is_generic,
4613 .addrspace_is_generic = key.addrspace_is_generic,
4614 },
4615 });
4616 if (key.comptime_bits != 0) ip.extra.appendAssumeCapacity(key.comptime_bits);
4617 if (key.noalias_bits != 0) ip.extra.appendAssumeCapacity(key.noalias_bits);
4618 ip.extra.appendSliceAssumeCapacity(@ptrCast(key.param_types));
4619
4620 ip.items.appendAssumeCapacity(.{
4621 .tag = .type_function,
4622 .data = func_type_extra_index,
4623 });
4624
4625 const adapter: KeyAdapter = .{ .intern_pool = ip };
4626 const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{
4627 .func = extraFuncDecl(ip, func_decl_extra_index),
4628 }, adapter);
4629 if (!gop.found_existing) {
4630 assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ .error_union_type = .{
4631 .error_set_type = @enumFromInt(ip.items.len - 2),
4632 .payload_type = key.bare_return_type,
4633 } }, adapter).found_existing);
4634 assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{
4635 .inferred_error_set_type = @enumFromInt(ip.items.len - 4),
4636 }, adapter).found_existing);
4637 assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{
4638 .func_type = extraFuncType(ip, func_type_extra_index),
4639 }, adapter).found_existing);
4640 return @enumFromInt(ip.items.len - 4);
4641 }
4642
4643 // An existing function type was found; undo the additions to our two arrays.
4644 ip.items.len -= 4;
4645 ip.extra.items.len = prev_extra_len;
4646 return @enumFromInt(gop.index);
4647}
4648
4649pub fn getErrorSetType(
4650 ip: *InternPool,
4651 gpa: Allocator,
4652 names: []const NullTerminatedString,
4653) Allocator.Error!Index {
4654 assert(std.sort.isSorted(NullTerminatedString, names, {}, NullTerminatedString.indexLessThan));
4655
4656 // The strategy here is to add the type unconditionally, then to ask if it
4657 // already exists, and if so, revert the lengths of the mutated arrays.
4658 // This is similar to what `getOrPutTrailingString` does.
4659 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.ErrorSet).Struct.fields.len + names.len);
4660
4661 const prev_extra_len = ip.extra.items.len;
4662 errdefer ip.extra.items.len = prev_extra_len;
4663
4664 const predicted_names_map: MapIndex = @enumFromInt(ip.maps.items.len);
4665
4666 const error_set_extra_index = ip.addExtraAssumeCapacity(Tag.ErrorSet{
4667 .names_len = @intCast(names.len),
4668 .names_map = predicted_names_map,
4669 });
4670 ip.extra.appendSliceAssumeCapacity(@ptrCast(names));
4671
4672 const adapter: KeyAdapter = .{ .intern_pool = ip };
4673 const gop = try ip.map.getOrPutAdapted(gpa, Key{
4674 .error_set_type = extraErrorSet(ip, error_set_extra_index),
4675 }, adapter);
4676 errdefer _ = ip.map.pop();
4677
4678 if (gop.found_existing) {
4679 ip.extra.items.len = prev_extra_len;
4680 return @enumFromInt(gop.index);
4681 }
4682
4683 try ip.items.append(gpa, .{
4684 .tag = .type_error_set,
4685 .data = error_set_extra_index,
4686 });
4687 errdefer ip.items.len -= 1;
4688
4689 const names_map = try ip.addMap(gpa);
4690 errdefer _ = ip.maps.pop();
4691
4692 try addStringsToMap(ip, gpa, names_map, names);
4693
4694 return @enumFromInt(ip.items.len - 1);
4695}
4696
4697pub const GetFuncInstanceKey = struct {
4698 /// Has the length of the instance function (may be lesser than
4699 /// comptime_args).
4700 param_types: []Index,
4701 /// Has the length of generic_owner's parameters (may be greater than
4702 /// param_types).
4703 comptime_args: []const Index,
4704 noalias_bits: u32,
4705 bare_return_type: Index,
4706 cc: std.builtin.CallingConvention,
4707 alignment: Alignment,
4708 section: OptionalNullTerminatedString,
4709 is_noinline: bool,
4710 generic_owner: Index,
4711 inferred_error_set: bool,
4712 generation: u32,
4713};
4714
4715pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey) Allocator.Error!Index {
4716 if (arg.inferred_error_set)
4717 return getFuncInstanceIes(ip, gpa, arg);
4718
4719 const func_ty = try ip.getFuncType(gpa, .{
4720 .param_types = arg.param_types,
4721 .return_type = arg.bare_return_type,
4722 .comptime_bits = 0,
4723 .noalias_bits = arg.noalias_bits,
4724 .alignment = arg.alignment,
4725 .cc = arg.cc,
4726 .is_var_args = false,
4727 .is_generic = false,
4728 .is_noinline = arg.is_noinline,
4729 .section_is_generic = false,
4730 .addrspace_is_generic = false,
4731 });
4732
4733 const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner);
4734
4735 assert(arg.comptime_args.len == ip.funcTypeParamsLen(ip.typeOf(generic_owner)));
4736
4737 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncInstance).Struct.fields.len +
4738 arg.comptime_args.len);
4739 const prev_extra_len = ip.extra.items.len;
4740 errdefer ip.extra.items.len = prev_extra_len;
4741
4742 const func_extra_index = ip.addExtraAssumeCapacity(Tag.FuncInstance{
4743 .analysis = .{
4744 .state = if (arg.cc == .Inline) .inline_only else .none,
4745 .is_cold = false,
4746 .is_noinline = arg.is_noinline,
4747 .calls_or_awaits_errorable_fn = false,
4748 .stack_alignment = .none,
4749 .inferred_error_set = false,
4750 },
4751 // This is populated after we create the Decl below. It is not read
4752 // by equality or hashing functions.
4753 .owner_decl = undefined,
4754 .ty = func_ty,
4755 .branch_quota = 0,
4756 .generic_owner = generic_owner,
4757 });
4758 ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.comptime_args));
4759
4760 const gop = try ip.map.getOrPutAdapted(gpa, Key{
4761 .func = extraFuncInstance(ip, func_extra_index),
4762 }, KeyAdapter{ .intern_pool = ip });
4763 errdefer _ = ip.map.pop();
4764
4765 if (gop.found_existing) {
4766 ip.extra.items.len = prev_extra_len;
4767 return @enumFromInt(gop.index);
4768 }
4769
4770 const func_index: Index = @enumFromInt(ip.items.len);
4771
4772 try ip.items.append(gpa, .{
4773 .tag = .func_instance,
4774 .data = func_extra_index,
4775 });
4776 errdefer ip.items.len -= 1;
4777
4778 return finishFuncInstance(
4779 ip,
4780 gpa,
4781 generic_owner,
4782 func_index,
4783 func_extra_index,
4784 arg.generation,
4785 func_ty,
4786 arg.section,
4787 );
4788}
4789
4790/// This function exists separately than `getFuncInstance` because it needs to
4791/// create 4 new items in the InternPool atomically before it can look for an
4792/// existing item in the map.
4793pub fn getFuncInstanceIes(
4794 ip: *InternPool,
4795 gpa: Allocator,
4796 arg: GetFuncInstanceKey,
4797) Allocator.Error!Index {
4798 // Validate input parameters.
4799 assert(arg.inferred_error_set);
4800 assert(arg.bare_return_type != .none);
4801 for (arg.param_types) |param_type| assert(param_type != .none);
4802
4803 // The strategy here is to add the function decl unconditionally, then to
4804 // ask if it already exists, and if so, revert the lengths of the mutated
4805 // arrays. This is similar to what `getOrPutTrailingString` does.
4806 const prev_extra_len = ip.extra.items.len;
4807 const params_len: u32 = @intCast(arg.param_types.len);
4808
4809 try ip.map.ensureUnusedCapacity(gpa, 4);
4810 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncInstance).Struct.fields.len +
4811 1 + // inferred_error_set
4812 arg.comptime_args.len +
4813 @typeInfo(Tag.ErrorUnionType).Struct.fields.len +
4814 @typeInfo(Tag.TypeFunction).Struct.fields.len +
4815 @intFromBool(arg.noalias_bits != 0) +
4816 params_len);
4817 try ip.items.ensureUnusedCapacity(gpa, 4);
4818
4819 const func_index: Index = @enumFromInt(ip.items.len);
4820 const error_union_type: Index = @enumFromInt(ip.items.len + 1);
4821 const error_set_type: Index = @enumFromInt(ip.items.len + 2);
4822 const func_ty: Index = @enumFromInt(ip.items.len + 3);
4823
4824 const func_extra_index = ip.addExtraAssumeCapacity(Tag.FuncInstance{
4825 .analysis = .{
4826 .state = if (arg.cc == .Inline) .inline_only else .none,
4827 .is_cold = false,
4828 .is_noinline = arg.is_noinline,
4829 .calls_or_awaits_errorable_fn = false,
4830 .stack_alignment = .none,
4831 .inferred_error_set = true,
4832 },
4833 // This is populated after we create the Decl below. It is not read
4834 // by equality or hashing functions.
4835 .owner_decl = undefined,
4836 .ty = func_ty,
4837 .branch_quota = 0,
4838 .generic_owner = arg.generic_owner,
4839 });
4840 ip.extra.appendAssumeCapacity(@intFromEnum(Index.none)); // resolved error set
4841 ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.comptime_args));
4842
4843 const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{
4844 .params_len = params_len,
4845 .return_type = error_union_type,
4846 .flags = .{
4847 .alignment = arg.alignment,
4848 .cc = arg.cc,
4849 .is_var_args = false,
4850 .has_comptime_bits = false,
4851 .has_noalias_bits = arg.noalias_bits != 0,
4852 .is_generic = false,
4853 .is_noinline = arg.is_noinline,
4854 .align_is_generic = false,
4855 .cc_is_generic = false,
4856 .section_is_generic = false,
4857 .addrspace_is_generic = false,
4858 },
4859 });
4860 // no comptime_bits because has_comptime_bits is false
4861 if (arg.noalias_bits != 0) ip.extra.appendAssumeCapacity(arg.noalias_bits);
4862 ip.extra.appendSliceAssumeCapacity(@ptrCast(arg.param_types));
4863
4864 // TODO: add appendSliceAssumeCapacity to MultiArrayList.
4865 ip.items.appendAssumeCapacity(.{
4866 .tag = .func_instance,
4867 .data = func_extra_index,
4868 });
4869 ip.items.appendAssumeCapacity(.{
4870 .tag = .type_error_union,
4871 .data = ip.addExtraAssumeCapacity(Tag.ErrorUnionType{
4872 .error_set_type = error_set_type,
4873 .payload_type = arg.bare_return_type,
4874 }),
4875 });
4876 ip.items.appendAssumeCapacity(.{
4877 .tag = .type_inferred_error_set,
4878 .data = @intFromEnum(func_index),
4879 });
4880 ip.items.appendAssumeCapacity(.{
4881 .tag = .type_function,
4882 .data = func_type_extra_index,
4883 });
4884
4885 const adapter: KeyAdapter = .{ .intern_pool = ip };
4886 const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{
4887 .func = extraFuncInstance(ip, func_extra_index),
4888 }, adapter);
4889 if (gop.found_existing) {
4890 // Hot path: undo the additions to our two arrays.
4891 ip.items.len -= 4;
4892 ip.extra.items.len = prev_extra_len;
4893 return @enumFromInt(gop.index);
4894 }
4895
4896 // Synchronize the map with items.
4897 assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{ .error_union_type = .{
4898 .error_set_type = error_set_type,
4899 .payload_type = arg.bare_return_type,
4900 } }, adapter).found_existing);
4901 assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{
4902 .inferred_error_set_type = func_index,
4903 }, adapter).found_existing);
4904 assert(!ip.map.getOrPutAssumeCapacityAdapted(Key{
4905 .func_type = extraFuncType(ip, func_type_extra_index),
4906 }, adapter).found_existing);
4907
4908 return finishFuncInstance(
4909 ip,
4910 gpa,
4911 arg.generic_owner,
4912 func_index,
4913 func_extra_index,
4914 arg.generation,
4915 func_ty,
4916 arg.section,
4917 );
4918}
4919
4920fn finishFuncInstance(
4921 ip: *InternPool,
4922 gpa: Allocator,
4923 generic_owner: Index,
4924 func_index: Index,
4925 func_extra_index: u32,
4926 generation: u32,
4927 func_ty: Index,
4928 section: OptionalNullTerminatedString,
4929) Allocator.Error!Index {
4930 const fn_owner_decl = ip.declPtr(ip.funcDeclOwner(generic_owner));
4931 const decl_index = try ip.createDecl(gpa, .{
4932 .name = undefined,
4933 .src_namespace = fn_owner_decl.src_namespace,
4934 .src_node = fn_owner_decl.src_node,
4935 .src_line = fn_owner_decl.src_line,
4936 .has_tv = true,
4937 .owns_tv = true,
4938 .ty = func_ty.toType(),
4939 .val = func_index.toValue(),
4940 .alignment = .none,
4941 .@"linksection" = section,
4942 .@"addrspace" = fn_owner_decl.@"addrspace",
4943 .analysis = .complete,
4944 .deletion_flag = false,
4945 .zir_decl_index = fn_owner_decl.zir_decl_index,
4946 .src_scope = fn_owner_decl.src_scope,
4947 .generation = generation,
4948 .is_pub = fn_owner_decl.is_pub,
4949 .is_exported = fn_owner_decl.is_exported,
4950 .has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace,
4951 .has_align = fn_owner_decl.has_align,
4952 .alive = true,
4953 .kind = .anon,
4954 });
4955 errdefer ip.destroyDecl(gpa, decl_index);
4956
4957 // Populate the owner_decl field which was left undefined until now.
4958 ip.extra.items[
4959 func_extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_decl").?
4960 ] = @intFromEnum(decl_index);
4961
4962 // TODO: improve this name
4963 const decl = ip.declPtr(decl_index);
4964 decl.name = try ip.getOrPutStringFmt(gpa, "{}__anon_{d}", .{
4965 fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index),
4966 });
4967
4968 return func_index;
4969}
4970
4971/// Provides API for completing an enum type after calling `getIncompleteEnum`.
4972pub const IncompleteEnumType = struct {
4973 index: Index,
4974 tag_ty_index: u32,
4975 names_map: MapIndex,
4976 names_start: u32,
4977 values_map: OptionalMapIndex,
4978 values_start: u32,
4979
4980 pub fn setTagType(self: @This(), ip: *InternPool, tag_ty: Index) void {
4981 assert(tag_ty == .noreturn_type or ip.isIntegerType(tag_ty));
4982 ip.extra.items[self.tag_ty_index] = @intFromEnum(tag_ty);
4983 }
4984
4985 /// Returns the already-existing field with the same name, if any.
4986 pub fn addFieldName(
4987 self: @This(),
4988 ip: *InternPool,
4989 gpa: Allocator,
4990 name: NullTerminatedString,
4991 ) Allocator.Error!?u32 {
4992 const map = &ip.maps.items[@intFromEnum(self.names_map)];
4993 const field_index = map.count();
4994 const strings = ip.extra.items[self.names_start..][0..field_index];
4995 const adapter: NullTerminatedString.Adapter = .{
4996 .strings = @as([]const NullTerminatedString, @ptrCast(strings)),
4997 };
4998 const gop = try map.getOrPutAdapted(gpa, name, adapter);
4999 if (gop.found_existing) return @as(u32, @intCast(gop.index));
5000 ip.extra.items[self.names_start + field_index] = @intFromEnum(name);
5001 return null;
5002 }
5003
5004 /// Returns the already-existing field with the same value, if any.
5005 /// Make sure the type of the value has the integer tag type of the enum.
5006 pub fn addFieldValue(
5007 self: @This(),
5008 ip: *InternPool,
5009 gpa: Allocator,
5010 value: Index,
5011 ) Allocator.Error!?u32 {
5012 assert(ip.typeOf(value) == @as(Index, @enumFromInt(ip.extra.items[self.tag_ty_index])));
5013 const map = &ip.maps.items[@intFromEnum(self.values_map.unwrap().?)];
5014 const field_index = map.count();
5015 const indexes = ip.extra.items[self.values_start..][0..field_index];
5016 const adapter: Index.Adapter = .{
5017 .indexes = @as([]const Index, @ptrCast(indexes)),
5018 };
5019 const gop = try map.getOrPutAdapted(gpa, value, adapter);
5020 if (gop.found_existing) return @as(u32, @intCast(gop.index));
5021 ip.extra.items[self.values_start + field_index] = @intFromEnum(value);
5022 return null;
5023 }
5024};
5025
5026/// This is used to create an enum type in the `InternPool`, with the ability
5027/// to update the tag type, field names, and field values later.
5028pub fn getIncompleteEnum(
5029 ip: *InternPool,
5030 gpa: Allocator,
5031 enum_type: Key.IncompleteEnumType,
5032) Allocator.Error!IncompleteEnumType {
5033 switch (enum_type.tag_mode) {
5034 .auto => return getIncompleteEnumAuto(ip, gpa, enum_type),
5035 .explicit => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_explicit),
5036 .nonexhaustive => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_nonexhaustive),
5037 }
5038}
5039
5040fn getIncompleteEnumAuto(
5041 ip: *InternPool,
5042 gpa: Allocator,
5043 enum_type: Key.IncompleteEnumType,
5044) Allocator.Error!IncompleteEnumType {
5045 const int_tag_type = if (enum_type.tag_ty != .none)
5046 enum_type.tag_ty
5047 else
5048 try ip.get(gpa, .{ .int_type = .{
5049 .bits = if (enum_type.fields_len == 0) 0 else std.math.log2_int_ceil(u32, enum_type.fields_len),
5050 .signedness = .unsigned,
5051 } });
5052
5053 // We must keep the map in sync with `items`. The hash and equality functions
5054 // for enum types only look at the decl field, which is present even in
5055 // an `IncompleteEnumType`.
5056 const adapter: KeyAdapter = .{ .intern_pool = ip };
5057 const gop = try ip.map.getOrPutAdapted(gpa, enum_type.toKey(), adapter);
5058 assert(!gop.found_existing);
5059
5060 const names_map = try ip.addMap(gpa);
5061
5062 const extra_fields_len: u32 = @typeInfo(EnumAuto).Struct.fields.len;
5063 try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.fields_len);
5064 try ip.items.ensureUnusedCapacity(gpa, 1);
5065
5066 const extra_index = ip.addExtraAssumeCapacity(EnumAuto{
5067 .decl = enum_type.decl,
5068 .namespace = enum_type.namespace,
5069 .int_tag_type = int_tag_type,
41705070 .names_map = names_map,
41715071 .fields_len = enum_type.fields_len,
41725072 });
......@@ -4265,15 +5165,15 @@ pub fn finishGetEnum(
42655165 .values_map = values_map,
42665166 }),
42675167 });
4268 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.names)));
4269 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.values)));
4270 return @as(Index, @enumFromInt(ip.items.len - 1));
5168 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.names));
5169 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.values));
5170 return @enumFromInt(ip.items.len - 1);
42715171}
42725172
42735173pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {
42745174 const adapter: KeyAdapter = .{ .intern_pool = ip };
42755175 const index = ip.map.getIndexAdapted(key, adapter) orelse return null;
4276 return @as(Index, @enumFromInt(index));
5176 return @enumFromInt(index);
42775177}
42785178
42795179pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {
......@@ -4311,7 +5211,7 @@ fn addIndexesToMap(
43115211fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex {
43125212 const ptr = try ip.maps.addOne(gpa);
43135213 ptr.* = .{};
4314 return @as(MapIndex, @enumFromInt(ip.maps.items.len - 1));
5214 return @enumFromInt(ip.maps.items.len - 1);
43155215}
43165216
43175217/// This operation only happens under compile error conditions.
......@@ -4342,24 +5242,28 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
43425242 const result = @as(u32, @intCast(ip.extra.items.len));
43435243 inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| {
43445244 ip.extra.appendAssumeCapacity(switch (field.type) {
4345 u32 => @field(extra, field.name),
4346 Index => @intFromEnum(@field(extra, field.name)),
4347 Module.Decl.Index => @intFromEnum(@field(extra, field.name)),
4348 Module.Namespace.Index => @intFromEnum(@field(extra, field.name)),
4349 Module.Namespace.OptionalIndex => @intFromEnum(@field(extra, field.name)),
4350 Module.Fn.Index => @intFromEnum(@field(extra, field.name)),
4351 MapIndex => @intFromEnum(@field(extra, field.name)),
4352 OptionalMapIndex => @intFromEnum(@field(extra, field.name)),
4353 RuntimeIndex => @intFromEnum(@field(extra, field.name)),
4354 String => @intFromEnum(@field(extra, field.name)),
4355 NullTerminatedString => @intFromEnum(@field(extra, field.name)),
4356 OptionalNullTerminatedString => @intFromEnum(@field(extra, field.name)),
4357 i32 => @as(u32, @bitCast(@field(extra, field.name))),
4358 Tag.TypePointer.Flags => @as(u32, @bitCast(@field(extra, field.name))),
4359 TypeFunction.Flags => @as(u32, @bitCast(@field(extra, field.name))),
4360 Tag.TypePointer.PackedOffset => @as(u32, @bitCast(@field(extra, field.name))),
4361 Tag.TypePointer.VectorIndex => @intFromEnum(@field(extra, field.name)),
4362 Tag.Variable.Flags => @as(u32, @bitCast(@field(extra, field.name))),
5245 Index,
5246 Module.Decl.Index,
5247 Module.Namespace.Index,
5248 Module.Namespace.OptionalIndex,
5249 MapIndex,
5250 OptionalMapIndex,
5251 RuntimeIndex,
5252 String,
5253 NullTerminatedString,
5254 OptionalNullTerminatedString,
5255 Tag.TypePointer.VectorIndex,
5256 => @intFromEnum(@field(extra, field.name)),
5257
5258 u32,
5259 i32,
5260 FuncAnalysis,
5261 Tag.TypePointer.Flags,
5262 Tag.TypeFunction.Flags,
5263 Tag.TypePointer.PackedOffset,
5264 Tag.Variable.Flags,
5265 => @bitCast(@field(extra, field.name)),
5266
43635267 else => @compileError("bad field type: " ++ @typeName(field.type)),
43645268 });
43655269 }
......@@ -4404,36 +5308,40 @@ fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void {
44045308 }
44055309}
44065310
4407fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct { data: T, end: usize } {
5311fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct { data: T, end: u32 } {
44085312 var result: T = undefined;
44095313 const fields = @typeInfo(T).Struct.fields;
44105314 inline for (fields, 0..) |field, i| {
44115315 const int32 = ip.extra.items[i + index];
44125316 @field(result, field.name) = switch (field.type) {
4413 u32 => int32,
4414 Index => @as(Index, @enumFromInt(int32)),
4415 Module.Decl.Index => @as(Module.Decl.Index, @enumFromInt(int32)),
4416 Module.Namespace.Index => @as(Module.Namespace.Index, @enumFromInt(int32)),
4417 Module.Namespace.OptionalIndex => @as(Module.Namespace.OptionalIndex, @enumFromInt(int32)),
4418 Module.Fn.Index => @as(Module.Fn.Index, @enumFromInt(int32)),
4419 MapIndex => @as(MapIndex, @enumFromInt(int32)),
4420 OptionalMapIndex => @as(OptionalMapIndex, @enumFromInt(int32)),
4421 RuntimeIndex => @as(RuntimeIndex, @enumFromInt(int32)),
4422 String => @as(String, @enumFromInt(int32)),
4423 NullTerminatedString => @as(NullTerminatedString, @enumFromInt(int32)),
4424 OptionalNullTerminatedString => @as(OptionalNullTerminatedString, @enumFromInt(int32)),
4425 i32 => @as(i32, @bitCast(int32)),
4426 Tag.TypePointer.Flags => @as(Tag.TypePointer.Flags, @bitCast(int32)),
4427 TypeFunction.Flags => @as(TypeFunction.Flags, @bitCast(int32)),
4428 Tag.TypePointer.PackedOffset => @as(Tag.TypePointer.PackedOffset, @bitCast(int32)),
4429 Tag.TypePointer.VectorIndex => @as(Tag.TypePointer.VectorIndex, @enumFromInt(int32)),
4430 Tag.Variable.Flags => @as(Tag.Variable.Flags, @bitCast(int32)),
5317 Index,
5318 Module.Decl.Index,
5319 Module.Namespace.Index,
5320 Module.Namespace.OptionalIndex,
5321 MapIndex,
5322 OptionalMapIndex,
5323 RuntimeIndex,
5324 String,
5325 NullTerminatedString,
5326 OptionalNullTerminatedString,
5327 Tag.TypePointer.VectorIndex,
5328 => @enumFromInt(int32),
5329
5330 u32,
5331 i32,
5332 Tag.TypePointer.Flags,
5333 Tag.TypeFunction.Flags,
5334 Tag.TypePointer.PackedOffset,
5335 Tag.Variable.Flags,
5336 FuncAnalysis,
5337 => @bitCast(int32),
5338
44315339 else => @compileError("bad field type: " ++ @typeName(field.type)),
44325340 };
44335341 }
44345342 return .{
44355343 .data = result,
4436 .end = index + fields.len,
5344 .end = @intCast(index + fields.len),
44375345 };
44385346}
44395347
......@@ -4603,206 +5511,226 @@ pub fn sliceLen(ip: *const InternPool, i: Index) Index {
46035511pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
46045512 const old_ty = ip.typeOf(val);
46055513 if (old_ty == new_ty) return val;
5514
5515 const tags = ip.items.items(.tag);
5516
46065517 switch (val) {
46075518 .undef => return ip.get(gpa, .{ .undef = new_ty }),
4608 .null_value => if (ip.isOptionalType(new_ty))
4609 return ip.get(gpa, .{ .opt = .{
5519 .null_value => {
5520 if (ip.isOptionalType(new_ty)) return ip.get(gpa, .{ .opt = .{
46105521 .ty = new_ty,
46115522 .val = .none,
4612 } })
4613 else if (ip.isPointerType(new_ty))
4614 return ip.get(gpa, .{ .ptr = .{
5523 } });
5524
5525 if (ip.isPointerType(new_ty)) return ip.get(gpa, .{ .ptr = .{
46155526 .ty = new_ty,
46165527 .addr = .{ .int = .zero_usize },
46175528 .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) {
46185529 .One, .Many, .C => .none,
46195530 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
46205531 },
5532 } });
5533 },
5534 else => switch (tags[@intFromEnum(val)]) {
5535 .func_decl => return getCoercedFuncDecl(ip, gpa, val, new_ty),
5536 .func_instance => return getCoercedFuncInstance(ip, gpa, val, new_ty),
5537 .func_coerced => {
5538 const extra_index = ip.items.items(.data)[@intFromEnum(val)];
5539 const func: Index = @enumFromInt(
5540 ip.extra.items[extra_index + std.meta.fieldIndex(Tag.FuncCoerced, "func").?],
5541 );
5542 switch (tags[@intFromEnum(func)]) {
5543 .func_decl => return getCoercedFuncDecl(ip, gpa, val, new_ty),
5544 .func_instance => return getCoercedFuncInstance(ip, gpa, val, new_ty),
5545 else => unreachable,
5546 }
5547 },
5548 else => {},
5549 },
5550 }
5551
5552 switch (ip.indexToKey(val)) {
5553 .undef => return ip.get(gpa, .{ .undef = new_ty }),
5554 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))
5555 return ip.get(gpa, .{ .extern_func = .{
5556 .ty = new_ty,
5557 .decl = extern_func.decl,
5558 .lib_name = extern_func.lib_name,
46215559 } }),
4622 else => switch (ip.indexToKey(val)) {
4623 .undef => return ip.get(gpa, .{ .undef = new_ty }),
4624 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))
4625 return ip.get(gpa, .{ .extern_func = .{
4626 .ty = new_ty,
4627 .decl = extern_func.decl,
4628 .lib_name = extern_func.lib_name,
4629 } }),
4630 .func => |func| if (ip.isFunctionType(new_ty))
4631 return ip.get(gpa, .{ .func = .{
4632 .ty = new_ty,
4633 .index = func.index,
4634 } }),
4635 .int => |int| switch (ip.indexToKey(new_ty)) {
4636 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
4637 .ty = new_ty,
4638 .int = try ip.getCoerced(gpa, val, enum_type.tag_ty),
4639 } }),
4640 .ptr_type => return ip.get(gpa, .{ .ptr = .{
5560
5561 .func => unreachable,
5562
5563 .int => |int| switch (ip.indexToKey(new_ty)) {
5564 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
5565 .ty = new_ty,
5566 .int = try ip.getCoerced(gpa, val, enum_type.tag_ty),
5567 } }),
5568 .ptr_type => return ip.get(gpa, .{ .ptr = .{
5569 .ty = new_ty,
5570 .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) },
5571 } }),
5572 else => if (ip.isIntegerType(new_ty))
5573 return getCoercedInts(ip, gpa, int, new_ty),
5574 },
5575 .float => |float| switch (ip.indexToKey(new_ty)) {
5576 .simple_type => |simple| switch (simple) {
5577 .f16,
5578 .f32,
5579 .f64,
5580 .f80,
5581 .f128,
5582 .c_longdouble,
5583 .comptime_float,
5584 => return ip.get(gpa, .{ .float = .{
46415585 .ty = new_ty,
4642 .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) },
5586 .storage = float.storage,
46435587 } }),
4644 else => if (ip.isIntegerType(new_ty))
4645 return getCoercedInts(ip, gpa, int, new_ty),
4646 },
4647 .float => |float| switch (ip.indexToKey(new_ty)) {
4648 .simple_type => |simple| switch (simple) {
4649 .f16,
4650 .f32,
4651 .f64,
4652 .f80,
4653 .f128,
4654 .c_longdouble,
4655 .comptime_float,
4656 => return ip.get(gpa, .{ .float = .{
4657 .ty = new_ty,
4658 .storage = float.storage,
4659 } }),
4660 else => {},
4661 },
46625588 else => {},
46635589 },
4664 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
4665 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
4666 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
4667 .enum_type => |enum_type| {
4668 const index = enum_type.nameIndex(ip, enum_literal).?;
4669 return ip.get(gpa, .{ .enum_tag = .{
4670 .ty = new_ty,
4671 .int = if (enum_type.values.len != 0)
4672 enum_type.values[index]
4673 else
4674 try ip.get(gpa, .{ .int = .{
4675 .ty = enum_type.tag_ty,
4676 .storage = .{ .u64 = index },
4677 } }),
4678 } });
4679 },
5590 else => {},
5591 },
5592 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
5593 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
5594 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
5595 .enum_type => |enum_type| {
5596 const index = enum_type.nameIndex(ip, enum_literal).?;
5597 return ip.get(gpa, .{ .enum_tag = .{
5598 .ty = new_ty,
5599 .int = if (enum_type.values.len != 0)
5600 enum_type.values[index]
5601 else
5602 try ip.get(gpa, .{ .int = .{
5603 .ty = enum_type.tag_ty,
5604 .storage = .{ .u64 = index },
5605 } }),
5606 } });
5607 },
5608 else => {},
5609 },
5610 .ptr => |ptr| if (ip.isPointerType(new_ty))
5611 return ip.get(gpa, .{ .ptr = .{
5612 .ty = new_ty,
5613 .addr = ptr.addr,
5614 .len = ptr.len,
5615 } })
5616 else if (ip.isIntegerType(new_ty))
5617 switch (ptr.addr) {
5618 .int => |int| return ip.getCoerced(gpa, int, new_ty),
46805619 else => {},
46815620 },
4682 .ptr => |ptr| if (ip.isPointerType(new_ty))
4683 return ip.get(gpa, .{ .ptr = .{
5621 .opt => |opt| switch (ip.indexToKey(new_ty)) {
5622 .ptr_type => |ptr_type| return switch (opt.val) {
5623 .none => try ip.get(gpa, .{ .ptr = .{
46845624 .ty = new_ty,
4685 .addr = ptr.addr,
4686 .len = ptr.len,
4687 } })
4688 else if (ip.isIntegerType(new_ty))
4689 switch (ptr.addr) {
4690 .int => |int| return ip.getCoerced(gpa, int, new_ty),
4691 else => {},
4692 },
4693 .opt => |opt| switch (ip.indexToKey(new_ty)) {
4694 .ptr_type => |ptr_type| return switch (opt.val) {
4695 .none => try ip.get(gpa, .{ .ptr = .{
4696 .ty = new_ty,
4697 .addr = .{ .int = .zero_usize },
4698 .len = switch (ptr_type.flags.size) {
4699 .One, .Many, .C => .none,
4700 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
4701 },
4702 } }),
4703 else => |payload| try ip.getCoerced(gpa, payload, new_ty),
4704 },
4705 .opt_type => |child_type| return try ip.get(gpa, .{ .opt = .{
4706 .ty = new_ty,
4707 .val = switch (opt.val) {
4708 .none => .none,
4709 else => try ip.getCoerced(gpa, opt.val, child_type),
5625 .addr = .{ .int = .zero_usize },
5626 .len = switch (ptr_type.flags.size) {
5627 .One, .Many, .C => .none,
5628 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
47105629 },
47115630 } }),
4712 else => {},
5631 else => |payload| try ip.getCoerced(gpa, payload, new_ty),
47135632 },
4714 .err => |err| if (ip.isErrorSetType(new_ty))
4715 return ip.get(gpa, .{ .err = .{
4716 .ty = new_ty,
4717 .name = err.name,
4718 } })
4719 else if (ip.isErrorUnionType(new_ty))
4720 return ip.get(gpa, .{ .error_union = .{
4721 .ty = new_ty,
4722 .val = .{ .err_name = err.name },
4723 } }),
4724 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
4725 return ip.get(gpa, .{ .error_union = .{
4726 .ty = new_ty,
4727 .val = error_union.val,
4728 } }),
4729 .aggregate => |aggregate| {
4730 const new_len = @as(usize, @intCast(ip.aggregateTypeLen(new_ty)));
4731 direct: {
4732 const old_ty_child = switch (ip.indexToKey(old_ty)) {
4733 inline .array_type, .vector_type => |seq_type| seq_type.child,
4734 .anon_struct_type, .struct_type => break :direct,
4735 else => unreachable,
4736 };
4737 const new_ty_child = switch (ip.indexToKey(new_ty)) {
4738 inline .array_type, .vector_type => |seq_type| seq_type.child,
4739 .anon_struct_type, .struct_type => break :direct,
4740 else => unreachable,
4741 };
4742 if (old_ty_child != new_ty_child) break :direct;
4743 // TODO: write something like getCoercedInts to avoid needing to dupe here
4744 switch (aggregate.storage) {
4745 .bytes => |bytes| {
4746 const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]);
4747 defer gpa.free(bytes_copy);
4748 return ip.get(gpa, .{ .aggregate = .{
4749 .ty = new_ty,
4750 .storage = .{ .bytes = bytes_copy },
4751 } });
4752 },
4753 .elems => |elems| {
4754 const elems_copy = try gpa.dupe(InternPool.Index, elems[0..new_len]);
4755 defer gpa.free(elems_copy);
4756 return ip.get(gpa, .{ .aggregate = .{
4757 .ty = new_ty,
4758 .storage = .{ .elems = elems_copy },
4759 } });
4760 },
4761 .repeated_elem => |elem| {
4762 return ip.get(gpa, .{ .aggregate = .{
4763 .ty = new_ty,
4764 .storage = .{ .repeated_elem = elem },
4765 } });
4766 },
4767 }
4768 }
4769 // Direct approach failed - we must recursively coerce elems
4770 const agg_elems = try gpa.alloc(InternPool.Index, new_len);
4771 defer gpa.free(agg_elems);
4772 // First, fill the vector with the uncoerced elements. We do this to avoid key
4773 // lifetime issues, since it'll allow us to avoid referencing `aggregate` after we
4774 // begin interning elems.
5633 .opt_type => |child_type| return try ip.get(gpa, .{ .opt = .{
5634 .ty = new_ty,
5635 .val = switch (opt.val) {
5636 .none => .none,
5637 else => try ip.getCoerced(gpa, opt.val, child_type),
5638 },
5639 } }),
5640 else => {},
5641 },
5642 .err => |err| if (ip.isErrorSetType(new_ty))
5643 return ip.get(gpa, .{ .err = .{
5644 .ty = new_ty,
5645 .name = err.name,
5646 } })
5647 else if (ip.isErrorUnionType(new_ty))
5648 return ip.get(gpa, .{ .error_union = .{
5649 .ty = new_ty,
5650 .val = .{ .err_name = err.name },
5651 } }),
5652 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
5653 return ip.get(gpa, .{ .error_union = .{
5654 .ty = new_ty,
5655 .val = error_union.val,
5656 } }),
5657 .aggregate => |aggregate| {
5658 const new_len = @as(usize, @intCast(ip.aggregateTypeLen(new_ty)));
5659 direct: {
5660 const old_ty_child = switch (ip.indexToKey(old_ty)) {
5661 inline .array_type, .vector_type => |seq_type| seq_type.child,
5662 .anon_struct_type, .struct_type => break :direct,
5663 else => unreachable,
5664 };
5665 const new_ty_child = switch (ip.indexToKey(new_ty)) {
5666 inline .array_type, .vector_type => |seq_type| seq_type.child,
5667 .anon_struct_type, .struct_type => break :direct,
5668 else => unreachable,
5669 };
5670 if (old_ty_child != new_ty_child) break :direct;
5671 // TODO: write something like getCoercedInts to avoid needing to dupe here
47755672 switch (aggregate.storage) {
4776 .bytes => {
4777 // We have to intern each value here, so unfortunately we can't easily avoid
4778 // the repeated indexToKey calls.
4779 for (agg_elems, 0..) |*elem, i| {
4780 const x = ip.indexToKey(val).aggregate.storage.bytes[i];
4781 elem.* = try ip.get(gpa, .{ .int = .{
4782 .ty = .u8_type,
4783 .storage = .{ .u64 = x },
4784 } });
4785 }
5673 .bytes => |bytes| {
5674 const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]);
5675 defer gpa.free(bytes_copy);
5676 return ip.get(gpa, .{ .aggregate = .{
5677 .ty = new_ty,
5678 .storage = .{ .bytes = bytes_copy },
5679 } });
5680 },
5681 .elems => |elems| {
5682 const elems_copy = try gpa.dupe(Index, elems[0..new_len]);
5683 defer gpa.free(elems_copy);
5684 return ip.get(gpa, .{ .aggregate = .{
5685 .ty = new_ty,
5686 .storage = .{ .elems = elems_copy },
5687 } });
5688 },
5689 .repeated_elem => |elem| {
5690 return ip.get(gpa, .{ .aggregate = .{
5691 .ty = new_ty,
5692 .storage = .{ .repeated_elem = elem },
5693 } });
47865694 },
4787 .elems => |elems| @memcpy(agg_elems, elems[0..new_len]),
4788 .repeated_elem => |elem| @memset(agg_elems, elem),
4789 }
4790 // Now, coerce each element to its new type.
4791 for (agg_elems, 0..) |*elem, i| {
4792 const new_elem_ty = switch (ip.indexToKey(new_ty)) {
4793 inline .array_type, .vector_type => |seq_type| seq_type.child,
4794 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i],
4795 .struct_type => |struct_type| ip.structPtr(struct_type.index.unwrap().?)
4796 .fields.values()[i].ty.toIntern(),
4797 else => unreachable,
4798 };
4799 elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty);
48005695 }
4801 return ip.get(gpa, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } });
4802 },
4803 else => {},
5696 }
5697 // Direct approach failed - we must recursively coerce elems
5698 const agg_elems = try gpa.alloc(Index, new_len);
5699 defer gpa.free(agg_elems);
5700 // First, fill the vector with the uncoerced elements. We do this to avoid key
5701 // lifetime issues, since it'll allow us to avoid referencing `aggregate` after we
5702 // begin interning elems.
5703 switch (aggregate.storage) {
5704 .bytes => {
5705 // We have to intern each value here, so unfortunately we can't easily avoid
5706 // the repeated indexToKey calls.
5707 for (agg_elems, 0..) |*elem, i| {
5708 const x = ip.indexToKey(val).aggregate.storage.bytes[i];
5709 elem.* = try ip.get(gpa, .{ .int = .{
5710 .ty = .u8_type,
5711 .storage = .{ .u64 = x },
5712 } });
5713 }
5714 },
5715 .elems => |elems| @memcpy(agg_elems, elems[0..new_len]),
5716 .repeated_elem => |elem| @memset(agg_elems, elem),
5717 }
5718 // Now, coerce each element to its new type.
5719 for (agg_elems, 0..) |*elem, i| {
5720 const new_elem_ty = switch (ip.indexToKey(new_ty)) {
5721 inline .array_type, .vector_type => |seq_type| seq_type.child,
5722 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i],
5723 .struct_type => |struct_type| ip.structPtr(struct_type.index.unwrap().?)
5724 .fields.values()[i].ty.toIntern(),
5725 else => unreachable,
5726 };
5727 elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty);
5728 }
5729 return ip.get(gpa, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } });
48045730 },
5731 else => {},
48055732 }
5733
48065734 switch (ip.indexToKey(new_ty)) {
48075735 .opt_type => |child_type| switch (val) {
48085736 .null_value => return ip.get(gpa, .{ .opt = .{
......@@ -4830,6 +5758,54 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
48305758 unreachable;
48315759}
48325760
5761fn getCoercedFuncDecl(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
5762 const datas = ip.items.items(.data);
5763 const extra_index = datas[@intFromEnum(val)];
5764 const prev_ty: Index = @enumFromInt(
5765 ip.extra.items[extra_index + std.meta.fieldIndex(Tag.FuncDecl, "ty").?],
5766 );
5767 if (new_ty == prev_ty) return val;
5768 return getCoercedFunc(ip, gpa, val, new_ty);
5769}
5770
5771fn getCoercedFuncInstance(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
5772 const datas = ip.items.items(.data);
5773 const extra_index = datas[@intFromEnum(val)];
5774 const prev_ty: Index = @enumFromInt(
5775 ip.extra.items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "ty").?],
5776 );
5777 if (new_ty == prev_ty) return val;
5778 return getCoercedFunc(ip, gpa, val, new_ty);
5779}
5780
5781fn getCoercedFunc(ip: *InternPool, gpa: Allocator, func: Index, ty: Index) Allocator.Error!Index {
5782 const prev_extra_len = ip.extra.items.len;
5783 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncCoerced).Struct.fields.len);
5784 try ip.items.ensureUnusedCapacity(gpa, 1);
5785 try ip.map.ensureUnusedCapacity(gpa, 1);
5786
5787 const extra_index = ip.addExtraAssumeCapacity(Tag.FuncCoerced{
5788 .ty = ty,
5789 .func = func,
5790 });
5791
5792 const adapter: KeyAdapter = .{ .intern_pool = ip };
5793 const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{
5794 .func = extraFuncCoerced(ip, extra_index),
5795 }, adapter);
5796
5797 if (gop.found_existing) {
5798 ip.extra.items.len = prev_extra_len;
5799 return @enumFromInt(gop.index);
5800 }
5801
5802 ip.items.appendAssumeCapacity(.{
5803 .tag = .func_coerced,
5804 .data = extra_index,
5805 });
5806 return @enumFromInt(ip.items.len - 1);
5807}
5808
48335809/// Asserts `val` has an integer type.
48345810/// Assumes `new_ty` is an integer type.
48355811pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Index) Allocator.Error!Index {
......@@ -4881,27 +5857,11 @@ pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType {
48815857 const tags = ip.items.items(.tag);
48825858 const datas = ip.items.items(.data);
48835859 switch (tags[@intFromEnum(val)]) {
4884 .type_function => return indexToKeyFuncType(ip, datas[@intFromEnum(val)]),
5860 .type_function => return extraFuncType(ip, datas[@intFromEnum(val)]),
48855861 else => return null,
48865862 }
48875863}
48885864
4889pub fn indexToFunc(ip: *const InternPool, val: Index) Module.Fn.OptionalIndex {
4890 assert(val != .none);
4891 const tags = ip.items.items(.tag);
4892 if (tags[@intFromEnum(val)] != .func) return .none;
4893 const datas = ip.items.items(.data);
4894 return ip.extraData(Tag.Func, datas[@intFromEnum(val)]).index.toOptional();
4895}
4896
4897pub fn indexToInferredErrorSetType(ip: *const InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex {
4898 assert(val != .none);
4899 const tags = ip.items.items(.tag);
4900 if (tags[@intFromEnum(val)] != .type_inferred_error_set) return .none;
4901 const datas = ip.items.items(.data);
4902 return @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(datas[@intFromEnum(val)])).toOptional();
4903}
4904
49055865/// includes .comptime_int_type
49065866pub fn isIntegerType(ip: *const InternPool, ty: Index) bool {
49075867 return switch (ty) {
......@@ -4952,14 +5912,17 @@ pub fn isOptionalType(ip: *const InternPool, ty: Index) bool {
49525912
49535913/// includes .inferred_error_set_type
49545914pub fn isErrorSetType(ip: *const InternPool, ty: Index) bool {
4955 return ty == .anyerror_type or switch (ip.indexToKey(ty)) {
4956 .error_set_type, .inferred_error_set_type => true,
4957 else => false,
5915 return switch (ty) {
5916 .anyerror_type, .adhoc_inferred_error_set_type => true,
5917 else => switch (ip.indexToKey(ty)) {
5918 .error_set_type, .inferred_error_set_type => true,
5919 else => false,
5920 },
49585921 };
49595922}
49605923
49615924pub fn isInferredErrorSetType(ip: *const InternPool, ty: Index) bool {
4962 return ip.indexToKey(ty) == .inferred_error_set_type;
5925 return ty == .adhoc_inferred_error_set_type or ip.indexToKey(ty) == .inferred_error_set_type;
49635926}
49645927
49655928pub fn isErrorUnionType(ip: *const InternPool, ty: Index) bool {
......@@ -4973,6 +5936,14 @@ pub fn isAggregateType(ip: *const InternPool, ty: Index) bool {
49735936 };
49745937}
49755938
5939pub fn errorUnionSet(ip: *const InternPool, ty: Index) Index {
5940 return ip.indexToKey(ty).error_union_type.error_set_type;
5941}
5942
5943pub fn errorUnionPayload(ip: *const InternPool, ty: Index) Index {
5944 return ip.indexToKey(ty).error_union_type.payload_type;
5945}
5946
49765947/// The is only legal because the initializer is not part of the hash.
49775948pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void {
49785949 const item = ip.items.get(@intFromEnum(index));
......@@ -4994,12 +5965,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
49945965 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
49955966 const unions_size = ip.allocated_unions.len *
49965967 (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
4997 const funcs_size = ip.allocated_funcs.len *
4998 (@sizeOf(Module.Fn) + @sizeOf(Module.Decl));
49995968
50005969 // TODO: map overhead size is not taken into account
50015970 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +
5002 structs_size + unions_size + funcs_size;
5971 structs_size + unions_size;
50035972
50045973 std.debug.print(
50055974 \\InternPool size: {d} bytes
......@@ -5008,7 +5977,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
50085977 \\ {d} limbs: {d} bytes
50095978 \\ {d} structs: {d} bytes
50105979 \\ {d} unions: {d} bytes
5011 \\ {d} funcs: {d} bytes
50125980 \\
50135981 , .{
50145982 total_size,
......@@ -5022,8 +5990,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
50225990 structs_size,
50235991 ip.allocated_unions.len,
50245992 unions_size,
5025 ip.allocated_funcs.len,
5026 funcs_size,
50275993 });
50285994
50295995 const tags = ip.items.items(.tag);
......@@ -5048,11 +6014,12 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
50486014 .type_optional => 0,
50496015 .type_anyframe => 0,
50506016 .type_error_union => @sizeOf(Key.ErrorUnionType),
6017 .type_anyerror_union => 0,
50516018 .type_error_set => b: {
5052 const info = ip.extraData(ErrorSet, data);
5053 break :b @sizeOf(ErrorSet) + (@sizeOf(u32) * info.names_len);
6019 const info = ip.extraData(Tag.ErrorSet, data);
6020 break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len);
50546021 },
5055 .type_inferred_error_set => @sizeOf(Module.Fn.InferredErrorSet),
6022 .type_inferred_error_set => 0,
50566023 .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),
50576024 .type_enum_auto => @sizeOf(EnumAuto),
50586025 .type_opaque => @sizeOf(Key.OpaqueType),
......@@ -5080,8 +6047,11 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
50806047 => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),
50816048
50826049 .type_function => b: {
5083 const info = ip.extraData(TypeFunction, data);
5084 break :b @sizeOf(TypeFunction) + (@sizeOf(Index) * info.params_len);
6050 const info = ip.extraData(Tag.TypeFunction, data);
6051 break :b @sizeOf(Tag.TypeFunction) +
6052 (@sizeOf(Index) * info.params_len) +
6053 (@as(u32, 4) * @intFromBool(info.flags.has_comptime_bits)) +
6054 (@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits));
50856055 },
50866056
50876057 .undef => 0,
......@@ -5130,7 +6100,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
51306100 },
51316101 .aggregate => b: {
51326102 const info = ip.extraData(Tag.Aggregate, data);
5133 const fields_len = @as(u32, @intCast(ip.aggregateTypeLenIncludingSentinel(info.ty)));
6103 const fields_len: u32 = @intCast(ip.aggregateTypeLenIncludingSentinel(info.ty));
51346104 break :b @sizeOf(Tag.Aggregate) + (@sizeOf(Index) * fields_len);
51356105 },
51366106 .repeated => @sizeOf(Repeated),
......@@ -5145,7 +6115,15 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
51456115 .float_comptime_float => @sizeOf(Float128),
51466116 .variable => @sizeOf(Tag.Variable) + @sizeOf(Module.Decl),
51476117 .extern_func => @sizeOf(Tag.ExternFunc) + @sizeOf(Module.Decl),
5148 .func => @sizeOf(Tag.Func) + @sizeOf(Module.Fn) + @sizeOf(Module.Decl),
6118 .func_decl => @sizeOf(Tag.FuncDecl) + @sizeOf(Module.Decl),
6119 .func_instance => b: {
6120 const info = ip.extraData(Tag.FuncInstance, data);
6121 const ty = ip.typeOf(info.generic_owner);
6122 const params_len = ip.indexToKey(ty).func_type.param_types.len;
6123 break :b @sizeOf(Tag.FuncInstance) + @sizeOf(Index) * params_len +
6124 @sizeOf(Module.Decl);
6125 },
6126 .func_coerced => @sizeOf(Tag.FuncCoerced),
51496127 .only_possible_value => 0,
51506128 .union_value => @sizeOf(Key.Union),
51516129
......@@ -5193,6 +6171,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
51936171 .type_optional,
51946172 .type_anyframe,
51956173 .type_error_union,
6174 .type_anyerror_union,
51966175 .type_error_set,
51976176 .type_inferred_error_set,
51986177 .type_enum_explicit,
......@@ -5249,7 +6228,9 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
52496228 .float_comptime_float,
52506229 .variable,
52516230 .extern_func,
5252 .func,
6231 .func_decl,
6232 .func_instance,
6233 .func_coerced,
52536234 .union_value,
52546235 .memoized_call,
52556236 => try w.print("{d}", .{data}),
......@@ -5284,20 +6265,12 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo
52846265 return ip.allocated_unions.at(@intFromEnum(index));
52856266}
52866267
5287pub fn funcPtr(ip: *InternPool, index: Module.Fn.Index) *Module.Fn {
5288 return ip.allocated_funcs.at(@intFromEnum(index));
5289}
5290
5291pub fn funcPtrConst(ip: *const InternPool, index: Module.Fn.Index) *const Module.Fn {
5292 return ip.allocated_funcs.at(@intFromEnum(index));
6268pub fn declPtr(ip: *InternPool, index: Module.Decl.Index) *Module.Decl {
6269 return ip.allocated_decls.at(@intFromEnum(index));
52936270}
52946271
5295pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet {
5296 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));
5297}
5298
5299pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.Fn.InferredErrorSet.Index) *const Module.Fn.InferredErrorSet {
5300 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));
6272pub fn namespacePtr(ip: *InternPool, index: Module.Namespace.Index) *Module.Namespace {
6273 return ip.allocated_namespaces.at(@intFromEnum(index));
53016274}
53026275
53036276pub fn createStruct(
......@@ -5344,47 +6317,47 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)
53446317 };
53456318}
53466319
5347pub fn createFunc(
6320pub fn createDecl(
53486321 ip: *InternPool,
53496322 gpa: Allocator,
5350 initialization: Module.Fn,
5351) Allocator.Error!Module.Fn.Index {
5352 if (ip.funcs_free_list.popOrNull()) |index| {
5353 ip.allocated_funcs.at(@intFromEnum(index)).* = initialization;
6323 initialization: Module.Decl,
6324) Allocator.Error!Module.Decl.Index {
6325 if (ip.decls_free_list.popOrNull()) |index| {
6326 ip.allocated_decls.at(@intFromEnum(index)).* = initialization;
53546327 return index;
53556328 }
5356 const ptr = try ip.allocated_funcs.addOne(gpa);
6329 const ptr = try ip.allocated_decls.addOne(gpa);
53576330 ptr.* = initialization;
5358 return @as(Module.Fn.Index, @enumFromInt(ip.allocated_funcs.len - 1));
6331 return @as(Module.Decl.Index, @enumFromInt(ip.allocated_decls.len - 1));
53596332}
53606333
5361pub fn destroyFunc(ip: *InternPool, gpa: Allocator, index: Module.Fn.Index) void {
5362 ip.funcPtr(index).* = undefined;
5363 ip.funcs_free_list.append(gpa, index) catch {
5364 // In order to keep `destroyFunc` a non-fallible function, we ignore memory
5365 // allocation failures here, instead leaking the Fn until garbage collection.
6334pub fn destroyDecl(ip: *InternPool, gpa: Allocator, index: Module.Decl.Index) void {
6335 ip.declPtr(index).* = undefined;
6336 ip.decls_free_list.append(gpa, index) catch {
6337 // In order to keep `destroyDecl` a non-fallible function, we ignore memory
6338 // allocation failures here, instead leaking the Decl until garbage collection.
53666339 };
53676340}
53686341
5369pub fn createInferredErrorSet(
6342pub fn createNamespace(
53706343 ip: *InternPool,
53716344 gpa: Allocator,
5372 initialization: Module.Fn.InferredErrorSet,
5373) Allocator.Error!Module.Fn.InferredErrorSet.Index {
5374 if (ip.inferred_error_sets_free_list.popOrNull()) |index| {
5375 ip.allocated_inferred_error_sets.at(@intFromEnum(index)).* = initialization;
6345 initialization: Module.Namespace,
6346) Allocator.Error!Module.Namespace.Index {
6347 if (ip.namespaces_free_list.popOrNull()) |index| {
6348 ip.allocated_namespaces.at(@intFromEnum(index)).* = initialization;
53766349 return index;
53776350 }
5378 const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);
6351 const ptr = try ip.allocated_namespaces.addOne(gpa);
53796352 ptr.* = initialization;
5380 return @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(ip.allocated_inferred_error_sets.len - 1));
6353 return @as(Module.Namespace.Index, @enumFromInt(ip.allocated_namespaces.len - 1));
53816354}
53826355
5383pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.Fn.InferredErrorSet.Index) void {
5384 ip.inferredErrorSetPtr(index).* = undefined;
5385 ip.inferred_error_sets_free_list.append(gpa, index) catch {
5386 // In order to keep `destroyInferredErrorSet` a non-fallible function, we ignore memory
5387 // allocation failures here, instead leaking the InferredErrorSet until garbage collection.
6356pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: Module.Namespace.Index) void {
6357 ip.namespacePtr(index).* = undefined;
6358 ip.namespaces_free_list.append(gpa, index) catch {
6359 // In order to keep `destroyNamespace` a non-fallible function, we ignore memory
6360 // allocation failures here, instead leaking the Namespace until garbage collection.
53886361 };
53896362}
53906363
......@@ -5547,6 +6520,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
55476520 .slice_const_u8_sentinel_0_type,
55486521 .optional_noreturn_type,
55496522 .anyerror_void_error_union_type,
6523 .adhoc_inferred_error_set_type,
55506524 .generic_poison_type,
55516525 .empty_struct_type,
55526526 => .type_type,
......@@ -5576,6 +6550,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
55766550 .type_optional,
55776551 .type_anyframe,
55786552 .type_error_union,
6553 .type_anyerror_union,
55796554 .type_error_set,
55806555 .type_inferred_error_set,
55816556 .type_enum_auto,
......@@ -5596,7 +6571,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
55966571 .undef,
55976572 .opt_null,
55986573 .only_possible_value,
5599 => @as(Index, @enumFromInt(ip.items.items(.data)[@intFromEnum(index)])),
6574 => @enumFromInt(ip.items.items(.data)[@intFromEnum(index)]),
56006575
56016576 .simple_value => unreachable, // handled via Index above
56026577
......@@ -5620,7 +6595,9 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
56206595 .enum_tag,
56216596 .variable,
56226597 .extern_func,
5623 .func,
6598 .func_decl,
6599 .func_instance,
6600 .func_coerced,
56246601 .union_value,
56256602 .bytes,
56266603 .aggregate,
......@@ -5628,7 +6605,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
56286605 => |t| {
56296606 const extra_index = ip.items.items(.data)[@intFromEnum(index)];
56306607 const field_index = std.meta.fieldIndex(t.Payload(), "ty").?;
5631 return @as(Index, @enumFromInt(ip.extra.items[extra_index + field_index]));
6608 return @enumFromInt(ip.extra.items[extra_index + field_index]);
56326609 },
56336610
56346611 .int_u8 => .u8_type,
......@@ -5693,7 +6670,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {
56936670 };
56946671}
56956672
5696pub fn funcReturnType(ip: *const InternPool, ty: Index) Index {
6673pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {
56976674 const item = ip.items.get(@intFromEnum(ty));
56986675 const child_item = switch (item.tag) {
56996676 .type_pointer => ip.items.get(ip.extra.items[
......@@ -5704,7 +6681,7 @@ pub fn funcReturnType(ip: *const InternPool, ty: Index) Index {
57046681 };
57056682 assert(child_item.tag == .type_function);
57066683 return @as(Index, @enumFromInt(ip.extra.items[
5707 child_item.data + std.meta.fieldIndex(TypeFunction, "return_type").?
6684 child_item.data + std.meta.fieldIndex(Tag.TypeFunction, "return_type").?
57086685 ]));
57096686}
57106687
......@@ -5712,7 +6689,7 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
57126689 return switch (ty) {
57136690 .noreturn_type => true,
57146691 else => switch (ip.items.items(.tag)[@intFromEnum(ty)]) {
5715 .type_error_set => ip.extra.items[ip.items.items(.data)[@intFromEnum(ty)] + std.meta.fieldIndex(ErrorSet, "names_len").?] == 0,
6692 .type_error_set => ip.extra.items[ip.items.items(.data)[@intFromEnum(ty)] + std.meta.fieldIndex(Tag.ErrorSet, "names_len").?] == 0,
57166693 else => false,
57176694 },
57186695 };
......@@ -5821,7 +6798,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
58216798 .bool_type => .Bool,
58226799 .void_type => .Void,
58236800 .type_type => .Type,
5824 .anyerror_type => .ErrorSet,
6801 .anyerror_type, .adhoc_inferred_error_set_type => .ErrorSet,
58256802 .comptime_int_type => .ComptimeInt,
58266803 .comptime_float_type => .ComptimeFloat,
58276804 .noreturn_type => .NoReturn,
......@@ -5899,7 +6876,10 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
58996876
59006877 .type_optional => .Optional,
59016878 .type_anyframe => .AnyFrame,
5902 .type_error_union => .ErrorUnion,
6879
6880 .type_error_union,
6881 .type_anyerror_union,
6882 => .ErrorUnion,
59036883
59046884 .type_error_set,
59056885 .type_inferred_error_set,
......@@ -5969,7 +6949,9 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
59696949 .float_comptime_float,
59706950 .variable,
59716951 .extern_func,
5972 .func,
6952 .func_decl,
6953 .func_instance,
6954 .func_coerced,
59736955 .only_possible_value,
59746956 .union_value,
59756957 .bytes,
......@@ -5982,3 +6964,126 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
59826964 .none => unreachable, // special tag
59836965 };
59846966}
6967
6968pub fn isFuncBody(ip: *const InternPool, i: Index) bool {
6969 assert(i != .none);
6970 return switch (ip.items.items(.tag)[@intFromEnum(i)]) {
6971 .func_decl, .func_instance, .func_coerced => true,
6972 else => false,
6973 };
6974}
6975
6976pub fn funcAnalysis(ip: *const InternPool, i: Index) *FuncAnalysis {
6977 assert(i != .none);
6978 const item = ip.items.get(@intFromEnum(i));
6979 const extra_index = switch (item.tag) {
6980 .func_decl => item.data + std.meta.fieldIndex(Tag.FuncDecl, "analysis").?,
6981 .func_instance => item.data + std.meta.fieldIndex(Tag.FuncInstance, "analysis").?,
6982 .func_coerced => i: {
6983 const extra_index = item.data + std.meta.fieldIndex(Tag.FuncCoerced, "func").?;
6984 const func_index: Index = @enumFromInt(ip.extra.items[extra_index]);
6985 const sub_item = ip.items.get(@intFromEnum(func_index));
6986 break :i switch (sub_item.tag) {
6987 .func_decl => sub_item.data + std.meta.fieldIndex(Tag.FuncDecl, "analysis").?,
6988 .func_instance => sub_item.data + std.meta.fieldIndex(Tag.FuncInstance, "analysis").?,
6989 else => unreachable,
6990 };
6991 },
6992 else => unreachable,
6993 };
6994 return @ptrCast(&ip.extra.items[extra_index]);
6995}
6996
6997pub fn funcHasInferredErrorSet(ip: *const InternPool, i: Index) bool {
6998 return funcAnalysis(ip, i).inferred_error_set;
6999}
7000
7001pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index {
7002 assert(i != .none);
7003 const item = ip.items.get(@intFromEnum(i));
7004 const zir_body_inst_field_index = std.meta.fieldIndex(Tag.FuncDecl, "zir_body_inst").?;
7005 const extra_index = switch (item.tag) {
7006 .func_decl => item.data + zir_body_inst_field_index,
7007 .func_instance => b: {
7008 const generic_owner_field_index = std.meta.fieldIndex(Tag.FuncInstance, "generic_owner").?;
7009 const func_decl_index = ip.extra.items[item.data + generic_owner_field_index];
7010 assert(ip.items.items(.tag)[func_decl_index] == .func_decl);
7011 break :b ip.items.items(.data)[func_decl_index] + zir_body_inst_field_index;
7012 },
7013 else => unreachable,
7014 };
7015 return ip.extra.items[extra_index];
7016}
7017
7018pub fn iesFuncIndex(ip: *const InternPool, ies_index: Index) Index {
7019 assert(ies_index != .none);
7020 const tags = ip.items.items(.tag);
7021 assert(tags[@intFromEnum(ies_index)] == .type_inferred_error_set);
7022 const func_index = ip.items.items(.data)[@intFromEnum(ies_index)];
7023 switch (tags[func_index]) {
7024 .func_decl, .func_instance => {},
7025 else => unreachable, // assertion failed
7026 }
7027 return @enumFromInt(func_index);
7028}
7029
7030/// Returns a mutable pointer to the resolved error set type of an inferred
7031/// error set function. The returned pointer is invalidated when anything is
7032/// added to `ip`.
7033pub fn iesResolved(ip: *const InternPool, ies_index: Index) *Index {
7034 assert(ies_index != .none);
7035 const tags = ip.items.items(.tag);
7036 const datas = ip.items.items(.data);
7037 assert(tags[@intFromEnum(ies_index)] == .type_inferred_error_set);
7038 const func_index = datas[@intFromEnum(ies_index)];
7039 return funcIesResolved(ip, func_index);
7040}
7041
7042/// Returns a mutable pointer to the resolved error set type of an inferred
7043/// error set function. The returned pointer is invalidated when anything is
7044/// added to `ip`.
7045pub fn funcIesResolved(ip: *const InternPool, func_index: Index) *Index {
7046 const tags = ip.items.items(.tag);
7047 const datas = ip.items.items(.data);
7048 assert(funcHasInferredErrorSet(ip, func_index));
7049 const func_start = datas[@intFromEnum(func_index)];
7050 const extra_index = switch (tags[@intFromEnum(func_index)]) {
7051 .func_decl => func_start + @typeInfo(Tag.FuncDecl).Struct.fields.len,
7052 .func_instance => func_start + @typeInfo(Tag.FuncInstance).Struct.fields.len,
7053 else => unreachable,
7054 };
7055 return @ptrCast(&ip.extra.items[extra_index]);
7056}
7057
7058pub fn funcDeclInfo(ip: *const InternPool, i: Index) Key.Func {
7059 const tags = ip.items.items(.tag);
7060 const datas = ip.items.items(.data);
7061 assert(tags[@intFromEnum(i)] == .func_decl);
7062 return extraFuncDecl(ip, datas[@intFromEnum(i)]);
7063}
7064
7065pub fn funcDeclOwner(ip: *const InternPool, i: Index) Module.Decl.Index {
7066 return funcDeclInfo(ip, i).owner_decl;
7067}
7068
7069pub fn funcTypeParamsLen(ip: *const InternPool, i: Index) u32 {
7070 const tags = ip.items.items(.tag);
7071 const datas = ip.items.items(.data);
7072 assert(tags[@intFromEnum(i)] == .type_function);
7073 const start = datas[@intFromEnum(i)];
7074 return ip.extra.items[start + std.meta.fieldIndex(Tag.TypeFunction, "params_len").?];
7075}
7076
7077fn unwrapCoercedFunc(ip: *const InternPool, i: Index) Index {
7078 const tags = ip.items.items(.tag);
7079 return switch (tags[@intFromEnum(i)]) {
7080 .func_coerced => {
7081 const datas = ip.items.items(.data);
7082 return @enumFromInt(ip.extra.items[
7083 datas[@intFromEnum(i)] + std.meta.fieldIndex(Tag.FuncCoerced, "func").?
7084 ]);
7085 },
7086 .func_instance, .func_decl => i,
7087 else => unreachable,
7088 };
7089}
src/Module.zig+306-579
......@@ -87,7 +87,9 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{},
8787/// Keys are fully resolved file paths. This table owns the keys and values.
8888embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},
8989
90/// Stores all Type and Value objects; periodically garbage collected.
90/// Stores all Type and Value objects.
91/// The idea is that this will be periodically garbage-collected, but such logic
92/// is not yet implemented.
9193intern_pool: InternPool = .{},
9294
9395/// To be eliminated in a future commit by moving more data into InternPool.
......@@ -101,16 +103,6 @@ tmp_hack_arena: std.heap.ArenaAllocator,
101103/// This is currently only used for string literals.
102104memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},
103105
104monomorphed_func_keys: std.ArrayListUnmanaged(InternPool.Index) = .{},
105/// The set of all the generic function instantiations. This is used so that when a generic
106/// function is called twice with the same comptime parameter arguments, both calls dispatch
107/// to the same function.
108monomorphed_funcs: MonomorphedFuncsSet = .{},
109/// Contains the values from `@setAlignStack`. A sparse table is used here
110/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
111/// functions are many.
112align_stack_fns: std.AutoHashMapUnmanaged(Fn.Index, SetAlignStack) = .{},
113
114106/// We optimize memory usage for a compilation with no compile errors by storing the
115107/// error messages and mapping outside of `Decl`.
116108/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
......@@ -162,25 +154,6 @@ emit_h: ?*GlobalEmitH,
162154
163155test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
164156
165/// Rather than allocating Decl objects with an Allocator, we instead allocate
166/// them with this SegmentedList. This provides four advantages:
167/// * Stable memory so that one thread can access a Decl object while another
168/// thread allocates additional Decl objects from this list.
169/// * It allows us to use u32 indexes to reference Decl objects rather than
170/// pointers, saving memory in Type, Value, and dependency sets.
171/// * Using integers to reference Decl objects rather than pointers makes
172/// serialization trivial.
173/// * It provides a unique integer to be used for anonymous symbol names, avoiding
174/// multi-threaded contention on an atomic counter.
175allocated_decls: std.SegmentedList(Decl, 0) = .{},
176/// When a Decl object is freed from `allocated_decls`, it is pushed into this stack.
177decls_free_list: ArrayListUnmanaged(Decl.Index) = .{},
178
179/// Same pattern as with `allocated_decls`.
180allocated_namespaces: std.SegmentedList(Namespace, 0) = .{},
181/// Same pattern as with `decls_free_list`.
182namespaces_free_list: ArrayListUnmanaged(Namespace.Index) = .{},
183
184157global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},
185158
186159reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
......@@ -189,7 +162,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
189162}) = .{},
190163
191164panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len,
192panic_func_index: Fn.OptionalIndex = .none,
165/// The panic function body.
166panic_func_index: InternPool.Index = .none,
193167null_stack_trace: InternPool.Index = .none,
194168
195169pub const PanicId = enum {
......@@ -239,50 +213,6 @@ pub const CImportError = struct {
239213 }
240214};
241215
242pub const MonomorphedFuncKey = struct { func: Fn.Index, args_index: u32, args_len: u32 };
243
244pub const MonomorphedFuncAdaptedKey = struct { func: Fn.Index, args: []const InternPool.Index };
245
246pub const MonomorphedFuncsSet = std.HashMapUnmanaged(
247 MonomorphedFuncKey,
248 InternPool.Index,
249 MonomorphedFuncsContext,
250 std.hash_map.default_max_load_percentage,
251);
252
253pub const MonomorphedFuncsContext = struct {
254 mod: *Module,
255
256 pub fn eql(_: @This(), a: MonomorphedFuncKey, b: MonomorphedFuncKey) bool {
257 return std.meta.eql(a, b);
258 }
259
260 pub fn hash(ctx: @This(), key: MonomorphedFuncKey) u64 {
261 const key_args = ctx.mod.monomorphed_func_keys.items[key.args_index..][0..key.args_len];
262 return std.hash.Wyhash.hash(@intFromEnum(key.func), std.mem.sliceAsBytes(key_args));
263 }
264};
265
266pub const MonomorphedFuncsAdaptedContext = struct {
267 mod: *Module,
268
269 pub fn eql(ctx: @This(), adapted_key: MonomorphedFuncAdaptedKey, other_key: MonomorphedFuncKey) bool {
270 const other_key_args = ctx.mod.monomorphed_func_keys.items[other_key.args_index..][0..other_key.args_len];
271 return adapted_key.func == other_key.func and std.mem.eql(InternPool.Index, adapted_key.args, other_key_args);
272 }
273
274 pub fn hash(_: @This(), adapted_key: MonomorphedFuncAdaptedKey) u64 {
275 return std.hash.Wyhash.hash(@intFromEnum(adapted_key.func), std.mem.sliceAsBytes(adapted_key.args));
276 }
277};
278
279pub const SetAlignStack = struct {
280 alignment: Alignment,
281 /// TODO: This needs to store a non-lazy source location for the case of an inline function
282 /// which does `@setAlignStack` (applying it to the caller).
283 src: LazySrcLoc,
284};
285
286216/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
287217pub const GlobalEmitH = struct {
288218 /// Where to put the output.
......@@ -366,6 +296,9 @@ pub const CaptureScope = struct {
366296 }
367297
368298 pub fn incRef(self: *CaptureScope) void {
299 // TODO: wtf is reference counting doing in my beautiful codebase? 😠
300 // seriously though, let's change this to rely on InternPool garbage
301 // collection instead.
369302 self.refs += 1;
370303 }
371304
......@@ -625,13 +558,6 @@ pub const Decl = struct {
625558 function_body,
626559 };
627560
628 pub fn clearValues(decl: *Decl, mod: *Module) void {
629 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
630 _ = mod.align_stack_fns.remove(func);
631 mod.destroyFunc(func);
632 }
633 }
634
635561 /// This name is relative to the containing namespace of the decl.
636562 /// The memory is owned by the containing File ZIR.
637563 pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {
......@@ -816,14 +742,18 @@ pub const Decl = struct {
816742 return mod.typeToUnion(decl.val.toType());
817743 }
818744
819 /// If the Decl owns its value and it is a function, return it,
820 /// otherwise null.
821 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?*Fn {
822 return mod.funcPtrUnwrap(decl.getOwnedFunctionIndex(mod));
745 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?InternPool.Key.Func {
746 const i = decl.getOwnedFunctionIndex();
747 if (i == .none) return null;
748 return switch (mod.intern_pool.indexToKey(i)) {
749 .func => |func| func,
750 else => null,
751 };
823752 }
824753
825 pub fn getOwnedFunctionIndex(decl: Decl, mod: *Module) Fn.OptionalIndex {
826 return if (decl.owns_tv) decl.val.getFunctionIndex(mod) else .none;
754 /// This returns an InternPool.Index even when the value is not a function.
755 pub fn getOwnedFunctionIndex(decl: Decl) InternPool.Index {
756 return if (decl.owns_tv) decl.val.toIntern() else .none;
827757 }
828758
829759 /// If the Decl owns its value and it is an extern function, returns it,
......@@ -1368,252 +1298,6 @@ pub const Union = struct {
13681298 }
13691299};
13701300
1371/// Some extern function struct memory is owned by the Decl's TypedValue.Managed
1372/// arena allocator.
1373pub const ExternFn = struct {
1374 /// The Decl that corresponds to the function itself.
1375 owner_decl: Decl.Index,
1376 /// Library name if specified.
1377 /// For example `extern "c" fn write(...) usize` would have 'c' as library name.
1378 /// Allocated with Module's allocator; outlives the ZIR code.
1379 lib_name: ?[*:0]const u8,
1380
1381 pub fn deinit(extern_fn: *ExternFn, gpa: Allocator) void {
1382 if (extern_fn.lib_name) |lib_name| {
1383 gpa.free(mem.sliceTo(lib_name, 0));
1384 }
1385 }
1386};
1387
1388/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
1389/// Extern functions do not have this data structure; they are represented by `ExternFn`
1390/// instead.
1391pub const Fn = struct {
1392 /// The Decl that corresponds to the function itself.
1393 owner_decl: Decl.Index,
1394 /// The ZIR instruction that is a function instruction. Use this to find
1395 /// the body. We store this rather than the body directly so that when ZIR
1396 /// is regenerated on update(), we can map this to the new corresponding
1397 /// ZIR instruction.
1398 zir_body_inst: Zir.Inst.Index,
1399 /// If this is not null, this function is a generic function instantiation, and
1400 /// there is a `TypedValue` here for each parameter of the function.
1401 /// Non-comptime parameters are marked with a `generic_poison` for the value.
1402 /// Non-anytype parameters are marked with a `generic_poison` for the type.
1403 /// These never have .generic_poison for the Type
1404 /// because the Type is needed to pass to `Type.eql` and for inserting comptime arguments
1405 /// into the inst_map when analyzing the body of a generic function instantiation.
1406 /// Instead, the is_anytype knowledge is communicated via `isAnytypeParam`.
1407 comptime_args: ?[*]TypedValue,
1408
1409 /// Precomputed hash for monomorphed_funcs.
1410 /// This is important because it may be accessed when resizing monomorphed_funcs
1411 /// while this Fn has already been added to the set, but does not have the
1412 /// owner_decl, comptime_args, or other fields populated yet.
1413 /// This field is undefined if comptime_args == null.
1414 hash: u64,
1415
1416 /// Relative to owner Decl.
1417 lbrace_line: u32,
1418 /// Relative to owner Decl.
1419 rbrace_line: u32,
1420 lbrace_column: u16,
1421 rbrace_column: u16,
1422
1423 /// When a generic function is instantiated, this value is inherited from the
1424 /// active Sema context. Importantly, this value is also updated when an existing
1425 /// generic function instantiation is found and called.
1426 branch_quota: u32,
1427
1428 /// If this is not none, this function is a generic function instantiation, and
1429 /// this is the generic function decl from which the instance was derived.
1430 /// This information is redundant with a combination of checking if comptime_args is
1431 /// not null and looking at the first decl dependency of owner_decl. This redundant
1432 /// information is useful for three reasons:
1433 /// 1. Improved perf of monomorphed_funcs when checking the eql() function because it
1434 /// can do two fewer pointer chases by grabbing the info from this field directly
1435 /// instead of accessing the decl and then the dependencies set.
1436 /// 2. While a generic function instantiation is being initialized, we need hash()
1437 /// and eql() to work before the initialization is complete. Completing the
1438 /// insertion into the decl dependency set has more fallible operations than simply
1439 /// setting this field.
1440 /// 3. I forgot what the third thing was while typing up the other two.
1441 generic_owner_decl: Decl.OptionalIndex,
1442
1443 state: Analysis,
1444 is_cold: bool = false,
1445 is_noinline: bool,
1446 calls_or_awaits_errorable_fn: bool = false,
1447
1448 pub const Index = enum(u32) {
1449 _,
1450
1451 pub fn toOptional(i: Index) OptionalIndex {
1452 return @as(OptionalIndex, @enumFromInt(@intFromEnum(i)));
1453 }
1454 };
1455
1456 pub const OptionalIndex = enum(u32) {
1457 none = std.math.maxInt(u32),
1458 _,
1459
1460 pub fn init(oi: ?Index) OptionalIndex {
1461 return @as(OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none)));
1462 }
1463
1464 pub fn unwrap(oi: OptionalIndex) ?Index {
1465 if (oi == .none) return null;
1466 return @as(Index, @enumFromInt(@intFromEnum(oi)));
1467 }
1468 };
1469
1470 pub const Analysis = enum {
1471 /// This function has not yet undergone analysis, because we have not
1472 /// seen a potential runtime call. It may be analyzed in future.
1473 none,
1474 /// Analysis for this function has been queued, but not yet completed.
1475 queued,
1476 /// This function intentionally only has ZIR generated because it is marked
1477 /// inline, which means no runtime version of the function will be generated.
1478 inline_only,
1479 in_progress,
1480 /// There will be a corresponding ErrorMsg in Module.failed_decls
1481 sema_failure,
1482 /// This Fn might be OK but it depends on another Decl which did not
1483 /// successfully complete semantic analysis.
1484 dependency_failure,
1485 success,
1486 };
1487
1488 /// This struct is used to keep track of any dependencies related to functions instances
1489 /// that return inferred error sets. Note that a function may be associated to
1490 /// multiple different error sets, for example an inferred error set which
1491 /// this function returns, but also any inferred error sets of called inline
1492 /// or comptime functions.
1493 pub const InferredErrorSet = struct {
1494 /// The function from which this error set originates.
1495 func: Fn.Index,
1496
1497 /// All currently known errors that this error set contains. This includes
1498 /// direct additions via `return error.Foo;`, and possibly also errors that
1499 /// are returned from any dependent functions. When the inferred error set is
1500 /// fully resolved, this map contains all the errors that the function might return.
1501 errors: NameMap = .{},
1502
1503 /// Other inferred error sets which this inferred error set should include.
1504 inferred_error_sets: std.AutoArrayHashMapUnmanaged(InferredErrorSet.Index, void) = .{},
1505
1506 /// Whether the function returned anyerror. This is true if either of
1507 /// the dependent functions returns anyerror.
1508 is_anyerror: bool = false,
1509
1510 /// Whether this error set is already fully resolved. If true, resolving
1511 /// can skip resolving any dependents of this inferred error set.
1512 is_resolved: bool = false,
1513
1514 pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
1515
1516 pub const Index = enum(u32) {
1517 _,
1518
1519 pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1520 return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(i)));
1521 }
1522 };
1523
1524 pub const OptionalIndex = enum(u32) {
1525 none = std.math.maxInt(u32),
1526 _,
1527
1528 pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1529 return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none)));
1530 }
1531
1532 pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index {
1533 if (oi == .none) return null;
1534 return @as(InferredErrorSet.Index, @enumFromInt(@intFromEnum(oi)));
1535 }
1536 };
1537
1538 pub fn addErrorSet(
1539 self: *InferredErrorSet,
1540 err_set_ty: Type,
1541 ip: *InternPool,
1542 gpa: Allocator,
1543 ) !void {
1544 switch (err_set_ty.toIntern()) {
1545 .anyerror_type => {
1546 self.is_anyerror = true;
1547 },
1548 else => switch (ip.indexToKey(err_set_ty.toIntern())) {
1549 .error_set_type => |error_set_type| {
1550 for (error_set_type.names) |name| {
1551 try self.errors.put(gpa, name, {});
1552 }
1553 },
1554 .inferred_error_set_type => |ies_index| {
1555 try self.inferred_error_sets.put(gpa, ies_index, {});
1556 },
1557 else => unreachable,
1558 },
1559 }
1560 }
1561 };
1562
1563 pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {
1564 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
1565
1566 const tags = file.zir.instructions.items(.tag);
1567
1568 const param_body = file.zir.getParamBody(func.zir_body_inst);
1569 const param = param_body[index];
1570
1571 return switch (tags[param]) {
1572 .param, .param_comptime => false,
1573 .param_anytype, .param_anytype_comptime => true,
1574 else => unreachable,
1575 };
1576 }
1577
1578 pub fn getParamName(func: Fn, mod: *Module, index: u32) [:0]const u8 {
1579 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
1580
1581 const tags = file.zir.instructions.items(.tag);
1582 const data = file.zir.instructions.items(.data);
1583
1584 const param_body = file.zir.getParamBody(func.zir_body_inst);
1585 const param = param_body[index];
1586
1587 return switch (tags[param]) {
1588 .param, .param_comptime => blk: {
1589 const extra = file.zir.extraData(Zir.Inst.Param, data[param].pl_tok.payload_index);
1590 break :blk file.zir.nullTerminatedString(extra.data.name);
1591 },
1592 .param_anytype, .param_anytype_comptime => blk: {
1593 const param_data = data[param].str_tok;
1594 break :blk param_data.get(file.zir);
1595 },
1596 else => unreachable,
1597 };
1598 }
1599
1600 pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool {
1601 const owner_decl = mod.declPtr(func.owner_decl);
1602 const zir = owner_decl.getFileScope(mod).zir;
1603 const zir_tags = zir.instructions.items(.tag);
1604 switch (zir_tags[func.zir_body_inst]) {
1605 .func => return false,
1606 .func_inferred => return true,
1607 .func_fancy => {
1608 const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node;
1609 const extra = zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
1610 return extra.data.bits.is_inferred_error;
1611 },
1612 else => unreachable,
1613 }
1614 }
1615};
1616
16171301pub const DeclAdapter = struct {
16181302 mod: *Module,
16191303
......@@ -1638,12 +1322,10 @@ pub const Namespace = struct {
16381322 /// Direct children of the namespace. Used during an update to detect
16391323 /// which decls have been added/removed from source.
16401324 /// Declaration order is preserved via entry order.
1641 /// Key memory is owned by `decl.name`.
1642 /// Anonymous decls are not stored here; they are kept in `anon_decls` instead.
1325 /// These are only declarations named directly by the AST; anonymous
1326 /// declarations are not stored here.
16431327 decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{},
16441328
1645 anon_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
1646
16471329 /// Key is usingnamespace Decl itself. To find the namespace being included,
16481330 /// the Decl Value has to be resolved as a Type which has a Namespace.
16491331 /// Value is whether the usingnamespace decl is marked `pub`.
......@@ -1698,18 +1380,11 @@ pub const Namespace = struct {
16981380 var decls = ns.decls;
16991381 ns.decls = .{};
17001382
1701 var anon_decls = ns.anon_decls;
1702 ns.anon_decls = .{};
1703
17041383 for (decls.keys()) |decl_index| {
17051384 mod.destroyDecl(decl_index);
17061385 }
17071386 decls.deinit(gpa);
17081387
1709 for (anon_decls.keys()) |key| {
1710 mod.destroyDecl(key);
1711 }
1712 anon_decls.deinit(gpa);
17131388 ns.usingnamespace_set.deinit(gpa);
17141389 }
17151390
......@@ -1723,9 +1398,6 @@ pub const Namespace = struct {
17231398 var decls = ns.decls;
17241399 ns.decls = .{};
17251400
1726 var anon_decls = ns.anon_decls;
1727 ns.anon_decls = .{};
1728
17291401 // TODO rework this code to not panic on OOM.
17301402 // (might want to coordinate with the clearDecl function)
17311403
......@@ -1735,12 +1407,6 @@ pub const Namespace = struct {
17351407 }
17361408 decls.deinit(gpa);
17371409
1738 for (anon_decls.keys()) |child_decl| {
1739 mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory");
1740 mod.destroyDecl(child_decl);
1741 }
1742 anon_decls.deinit(gpa);
1743
17441410 ns.usingnamespace_set.deinit(gpa);
17451411 }
17461412
......@@ -2155,8 +1821,8 @@ pub const SrcLoc = struct {
21551821 return tree.firstToken(src_loc.parent_decl_node);
21561822 }
21571823
2158 pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.TokenIndex {
2159 return @as(Ast.Node.Index, @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node))));
1824 pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index {
1825 return @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node)));
21601826 }
21611827
21621828 pub const Span = struct {
......@@ -2468,6 +2134,37 @@ pub const SrcLoc = struct {
24682134 }
24692135 } else unreachable;
24702136 },
2137 .call_arg => |call_arg| {
2138 const tree = try src_loc.file_scope.getTree(gpa);
2139 const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset);
2140 var buf: [1]Ast.Node.Index = undefined;
2141 const call_full = tree.fullCall(&buf, node).?;
2142 const src_node = call_full.ast.params[call_arg.arg_index];
2143 return nodeToSpan(tree, src_node);
2144 },
2145 .fn_proto_param => |fn_proto_param| {
2146 const tree = try src_loc.file_scope.getTree(gpa);
2147 const node = src_loc.declRelativeToNodeIndex(fn_proto_param.fn_proto_node_offset);
2148 var buf: [1]Ast.Node.Index = undefined;
2149 const full = tree.fullFnProto(&buf, node).?;
2150 var it = full.iterate(tree);
2151 var i: usize = 0;
2152 while (it.next()) |param| : (i += 1) {
2153 if (i == fn_proto_param.param_index) {
2154 if (param.anytype_ellipsis3) |token| return tokenToSpan(tree, token);
2155 const first_token = param.comptime_noalias orelse
2156 param.name_token orelse
2157 tree.firstToken(param.type_expr);
2158 return tokensToSpan(
2159 tree,
2160 first_token,
2161 tree.lastToken(param.type_expr),
2162 first_token,
2163 );
2164 }
2165 }
2166 unreachable;
2167 },
24712168 .node_offset_bin_lhs => |node_off| {
24722169 const tree = try src_loc.file_scope.getTree(gpa);
24732170 const node = src_loc.declRelativeToNodeIndex(node_off);
......@@ -2820,6 +2517,10 @@ pub const SrcLoc = struct {
28202517 );
28212518 }
28222519
2520 fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span {
2521 return tokensToSpan(tree, token, token, token);
2522 }
2523
28232524 fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {
28242525 const token_starts = tree.tokens.items(.start);
28252526 var start_tok = start;
......@@ -3146,6 +2847,21 @@ pub const LazySrcLoc = union(enum) {
31462847 /// Next, navigate to the corresponding capture.
31472848 /// The Decl is determined contextually.
31482849 for_capture_from_input: i32,
2850 /// The source location points to the argument node of a function call.
2851 call_arg: struct {
2852 decl: Decl.Index,
2853 /// Points to the function call AST node.
2854 call_node_offset: i32,
2855 /// The index of the argument the source location points to.
2856 arg_index: u32,
2857 },
2858 fn_proto_param: struct {
2859 decl: Decl.Index,
2860 /// Points to the function prototype AST node.
2861 fn_proto_node_offset: i32,
2862 /// The index of the parameter the source location points to.
2863 param_index: u32,
2864 },
31492865
31502866 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
31512867
......@@ -3240,6 +2956,13 @@ pub const LazySrcLoc = union(enum) {
32402956 .parent_decl_node = decl.src_node,
32412957 .lazy = lazy,
32422958 },
2959 inline .call_arg,
2960 .fn_proto_param,
2961 => |x| .{
2962 .file_scope = decl.getFileScope(mod),
2963 .parent_decl_node = mod.declPtr(x.decl).src_node,
2964 .lazy = lazy,
2965 },
32432966 };
32442967 }
32452968};
......@@ -3373,17 +3096,10 @@ pub fn deinit(mod: *Module) void {
33733096 mod.global_error_set.deinit(gpa);
33743097
33753098 mod.test_functions.deinit(gpa);
3376 mod.align_stack_fns.deinit(gpa);
3377 mod.monomorphed_funcs.deinit(gpa);
33783099
3379 mod.decls_free_list.deinit(gpa);
3380 mod.allocated_decls.deinit(gpa);
33813100 mod.global_assembly.deinit(gpa);
33823101 mod.reference_table.deinit(gpa);
33833102
3384 mod.namespaces_free_list.deinit(gpa);
3385 mod.allocated_namespaces.deinit(gpa);
3386
33873103 mod.memoized_decls.deinit(gpa);
33883104 mod.intern_pool.deinit(gpa);
33893105 mod.tmp_hack_arena.deinit();
......@@ -3391,6 +3107,8 @@ pub fn deinit(mod: *Module) void {
33913107
33923108pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
33933109 const gpa = mod.gpa;
3110 const ip = &mod.intern_pool;
3111
33943112 {
33953113 const decl = mod.declPtr(decl_index);
33963114 _ = mod.test_functions.swapRemove(decl_index);
......@@ -3407,15 +3125,12 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
34073125 }
34083126 }
34093127 if (decl.src_scope) |scope| scope.decRef(gpa);
3410 decl.clearValues(mod);
34113128 decl.dependants.deinit(gpa);
34123129 decl.dependencies.deinit(gpa);
3413 decl.* = undefined;
34143130 }
3415 mod.decls_free_list.append(gpa, decl_index) catch {
3416 // In order to keep `destroyDecl` a non-fallible function, we ignore memory
3417 // allocation failures here, instead leaking the Decl until garbage collection.
3418 };
3131
3132 ip.destroyDecl(gpa, decl_index);
3133
34193134 if (mod.emit_h) |mod_emit_h| {
34203135 const decl_emit_h = mod_emit_h.declPtr(decl_index);
34213136 decl_emit_h.fwd_decl.deinit(gpa);
......@@ -3424,11 +3139,11 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
34243139}
34253140
34263141pub fn declPtr(mod: *Module, index: Decl.Index) *Decl {
3427 return mod.allocated_decls.at(@intFromEnum(index));
3142 return mod.intern_pool.declPtr(index);
34283143}
34293144
34303145pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace {
3431 return mod.allocated_namespaces.at(@intFromEnum(index));
3146 return mod.intern_pool.namespacePtr(index);
34323147}
34333148
34343149pub fn unionPtr(mod: *Module, index: Union.Index) *Union {
......@@ -3439,14 +3154,6 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
34393154 return mod.intern_pool.structPtr(index);
34403155}
34413156
3442pub fn funcPtr(mod: *Module, index: Fn.Index) *Fn {
3443 return mod.intern_pool.funcPtr(index);
3444}
3445
3446pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet {
3447 return mod.intern_pool.inferredErrorSetPtr(index);
3448}
3449
34503157pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namespace {
34513158 return mod.namespacePtr(index.unwrap() orelse return null);
34523159}
......@@ -3457,10 +3164,6 @@ pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {
34573164 return mod.structPtr(index.unwrap() orelse return null);
34583165}
34593166
3460pub fn funcPtrUnwrap(mod: *Module, index: Fn.OptionalIndex) ?*Fn {
3461 return mod.funcPtr(index.unwrap() orelse return null);
3462}
3463
34643167/// Returns true if and only if the Decl is the top level struct associated with a File.
34653168pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
34663169 const decl = mod.declPtr(decl_index);
......@@ -3881,6 +3584,8 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
38813584 // to re-generate ZIR for the File.
38823585 try file.outdated_decls.append(gpa, root_decl);
38833586
3587 const ip = &mod.intern_pool;
3588
38843589 while (decl_stack.popOrNull()) |decl_index| {
38853590 const decl = mod.declPtr(decl_index);
38863591 // Anonymous decls and the root decl have this set to 0. We still need
......@@ -3918,7 +3623,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
39183623 }
39193624
39203625 if (decl.getOwnedFunction(mod)) |func| {
3921 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
3626 func.zirBodyInst(ip).* = inst_map.get(func.zir_body_inst) orelse {
39223627 try file.deleted_decls.append(gpa, decl_index);
39233628 continue;
39243629 };
......@@ -3928,9 +3633,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
39283633 for (namespace.decls.keys()) |sub_decl| {
39293634 try decl_stack.append(gpa, sub_decl);
39303635 }
3931 for (namespace.anon_decls.keys()) |sub_decl| {
3932 try decl_stack.append(gpa, sub_decl);
3933 }
39343636 }
39353637 }
39363638}
......@@ -4101,11 +3803,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
41013803 // prior to re-analysis.
41023804 try mod.deleteDeclExports(decl_index);
41033805
4104 // Similarly, `@setAlignStack` invocations will be re-discovered.
4105 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
4106 _ = mod.align_stack_fns.remove(func);
4107 }
4108
41093806 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
41103807 for (decl.dependencies.keys()) |dep_index| {
41113808 const dep = mod.declPtr(dep_index);
......@@ -4189,11 +3886,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
41893886 }
41903887}
41913888
4192pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void {
3889pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaError!void {
41933890 const tracy = trace(@src());
41943891 defer tracy.end();
41953892
4196 const func = mod.funcPtr(func_index);
3893 const ip = &mod.intern_pool;
3894 const func = mod.funcInfo(func_index);
41973895 const decl_index = func.owner_decl;
41983896 const decl = mod.declPtr(decl_index);
41993897
......@@ -4211,7 +3909,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42113909 => return error.AnalysisFail,
42123910
42133911 .complete, .codegen_failure_retryable => {
4214 switch (func.state) {
3912 switch (func.analysis(ip).state) {
42153913 .sema_failure, .dependency_failure => return error.AnalysisFail,
42163914 .none, .queued => {},
42173915 .in_progress => unreachable,
......@@ -4227,11 +3925,11 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42273925
42283926 var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
42293927 error.AnalysisFail => {
4230 if (func.state == .in_progress) {
3928 if (func.analysis(ip).state == .in_progress) {
42313929 // If this decl caused the compile error, the analysis field would
42323930 // be changed to indicate it was this Decl's fault. Because this
42333931 // did not happen, we infer here that it was a dependency failure.
4234 func.state = .dependency_failure;
3932 func.analysis(ip).state = .dependency_failure;
42353933 }
42363934 return error.AnalysisFail;
42373935 },
......@@ -4251,14 +3949,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42513949
42523950 if (no_bin_file and !dump_air and !dump_llvm_ir) return;
42533951
4254 var liveness = try Liveness.analyze(gpa, air, &mod.intern_pool);
3952 var liveness = try Liveness.analyze(gpa, air, ip);
42553953 defer liveness.deinit(gpa);
42563954
42573955 if (dump_air) {
42583956 const fqn = try decl.getFullyQualifiedName(mod);
4259 std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(&mod.intern_pool)});
3957 std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});
42603958 @import("print_air.zig").dump(mod, air, liveness);
4261 std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(&mod.intern_pool)});
3959 std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)});
42623960 }
42633961
42643962 if (std.debug.runtime_safety) {
......@@ -4266,7 +3964,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42663964 .gpa = gpa,
42673965 .air = air,
42683966 .liveness = liveness,
4269 .intern_pool = &mod.intern_pool,
3967 .intern_pool = ip,
42703968 };
42713969 defer verify.deinit();
42723970
......@@ -4321,8 +4019,9 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
43214019/// analyzed, and for ensuring it can exist at runtime (see
43224020/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
43234021/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
4324pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
4325 const func = mod.funcPtr(func_index);
4022pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) !void {
4023 const ip = &mod.intern_pool;
4024 const func = mod.funcInfo(func_index);
43264025 const decl_index = func.owner_decl;
43274026 const decl = mod.declPtr(decl_index);
43284027
......@@ -4348,7 +4047,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
43484047
43494048 assert(decl.has_tv);
43504049
4351 switch (func.state) {
4050 switch (func.analysis(ip).state) {
43524051 .none => {},
43534052 .queued => return,
43544053 // As above, we don't need to forward errors here.
......@@ -4366,7 +4065,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
43664065 // since the last update
43674066 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
43684067 }
4369 func.state = .queued;
4068 func.analysis(ip).state = .queued;
43704069}
43714070
43724071pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {
......@@ -4490,10 +4189,9 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
44904189 .code = file.zir,
44914190 .owner_decl = new_decl,
44924191 .owner_decl_index = new_decl_index,
4493 .func = null,
44944192 .func_index = .none,
44954193 .fn_ret_ty = Type.void,
4496 .owner_func = null,
4194 .fn_ret_ty_ies = null,
44974195 .owner_func_index = .none,
44984196 .comptime_mutable_decls = &comptime_mutable_decls,
44994197 };
......@@ -4573,10 +4271,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
45734271 .code = zir,
45744272 .owner_decl = decl,
45754273 .owner_decl_index = decl_index,
4576 .func = null,
45774274 .func_index = .none,
45784275 .fn_ret_ty = Type.void,
4579 .owner_func = null,
4276 .fn_ret_ty_ies = null,
45804277 .owner_func_index = .none,
45814278 .comptime_mutable_decls = &comptime_mutable_decls,
45824279 };
......@@ -4608,10 +4305,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
46084305 .inlining = null,
46094306 .is_comptime = true,
46104307 };
4611 defer {
4612 block_scope.instructions.deinit(gpa);
4613 block_scope.params.deinit(gpa);
4614 }
4308 defer block_scope.instructions.deinit(gpa);
46154309
46164310 const zir_block_index = decl.zirBlockIndex(mod);
46174311 const inst_data = zir_datas[zir_block_index].pl_node;
......@@ -4658,48 +4352,49 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
46584352 return true;
46594353 }
46604354
4661 if (mod.intern_pool.indexToFunc(decl_tv.val.toIntern()).unwrap()) |func_index| {
4662 const func = mod.funcPtr(func_index);
4663 const owns_tv = func.owner_decl == decl_index;
4664 if (owns_tv) {
4665 var prev_type_has_bits = false;
4666 var prev_is_inline = false;
4667 var type_changed = true;
4668
4669 if (decl.has_tv) {
4670 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
4671 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4672 if (decl.getOwnedFunction(mod)) |prev_func| {
4673 prev_is_inline = prev_func.state == .inline_only;
4355 const ip = &mod.intern_pool;
4356 switch (ip.indexToKey(decl_tv.val.toIntern())) {
4357 .func => |func| {
4358 const owns_tv = func.owner_decl == decl_index;
4359 if (owns_tv) {
4360 var prev_type_has_bits = false;
4361 var prev_is_inline = false;
4362 var type_changed = true;
4363
4364 if (decl.has_tv) {
4365 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
4366 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4367 if (decl.getOwnedFunction(mod)) |prev_func| {
4368 prev_is_inline = prev_func.analysis(ip).state == .inline_only;
4369 }
46744370 }
4675 }
4676 decl.clearValues(mod);
4677
4678 decl.ty = decl_tv.ty;
4679 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
4680 // linksection, align, and addrspace were already set by Sema
4681 decl.has_tv = true;
4682 decl.owns_tv = owns_tv;
4683 decl.analysis = .complete;
4684 decl.generation = mod.generation;
4685
4686 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
4687 if (decl.is_exported) {
4688 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
4689 if (is_inline) {
4690 return sema.fail(&block_scope, export_src, "export of inline function", .{});
4371
4372 decl.ty = decl_tv.ty;
4373 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
4374 // linksection, align, and addrspace were already set by Sema
4375 decl.has_tv = true;
4376 decl.owns_tv = owns_tv;
4377 decl.analysis = .complete;
4378 decl.generation = mod.generation;
4379
4380 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
4381 if (decl.is_exported) {
4382 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
4383 if (is_inline) {
4384 return sema.fail(&block_scope, export_src, "export of inline function", .{});
4385 }
4386 // The scope needs to have the decl in it.
4387 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
46914388 }
4692 // The scope needs to have the decl in it.
4693 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
4389 return type_changed or is_inline != prev_is_inline;
46944390 }
4695 return type_changed or is_inline != prev_is_inline;
4696 }
4391 },
4392 else => {},
46974393 }
46984394 var type_changed = true;
46994395 if (decl.has_tv) {
47004396 type_changed = !decl.ty.eql(decl_tv.ty, mod);
47014397 }
4702 decl.clearValues(mod);
47034398
47044399 decl.owns_tv = false;
47054400 var queue_linker_work = false;
......@@ -4707,7 +4402,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47074402 switch (decl_tv.val.toIntern()) {
47084403 .generic_poison => unreachable,
47094404 .unreachable_value => unreachable,
4710 else => switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
4405 else => switch (ip.indexToKey(decl_tv.val.toIntern())) {
47114406 .variable => |variable| if (variable.decl == decl_index) {
47124407 decl.owns_tv = true;
47134408 queue_linker_work = true;
......@@ -4743,11 +4438,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47434438 } else if (bytes.len == 0) {
47444439 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
47454440 }
4746 const section = try mod.intern_pool.getOrPutString(gpa, bytes);
4441 const section = try ip.getOrPutString(gpa, bytes);
47474442 break :blk section.toOptional();
47484443 };
47494444 decl.@"addrspace" = blk: {
4750 const addrspace_ctx: Sema.AddressSpaceContext = switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
4445 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) {
47514446 .variable => .variable,
47524447 .extern_func, .func => .function,
47534448 else => .constant,
......@@ -5309,7 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
53095004 decl.has_align = has_align;
53105005 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
53115006 decl.zir_decl_index = @as(u32, @intCast(decl_sub_index));
5312 if (decl.getOwnedFunctionIndex(mod) != .none) {
5007 if (decl.getOwnedFunction(mod) != null) {
53135008 switch (comp.bin_file.tag) {
53145009 .coff, .elf, .macho, .plan9 => {
53155010 // TODO Look into detecting when this would be unnecessary by storing enough state
......@@ -5386,7 +5081,6 @@ pub fn clearDecl(
53865081 try namespace.deleteAllDecls(mod, outdated_decls);
53875082 }
53885083 }
5389 decl.clearValues(mod);
53905084
53915085 if (decl.deletion_flag) {
53925086 decl.deletion_flag = false;
......@@ -5397,21 +5091,19 @@ pub fn clearDecl(
53975091}
53985092
53995093/// This function is exclusively called for anonymous decls.
5094/// All resources referenced by anonymous decls are owned by InternPool
5095/// so there is no cleanup to do here.
54005096pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {
5401 const decl = mod.declPtr(decl_index);
5402
5403 assert(!mod.declIsRoot(decl_index));
5404 assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index));
5097 const gpa = mod.gpa;
5098 const ip = &mod.intern_pool;
54055099
5406 const dependants = decl.dependants.keys();
5407 for (dependants) |dep| {
5408 mod.declPtr(dep).removeDependency(decl_index);
5409 }
5100 ip.destroyDecl(gpa, decl_index);
54105101
5411 for (decl.dependencies.keys()) |dep| {
5412 mod.declPtr(dep).removeDependant(decl_index);
5102 if (mod.emit_h) |mod_emit_h| {
5103 const decl_emit_h = mod_emit_h.declPtr(decl_index);
5104 decl_emit_h.fwd_decl.deinit(gpa);
5105 decl_emit_h.* = undefined;
54135106 }
5414 mod.destroyDecl(decl_index);
54155107}
54165108
54175109/// We don't perform a deletion here, because this Decl or another one
......@@ -5428,7 +5120,6 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
54285120 const decl = mod.declPtr(decl_index);
54295121
54305122 assert(!mod.declIsRoot(decl_index));
5431 assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index));
54325123
54335124 // An aborted decl must not have dependants -- they must have
54345125 // been aborted first and removed from this list.
......@@ -5497,19 +5188,26 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
54975188 export_owners.deinit(mod.gpa);
54985189}
54995190
5500pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaError!Air {
5191pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocator) SemaError!Air {
55015192 const tracy = trace(@src());
55025193 defer tracy.end();
55035194
55045195 const gpa = mod.gpa;
5505 const func = mod.funcPtr(func_index);
5196 const ip = &mod.intern_pool;
5197 const func = mod.funcInfo(func_index);
55065198 const decl_index = func.owner_decl;
55075199 const decl = mod.declPtr(decl_index);
55085200
55095201 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
55105202 defer comptime_mutable_decls.deinit();
55115203
5204 // In the case of a generic function instance, this is the type of the
5205 // instance, which has comptime parameters elided. In other words, it is
5206 // the runtime-known parameters only, not to be confused with the
5207 // generic_owner function type, which potentially has more parameters,
5208 // including comptime parameters.
55125209 const fn_ty = decl.ty;
5210 const fn_ty_info = mod.typeToFunc(fn_ty).?;
55135211
55145212 var sema: Sema = .{
55155213 .mod = mod,
......@@ -5518,18 +5216,23 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
55185216 .code = decl.getFileScope(mod).zir,
55195217 .owner_decl = decl,
55205218 .owner_decl_index = decl_index,
5521 .func = func,
5522 .func_index = func_index.toOptional(),
5523 .fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(),
5524 .owner_func = func,
5525 .owner_func_index = func_index.toOptional(),
5526 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
5219 .func_index = func_index,
5220 .fn_ret_ty = fn_ty_info.return_type.toType(),
5221 .fn_ret_ty_ies = null,
5222 .owner_func_index = func_index,
5223 .branch_quota = @max(func.branchQuota(ip).*, Sema.default_branch_quota),
55275224 .comptime_mutable_decls = &comptime_mutable_decls,
55285225 };
55295226 defer sema.deinit();
55305227
5228 if (func.analysis(ip).inferred_error_set) {
5229 const ies = try arena.create(Sema.InferredErrorSet);
5230 ies.* = .{ .func = func_index };
5231 sema.fn_ret_ty_ies = ies;
5232 }
5233
55315234 // reset in case calls to errorable functions are removed.
5532 func.calls_or_awaits_errorable_fn = false;
5235 func.analysis(ip).calls_or_awaits_errorable_fn = false;
55335236
55345237 // First few indexes of extra are reserved and set at the end.
55355238 const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len;
......@@ -5551,8 +5254,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
55515254 };
55525255 defer inner_block.instructions.deinit(gpa);
55535256
5554 const fn_info = sema.code.getFnInfo(func.zir_body_inst);
5555 const zir_tags = sema.code.instructions.items(.tag);
5257 const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*);
55565258
55575259 // Here we are performing "runtime semantic analysis" for a function body, which means
55585260 // we must map the parameter ZIR instructions to `arg` AIR instructions.
......@@ -5560,35 +5262,36 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
55605262 // This could be a generic function instantiation, however, in which case we need to
55615263 // map the comptime parameters to constant values and only emit arg AIR instructions
55625264 // for the runtime ones.
5563 const runtime_params_len = @as(u32, @intCast(mod.typeToFunc(fn_ty).?.param_types.len));
5265 const runtime_params_len = fn_ty_info.param_types.len;
55645266 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
5565 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
5267 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len);
55665268 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
55675269
5568 var runtime_param_index: usize = 0;
5569 var total_param_index: usize = 0;
5570 for (fn_info.param_body) |inst| {
5571 switch (zir_tags[inst]) {
5572 .param, .param_comptime, .param_anytype, .param_anytype_comptime => {},
5573 else => continue,
5270 // In the case of a generic function instance, pre-populate all the comptime args.
5271 if (func.comptime_args.len != 0) {
5272 for (
5273 fn_info.param_body[0..func.comptime_args.len],
5274 func.comptime_args.get(ip),
5275 ) |inst, comptime_arg| {
5276 if (comptime_arg == .none) continue;
5277 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.internedToRef(comptime_arg));
55745278 }
5575 const param_ty = if (func.comptime_args) |comptime_args| t: {
5576 const arg_tv = comptime_args[total_param_index];
5577
5578 const arg_val = if (!arg_tv.val.isGenericPoison())
5579 arg_tv.val
5580 else if (try arg_tv.ty.onePossibleValue(mod)) |opv|
5581 opv
5582 else
5583 break :t arg_tv.ty;
5584
5585 const arg = try sema.addConstant(arg_val);
5586 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5587 total_param_index += 1;
5588 continue;
5589 } else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType();
5279 }
5280
5281 const src_params_len = if (func.comptime_args.len != 0)
5282 func.comptime_args.len
5283 else
5284 runtime_params_len;
5285
5286 var runtime_param_index: usize = 0;
5287 for (fn_info.param_body[0..src_params_len], 0..) |inst, src_param_index| {
5288 const gop = sema.inst_map.getOrPutAssumeCapacity(inst);
5289 if (gop.found_existing) continue; // provided above by comptime arg
55905290
5591 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
5291 const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index];
5292 runtime_param_index += 1;
5293
5294 const opt_opv = sema.typeHasOnePossibleValue(param_ty.toType()) catch |err| switch (err) {
55925295 error.NeededSourceLocation => unreachable,
55935296 error.GenericPoison => unreachable,
55945297 error.ComptimeReturn => unreachable,
......@@ -5596,28 +5299,22 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
55965299 else => |e| return e,
55975300 };
55985301 if (opt_opv) |opv| {
5599 const arg = try sema.addConstant(opv);
5600 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5601 total_param_index += 1;
5602 runtime_param_index += 1;
5302 gop.value_ptr.* = Air.internedToRef(opv.toIntern());
56035303 continue;
56045304 }
5605 const air_ty = try sema.addType(param_ty);
5606 const arg_index = @as(u32, @intCast(sema.air_instructions.len));
5305 const arg_index: u32 = @intCast(sema.air_instructions.len);
5306 gop.value_ptr.* = Air.indexToRef(arg_index);
56075307 inner_block.instructions.appendAssumeCapacity(arg_index);
56085308 sema.air_instructions.appendAssumeCapacity(.{
56095309 .tag = .arg,
56105310 .data = .{ .arg = .{
5611 .ty = air_ty,
5612 .src_index = @as(u32, @intCast(total_param_index)),
5311 .ty = Air.internedToRef(param_ty),
5312 .src_index = @intCast(src_param_index),
56135313 } },
56145314 });
5615 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
5616 total_param_index += 1;
5617 runtime_param_index += 1;
56185315 }
56195316
5620 func.state = .in_progress;
5317 func.analysis(ip).state = .in_progress;
56215318
56225319 const last_arg_index = inner_block.instructions.items.len;
56235320
......@@ -5648,7 +5345,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
56485345 }
56495346
56505347 // If we don't get an error return trace from a caller, create our own.
5651 if (func.calls_or_awaits_errorable_fn and
5348 if (func.analysis(ip).calls_or_awaits_errorable_fn and
56525349 mod.comp.bin_file.options.error_return_tracing and
56535350 !sema.fn_ret_ty.isError(mod))
56545351 {
......@@ -5672,12 +5369,33 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
56725369 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
56735370 inner_block.instructions.items.len);
56745371 const main_block_index = sema.addExtraAssumeCapacity(Air.Block{
5675 .body_len = @as(u32, @intCast(inner_block.instructions.items.len)),
5372 .body_len = @intCast(inner_block.instructions.items.len),
56765373 });
56775374 sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
56785375 sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;
56795376
5680 func.state = .success;
5377 // Resolving inferred error sets is done *before* setting the function
5378 // state to success, so that "unable to resolve inferred error set" errors
5379 // can be emitted here.
5380 if (sema.fn_ret_ty_ies) |ies| {
5381 sema.resolveInferredErrorSetPtr(&inner_block, LazySrcLoc.nodeOffset(0), ies) catch |err| switch (err) {
5382 error.NeededSourceLocation => unreachable,
5383 error.GenericPoison => unreachable,
5384 error.ComptimeReturn => unreachable,
5385 error.ComptimeBreak => unreachable,
5386 error.AnalysisFail => {
5387 // In this case our function depends on a type that had a compile error.
5388 // We should not try to lower this function.
5389 decl.analysis = .dependency_failure;
5390 return error.AnalysisFail;
5391 },
5392 else => |e| return e,
5393 };
5394 assert(ies.resolved != .none);
5395 ip.funcIesResolved(func_index).* = ies.resolved;
5396 }
5397
5398 func.analysis(ip).state = .success;
56815399
56825400 // Finally we must resolve the return type and parameter types so that backends
56835401 // have full access to type information.
......@@ -5716,7 +5434,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
57165434 };
57175435 }
57185436
5719 return Air{
5437 return .{
57205438 .instructions = sema.air_instructions.toOwnedSlice(),
57215439 .extra = try sema.air_extra.toOwnedSlice(gpa),
57225440 };
......@@ -5731,9 +5449,6 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
57315449 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
57325450 for (kv.value) |err| err.deinit(mod.gpa);
57335451 }
5734 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
5735 _ = mod.align_stack_fns.remove(func);
5736 }
57375452 if (mod.emit_h) |emit_h| {
57385453 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
57395454 kv.value.destroy(mod.gpa);
......@@ -5744,21 +5459,11 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
57445459}
57455460
57465461pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index {
5747 if (mod.namespaces_free_list.popOrNull()) |index| {
5748 mod.allocated_namespaces.at(@intFromEnum(index)).* = initialization;
5749 return index;
5750 }
5751 const ptr = try mod.allocated_namespaces.addOne(mod.gpa);
5752 ptr.* = initialization;
5753 return @as(Namespace.Index, @enumFromInt(mod.allocated_namespaces.len - 1));
5462 return mod.intern_pool.createNamespace(mod.gpa, initialization);
57545463}
57555464
57565465pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void {
5757 mod.namespacePtr(index).* = undefined;
5758 mod.namespaces_free_list.append(mod.gpa, index) catch {
5759 // In order to keep `destroyNamespace` a non-fallible function, we ignore memory
5760 // allocation failures here, instead leaking the Namespace until garbage collection.
5761 };
5466 return mod.intern_pool.destroyNamespace(mod.gpa, index);
57625467}
57635468
57645469pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index {
......@@ -5777,43 +5482,15 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {
57775482 return mod.intern_pool.destroyUnion(mod.gpa, index);
57785483}
57795484
5780pub fn createFunc(mod: *Module, initialization: Fn) Allocator.Error!Fn.Index {
5781 return mod.intern_pool.createFunc(mod.gpa, initialization);
5782}
5783
5784pub fn destroyFunc(mod: *Module, index: Fn.Index) void {
5785 return mod.intern_pool.destroyFunc(mod.gpa, index);
5786}
5787
57885485pub fn allocateNewDecl(
57895486 mod: *Module,
57905487 namespace: Namespace.Index,
57915488 src_node: Ast.Node.Index,
57925489 src_scope: ?*CaptureScope,
57935490) !Decl.Index {
5794 const decl_and_index: struct {
5795 new_decl: *Decl,
5796 decl_index: Decl.Index,
5797 } = if (mod.decls_free_list.popOrNull()) |decl_index| d: {
5798 break :d .{
5799 .new_decl = mod.declPtr(decl_index),
5800 .decl_index = decl_index,
5801 };
5802 } else d: {
5803 const decl = try mod.allocated_decls.addOne(mod.gpa);
5804 errdefer mod.allocated_decls.shrinkRetainingCapacity(mod.allocated_decls.len - 1);
5805 if (mod.emit_h) |mod_emit_h| {
5806 const decl_emit_h = try mod_emit_h.allocated_emit_h.addOne(mod.gpa);
5807 decl_emit_h.* = .{};
5808 }
5809 break :d .{
5810 .new_decl = decl,
5811 .decl_index = @as(Decl.Index, @enumFromInt(mod.allocated_decls.len - 1)),
5812 };
5813 };
5814
5815 if (src_scope) |scope| scope.incRef();
5816 decl_and_index.new_decl.* = .{
5491 const ip = &mod.intern_pool;
5492 const gpa = mod.gpa;
5493 const decl_index = try ip.createDecl(gpa, .{
58175494 .name = undefined,
58185495 .src_namespace = namespace,
58195496 .src_node = src_node,
......@@ -5836,9 +5513,18 @@ pub fn allocateNewDecl(
58365513 .has_align = false,
58375514 .alive = false,
58385515 .kind = .anon,
5839 };
5516 });
5517
5518 if (mod.emit_h) |mod_emit_h| {
5519 if (@intFromEnum(decl_index) >= mod_emit_h.allocated_emit_h.len) {
5520 try mod_emit_h.allocated_emit_h.append(gpa, .{});
5521 assert(@intFromEnum(decl_index) == mod_emit_h.allocated_emit_h.len);
5522 }
5523 }
5524
5525 if (src_scope) |scope| scope.incRef();
58405526
5841 return decl_and_index.decl_index;
5527 return decl_index;
58425528}
58435529
58445530pub fn getErrorValue(
......@@ -5874,7 +5560,7 @@ pub fn createAnonymousDeclFromDecl(
58745560 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{
58755561 src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index),
58765562 });
5877 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, tv, name);
5563 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, tv, name);
58785564 return new_decl_index;
58795565}
58805566
......@@ -5882,7 +5568,6 @@ pub fn initNewAnonDecl(
58825568 mod: *Module,
58835569 new_decl_index: Decl.Index,
58845570 src_line: u32,
5885 namespace: Namespace.Index,
58865571 typed_value: TypedValue,
58875572 name: InternPool.NullTerminatedString,
58885573) Allocator.Error!void {
......@@ -5899,8 +5584,6 @@ pub fn initNewAnonDecl(
58995584 new_decl.has_tv = true;
59005585 new_decl.analysis = .complete;
59015586 new_decl.generation = mod.generation;
5902
5903 try mod.namespacePtr(namespace).anon_decls.putNoClobber(mod.gpa, new_decl_index, {});
59045587}
59055588
59065589pub fn errNoteNonLazy(
......@@ -6578,7 +6261,6 @@ pub fn populateTestFunctions(
65786261
65796262 // Since we are replacing the Decl's value we must perform cleanup on the
65806263 // previous value.
6581 decl.clearValues(mod);
65826264 decl.ty = new_ty;
65836265 decl.val = new_val;
65846266 decl.has_tv = true;
......@@ -6657,7 +6339,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
66576339 switch (mod.intern_pool.indexToKey(val.toIntern())) {
66586340 .variable => |variable| try mod.markDeclIndexAlive(variable.decl),
66596341 .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),
6660 .func => |func| try mod.markDeclIndexAlive(mod.funcPtr(func.index).owner_decl),
6342 .func => |func| try mod.markDeclIndexAlive(func.owner_decl),
66616343 .error_union => |error_union| switch (error_union.val) {
66626344 .err_name => {},
66636345 .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),
......@@ -6851,8 +6533,8 @@ pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator
68516533 return mod.ptrType(info);
68526534}
68536535
6854pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Type {
6855 return (try intern(mod, .{ .func_type = info })).toType();
6536pub fn funcType(mod: *Module, key: InternPool.GetFuncTypeKey) Allocator.Error!Type {
6537 return (try mod.intern_pool.getFuncType(mod.gpa, key)).toType();
68566538}
68576539
68586540/// Use this for `anyframe->T` only.
......@@ -6870,7 +6552,8 @@ pub fn errorUnionType(mod: *Module, error_set_ty: Type, payload_ty: Type) Alloca
68706552
68716553pub fn singleErrorSetType(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type {
68726554 const names: *const [1]InternPool.NullTerminatedString = &name;
6873 return (try mod.intern_pool.get(mod.gpa, .{ .error_set_type = .{ .names = names } })).toType();
6555 const new_ty = try mod.intern_pool.getErrorSetType(mod.gpa, names);
6556 return new_ty.toType();
68746557}
68756558
68766559/// Sorts `names` in place.
......@@ -6884,7 +6567,7 @@ pub fn errorSetFromUnsortedNames(
68846567 {},
68856568 InternPool.NullTerminatedString.indexLessThan,
68866569 );
6887 const new_ty = try mod.intern(.{ .error_set_type = .{ .names = names } });
6570 const new_ty = try mod.intern_pool.getErrorSetType(mod.gpa, names);
68886571 return new_ty.toType();
68896572}
68906573
......@@ -7231,14 +6914,20 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {
72316914 return mod.intern_pool.indexToFuncType(ty.toIntern());
72326915}
72336916
7234pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*Fn.InferredErrorSet {
7235 const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;
7236 return mod.inferredErrorSetPtr(index);
6917pub fn funcOwnerDeclPtr(mod: *Module, func_index: InternPool.Index) *Decl {
6918 return mod.declPtr(mod.funcOwnerDeclIndex(func_index));
6919}
6920
6921pub fn funcOwnerDeclIndex(mod: *Module, func_index: InternPool.Index) Decl.Index {
6922 return mod.funcInfo(func_index).owner_decl;
6923}
6924
6925pub fn iesFuncIndex(mod: *const Module, ies_index: InternPool.Index) InternPool.Index {
6926 return mod.intern_pool.iesFuncIndex(ies_index);
72376927}
72386928
7239pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) Fn.InferredErrorSet.OptionalIndex {
7240 if (ty.ip_index == .none) return .none;
7241 return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern());
6929pub fn funcInfo(mod: *Module, func_index: InternPool.Index) InternPool.Key.Func {
6930 return mod.intern_pool.indexToKey(func_index).func;
72426931}
72436932
72446933pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {
......@@ -7265,3 +6954,41 @@ pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQu
72656954pub fn toEnum(mod: *Module, comptime E: type, val: Value) E {
72666955 return mod.intern_pool.toEnum(E, val.toIntern());
72676956}
6957
6958pub fn isAnytypeParam(mod: *Module, func: InternPool.Index, index: u32) bool {
6959 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
6960
6961 const tags = file.zir.instructions.items(.tag);
6962
6963 const param_body = file.zir.getParamBody(func.zir_body_inst);
6964 const param = param_body[index];
6965
6966 return switch (tags[param]) {
6967 .param, .param_comptime => false,
6968 .param_anytype, .param_anytype_comptime => true,
6969 else => unreachable,
6970 };
6971}
6972
6973pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0]const u8 {
6974 const func = mod.funcInfo(func_index);
6975 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
6976
6977 const tags = file.zir.instructions.items(.tag);
6978 const data = file.zir.instructions.items(.data);
6979
6980 const param_body = file.zir.getParamBody(func.zir_body_inst);
6981 const param = param_body[index];
6982
6983 return switch (tags[param]) {
6984 .param, .param_comptime => blk: {
6985 const extra = file.zir.extraData(Zir.Inst.Param, data[param].pl_tok.payload_index);
6986 break :blk file.zir.nullTerminatedString(extra.data.name);
6987 },
6988 .param_anytype, .param_anytype_comptime => blk: {
6989 const param_data = data[param].str_tok;
6990 break :blk param_data.get(file.zir);
6991 },
6992 else => unreachable,
6993 };
6994}
src/Sema.zig+1364-1345
......@@ -23,13 +23,13 @@ owner_decl: *Decl,
2323owner_decl_index: Decl.Index,
2424/// For an inline or comptime function call, this will be the root parent function
2525/// which contains the callsite. Corresponds to `owner_decl`.
26owner_func: ?*Module.Fn,
27owner_func_index: Module.Fn.OptionalIndex,
26/// This could be `none`, a `func_decl`, or a `func_instance`.
27owner_func_index: InternPool.Index,
2828/// The function this ZIR code is the body of, according to the source code.
29/// This starts out the same as `owner_func` and then diverges in the case of
29/// This starts out the same as `owner_func_index` and then diverges in the case of
3030/// an inline or comptime function call.
31func: ?*Module.Fn,
32func_index: Module.Fn.OptionalIndex,
31/// This could be `none`, a `func_decl`, or a `func_instance`.
32func_index: InternPool.Index,
3333/// Used to restore the error return trace when returning a non-error from a function.
3434error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
3535/// When semantic analysis needs to know the return type of the function whose body
......@@ -38,6 +38,10 @@ error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
3838/// generic function which uses a type expression for the return type.
3939/// The type will be `void` in the case that `func` is `null`.
4040fn_ret_ty: Type,
41/// In case of the return type being an error union with an inferred error
42/// set, this is the inferred error set. `null` otherwise. Allocated with
43/// `Sema.arena`.
44fn_ret_ty_ies: ?*InferredErrorSet,
4145branch_quota: u32 = default_branch_quota,
4246branch_count: u32 = 0,
4347/// Populated when returning `error.ComptimeBreak`. Used to communicate the
......@@ -49,21 +53,23 @@ comptime_break_inst: Zir.Inst.Index = undefined,
4953/// contain a mapped source location.
5054src: LazySrcLoc = .{ .token_offset = 0 },
5155decl_val_table: std.AutoHashMapUnmanaged(Decl.Index, Air.Inst.Ref) = .{},
52/// When doing a generic function instantiation, this array collects a
53/// `Value` object for each parameter that is comptime-known and thus elided
54/// from the generated function. This memory is allocated by a parent `Sema` and
55/// owned by the values arena of the Sema owner_decl.
56comptime_args: []TypedValue = &.{},
57/// Marks the function instruction that `comptime_args` applies to so that we
58/// don't accidentally apply it to a function prototype which is used in the
59/// type expression of a generic function parameter.
60comptime_args_fn_inst: Zir.Inst.Index = 0,
61/// When `comptime_args` is provided, this field is also provided. It was used as
62/// the key in the `monomorphed_funcs` set. The `func` instruction is supposed
63/// to use this instead of allocating a fresh one. This avoids an unnecessary
64/// extra hash table lookup in the `monomorphed_funcs` set.
65/// Sema will set this to null when it takes ownership.
66preallocated_new_func: Module.Fn.OptionalIndex = .none,
56/// When doing a generic function instantiation, this array collects a value
57/// for each parameter of the generic owner. `none` for non-comptime parameters.
58/// This is a separate array from `block.params` so that it can be passed
59/// directly to `comptime_args` when calling `InternPool.getFuncInstance`.
60/// This memory is allocated by a parent `Sema` in the temporary arena, and is
61/// used only to add a `func_instance` into the `InternPool`.
62comptime_args: []InternPool.Index = &.{},
63/// Used to communicate from a generic function instantiation to the logic that
64/// creates a generic function instantiation value in `funcCommon`.
65generic_owner: InternPool.Index = .none,
66/// When `generic_owner` is not none, this contains the generic function
67/// instantiation callsite so that compile errors on the parameter types of the
68/// instantiation can point back to the instantiation site in addition to the
69/// declaration site.
70generic_call_src: LazySrcLoc = .unneeded,
71/// Corresponds to `generic_call_src`.
72generic_call_decl: Decl.OptionalIndex = .none,
6773/// The key is types that must be fully resolved prior to machine code
6874/// generation pass. Types are added to this set when resolving them
6975/// immediately could cause a dependency loop, but they do need to be resolved
......@@ -79,8 +85,6 @@ types_to_resolve: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{},
7985post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
8086/// Populated with the last compile error created.
8187err: ?*Module.ErrorMsg = null,
82/// True when analyzing a generic instantiation. Used to suppress some errors.
83is_generic_instantiation: bool = false,
8488/// Set to true when analyzing a func type instruction so that nested generic
8589/// function types will emit generic poison instead of a partial type.
8690no_partial_func_ty: bool = false,
......@@ -97,6 +101,10 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAll
97101/// involve transitioning comptime-mutable memory away from using Decls at all.
98102comptime_mutable_decls: *std.ArrayList(Decl.Index),
99103
104/// This is populated when `@setAlignStack` occurs so that if there is a duplicate
105/// one encountered, the conflicting source location can be shown.
106prev_stack_alignment_src: ?LazySrcLoc = null,
107
100108const std = @import("std");
101109const math = std.math;
102110const mem = std.mem;
......@@ -131,6 +139,49 @@ const Alignment = InternPool.Alignment;
131139pub const default_branch_quota = 1000;
132140pub const default_reference_trace_len = 2;
133141
142pub const InferredErrorSet = struct {
143 /// The function body from which this error set originates.
144 /// This is `none` in the case of a comptime/inline function call, corresponding to
145 /// `InternPool.Index.adhoc_inferred_error_set_type`.
146 /// The function's resolved error set is not set until analysis of the
147 /// function body completes.
148 func: InternPool.Index,
149 /// All currently known errors that this error set contains. This includes
150 /// direct additions via `return error.Foo;`, and possibly also errors that
151 /// are returned from any dependent functions.
152 errors: NameMap = .{},
153 /// Other inferred error sets which this inferred error set should include.
154 inferred_error_sets: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{},
155 /// The regular error set created by resolving this inferred error set.
156 resolved: InternPool.Index = .none,
157
158 pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
159
160 pub fn addErrorSet(
161 self: *InferredErrorSet,
162 err_set_ty: Type,
163 ip: *InternPool,
164 arena: Allocator,
165 ) !void {
166 switch (err_set_ty.toIntern()) {
167 .anyerror_type => self.resolved = .anyerror_type,
168 .adhoc_inferred_error_set_type => {}, // Adding an inferred error set to itself.
169
170 else => switch (ip.indexToKey(err_set_ty.toIntern())) {
171 .error_set_type => |error_set_type| {
172 for (error_set_type.names.get(ip)) |name| {
173 try self.errors.put(arena, name, {});
174 }
175 },
176 .inferred_error_set_type => {
177 try self.inferred_error_sets.put(arena, err_set_ty.toIntern(), {});
178 },
179 else => unreachable,
180 },
181 }
182 }
183};
184
134185/// Stores the mapping from `Zir.Inst.Index -> Air.Inst.Ref`, which is used by sema to resolve
135186/// instructions during analysis.
136187/// Instead of a hash table approach, InstMap is simply a slice that is indexed into using the
......@@ -243,7 +294,13 @@ pub const Block = struct {
243294 /// The AIR instructions generated for this block.
244295 instructions: std.ArrayListUnmanaged(Air.Inst.Index),
245296 // `param` instructions are collected here to be used by the `func` instruction.
246 params: std.ArrayListUnmanaged(Param) = .{},
297 /// When doing a generic function instantiation, this array collects a type
298 /// for each *runtime-known* parameter. This array corresponds to the instance
299 /// function type, while `Sema.comptime_args` corresponds to the generic owner
300 /// function type.
301 /// This memory is allocated by a parent `Sema` in the temporary arena, and is
302 /// used to add a `func_instance` into the `InternPool`.
303 params: std.MultiArrayList(Param) = .{},
247304
248305 wip_capture_scope: *CaptureScope,
249306
......@@ -323,10 +380,10 @@ pub const Block = struct {
323380 };
324381
325382 const Param = struct {
326 /// `noreturn` means `anytype`.
327 ty: Type,
383 /// `none` means `anytype`.
384 ty: InternPool.Index,
328385 is_comptime: bool,
329 name: []const u8,
386 name: Zir.NullTerminatedString,
330387 };
331388
332389 /// This `Block` maps a block ZIR instruction to the corresponding
......@@ -342,7 +399,8 @@ pub const Block = struct {
342399 /// It is shared among all the blocks in an inline or comptime called
343400 /// function.
344401 pub const Inlining = struct {
345 func: ?*Module.Fn,
402 /// Might be `none`.
403 func: InternPool.Index,
346404 comptime_result: Air.Inst.Ref,
347405 merges: Merges,
348406 };
......@@ -906,7 +964,7 @@ fn analyzeBodyInner(
906964 // We use a while (true) loop here to avoid a redundant way of breaking out of
907965 // the loop. The only way to break out of the loop is with a `noreturn`
908966 // instruction.
909 var i: usize = 0;
967 var i: u32 = 0;
910968 const result = while (true) {
911969 crash_info.setBodyIndex(i);
912970 const inst = body[i];
......@@ -1116,7 +1174,7 @@ fn analyzeBodyInner(
11161174 .shl_sat => try sema.zirShl(block, inst, .shl_sat),
11171175
11181176 .ret_ptr => try sema.zirRetPtr(block),
1119 .ret_type => try sema.addType(sema.fn_ret_ty),
1177 .ret_type => Air.internedToRef(sema.fn_ret_ty.toIntern()),
11201178
11211179 // Instructions that we know to *always* be noreturn based solely on their tag.
11221180 // These functions match the return type of analyzeBody so that we can
......@@ -1338,22 +1396,22 @@ fn analyzeBodyInner(
13381396 continue;
13391397 },
13401398 .param => {
1341 try sema.zirParam(block, inst, false);
1399 try sema.zirParam(block, inst, i, false);
13421400 i += 1;
13431401 continue;
13441402 },
13451403 .param_comptime => {
1346 try sema.zirParam(block, inst, true);
1404 try sema.zirParam(block, inst, i, true);
13471405 i += 1;
13481406 continue;
13491407 },
13501408 .param_anytype => {
1351 try sema.zirParamAnytype(block, inst, false);
1409 try sema.zirParamAnytype(block, inst, i, false);
13521410 i += 1;
13531411 continue;
13541412 },
13551413 .param_anytype_comptime => {
1356 try sema.zirParamAnytype(block, inst, true);
1414 try sema.zirParamAnytype(block, inst, i, true);
13571415 i += 1;
13581416 continue;
13591417 },
......@@ -1493,10 +1551,7 @@ fn analyzeBodyInner(
14931551 // Note: this probably needs to be resolved in a more general manner.
14941552 const prev_params = block.params;
14951553 block.params = .{};
1496 defer {
1497 block.params.deinit(sema.gpa);
1498 block.params = prev_params;
1499 }
1554 defer block.params = prev_params;
15001555 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
15011556 break always_noreturn;
15021557 if (inst == break_data.block_inst) {
......@@ -1532,7 +1587,6 @@ fn analyzeBodyInner(
15321587 .merges = undefined,
15331588 };
15341589 child_block.label = &label;
1535 defer child_block.params.deinit(gpa);
15361590
15371591 // Write these instructions directly into the parent block
15381592 child_block.instructions = block.instructions;
......@@ -2008,10 +2062,7 @@ fn resolveDefinedValue(
20082062/// Value Tag `variable` causes this function to return `null`.
20092063/// Value Tag `undef` causes this function to return the Value.
20102064/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
2011fn resolveMaybeUndefVal(
2012 sema: *Sema,
2013 inst: Air.Inst.Ref,
2014) CompileError!?Value {
2065fn resolveMaybeUndefVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
20152066 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
20162067 if (val.isGenericPoison()) return error.GenericPoison;
20172068 if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null;
......@@ -2022,10 +2073,7 @@ fn resolveMaybeUndefVal(
20222073/// Value Tag `undef` causes this function to return the Value.
20232074/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
20242075/// Lazy values are recursively resolved.
2025fn resolveMaybeUndefLazyVal(
2026 sema: *Sema,
2027 inst: Air.Inst.Ref,
2028) CompileError!?Value {
2076fn resolveMaybeUndefLazyVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
20292077 return try sema.resolveLazyValue((try sema.resolveMaybeUndefVal(inst)) orelse return null);
20302078}
20312079
......@@ -2034,10 +2082,7 @@ fn resolveMaybeUndefLazyVal(
20342082/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
20352083/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`.
20362084/// Lazy values are recursively resolved.
2037fn resolveMaybeUndefValIntable(
2038 sema: *Sema,
2039 inst: Air.Inst.Ref,
2040) CompileError!?Value {
2085fn resolveMaybeUndefValIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
20412086 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
20422087 if (val.isGenericPoison()) return error.GenericPoison;
20432088 if (val.ip_index == .none) return val;
......@@ -2363,7 +2408,10 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
23632408 break :blk default_reference_trace_len;
23642409 };
23652410
2366 var referenced_by = if (sema.func) |some| some.owner_decl else sema.owner_decl_index;
2411 var referenced_by = if (sema.func_index != .none)
2412 mod.funcOwnerDeclIndex(sema.func_index)
2413 else
2414 sema.owner_decl_index;
23672415 var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa);
23682416 defer reference_stack.deinit();
23692417
......@@ -2399,14 +2447,15 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
23992447 }
24002448 err_msg.reference_trace = try reference_stack.toOwnedSlice();
24012449 }
2402 if (sema.owner_func) |func| {
2403 func.state = .sema_failure;
2450 const ip = &mod.intern_pool;
2451 if (sema.owner_func_index != .none) {
2452 ip.funcAnalysis(sema.owner_func_index).state = .sema_failure;
24042453 } else {
24052454 sema.owner_decl.analysis = .sema_failure;
24062455 sema.owner_decl.generation = mod.generation;
24072456 }
2408 if (sema.func) |func| {
2409 func.state = .sema_failure;
2457 if (sema.func_index != .none) {
2458 ip.funcAnalysis(sema.func_index).state = .sema_failure;
24102459 }
24112460 const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index);
24122461 if (gop.found_existing) {
......@@ -2866,6 +2915,7 @@ fn createAnonymousDeclTypeNamed(
28662915 inst: ?Zir.Inst.Index,
28672916) !Decl.Index {
28682917 const mod = sema.mod;
2918 const ip = &mod.intern_pool;
28692919 const gpa = sema.gpa;
28702920 const namespace = block.namespace;
28712921 const src_scope = block.wip_capture_scope;
......@@ -2886,16 +2936,16 @@ fn createAnonymousDeclTypeNamed(
28862936 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
28872937 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index),
28882938 }) catch unreachable;
2889 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2939 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name);
28902940 return new_decl_index;
28912941 },
28922942 .parent => {
28932943 const name = mod.declPtr(block.src_decl).name;
2894 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2944 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name);
28952945 return new_decl_index;
28962946 },
28972947 .func => {
2898 const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst);
2948 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index));
28992949 const zir_tags = sema.code.instructions.items(.tag);
29002950
29012951 var buf = std.ArrayList(u8).init(gpa);
......@@ -2927,7 +2977,7 @@ fn createAnonymousDeclTypeNamed(
29272977
29282978 try writer.writeByte(')');
29292979 const name = try mod.intern_pool.getOrPutString(gpa, buf.items);
2930 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2980 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name);
29312981 return new_decl_index;
29322982 },
29332983 .dbg_var => {
......@@ -2943,7 +2993,7 @@ fn createAnonymousDeclTypeNamed(
29432993 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),
29442994 });
29452995
2946 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
2996 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name);
29472997 return new_decl_index;
29482998 },
29492999 else => {},
......@@ -3070,18 +3120,12 @@ fn zirEnumDecl(
30703120 sema.owner_decl_index = prev_owner_decl_index;
30713121 }
30723122
3073 const prev_owner_func = sema.owner_func;
30743123 const prev_owner_func_index = sema.owner_func_index;
3075 sema.owner_func = null;
30763124 sema.owner_func_index = .none;
3077 defer sema.owner_func = prev_owner_func;
30783125 defer sema.owner_func_index = prev_owner_func_index;
30793126
3080 const prev_func = sema.func;
30813127 const prev_func_index = sema.func_index;
3082 sema.func = null;
30833128 sema.func_index = .none;
3084 defer sema.func = prev_func;
30853129 defer sema.func_index = prev_func_index;
30863130
30873131 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);
......@@ -3393,7 +3437,7 @@ fn zirErrorSetDecl(
33933437 const src = inst_data.src();
33943438 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
33953439
3396 var names: Module.Fn.InferredErrorSet.NameMap = .{};
3440 var names: InferredErrorSet.NameMap = .{};
33973441 try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len);
33983442
33993443 var extra_index = @as(u32, @intCast(extra.end));
......@@ -5236,12 +5280,10 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
52365280 // %b = store(%a, %c)
52375281 // Where %c is an error union or error set. In such case we need to add
52385282 // to the current function's inferred error set, if any.
5239 if (is_ret and (sema.typeOf(operand).zigTypeTag(mod) == .ErrorUnion or
5240 sema.typeOf(operand).zigTypeTag(mod) == .ErrorSet) and
5241 sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion)
5242 {
5243 try sema.addToInferredErrorSet(operand);
5244 }
5283 if (is_ret and sema.fn_ret_ty_ies != null) switch (sema.typeOf(operand).zigTypeTag(mod)) {
5284 .ErrorUnion, .ErrorSet => try sema.addToInferredErrorSet(operand),
5285 else => {},
5286 };
52455287
52465288 const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node };
52475289 const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node };
......@@ -5379,7 +5421,10 @@ fn zirCompileLog(
53795421 }
53805422 try writer.print("\n", .{});
53815423
5382 const decl_index = if (sema.func) |some| some.owner_decl else sema.owner_decl_index;
5424 const decl_index = if (sema.func_index != .none)
5425 mod.funcOwnerDeclIndex(sema.func_index)
5426 else
5427 sema.owner_decl_index;
53835428 const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index);
53845429 if (!gop.found_existing) {
53855430 gop.value_ptr.* = src_node;
......@@ -5967,11 +6012,11 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
59676012 alignment.toByteUnitsOptional().?,
59686013 });
59696014 }
5970 const func_index = sema.func_index.unwrap() orelse
6015 if (sema.func_index == .none) {
59716016 return sema.fail(block, src, "@setAlignStack outside function body", .{});
5972 const func = mod.funcPtr(func_index);
6017 }
59736018
5974 const fn_owner_decl = mod.declPtr(func.owner_decl);
6019 const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index);
59756020 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
59766021 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
59776022 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),
......@@ -5980,25 +6025,34 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
59806025 },
59816026 }
59826027
5983 const gop = try mod.align_stack_fns.getOrPut(sema.gpa, func_index);
5984 if (gop.found_existing) {
6028 if (sema.prev_stack_alignment_src) |prev_src| {
59856029 const msg = msg: {
59866030 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});
59876031 errdefer msg.destroy(sema.gpa);
5988 try sema.errNote(block, gop.value_ptr.src, msg, "other instance here", .{});
6032 try sema.errNote(block, prev_src, msg, "other instance here", .{});
59896033 break :msg msg;
59906034 };
59916035 return sema.failWithOwnedErrorMsg(msg);
59926036 }
5993 gop.value_ptr.* = .{ .alignment = alignment, .src = src };
6037
6038 const ip = &mod.intern_pool;
6039 const a = ip.funcAnalysis(sema.func_index);
6040 if (a.stack_alignment != .none) {
6041 a.stack_alignment = @enumFromInt(@max(
6042 @intFromEnum(alignment),
6043 @intFromEnum(a.stack_alignment),
6044 ));
6045 }
59946046}
59956047
59966048fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
6049 const mod = sema.mod;
6050 const ip = &mod.intern_pool;
59976051 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
59986052 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
59996053 const is_cold = try sema.resolveConstBool(block, operand_src, extra.operand, "operand to @setCold must be comptime-known");
6000 const func = sema.func orelse return; // does nothing outside a function
6001 func.is_cold = is_cold;
6054 if (sema.func_index == .none) return; // does nothing outside a function
6055 ip.funcAnalysis(sema.func_index).is_cold = is_cold;
60026056}
60036057
60046058fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
......@@ -6308,7 +6362,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
63086362 if (func_val.isUndef(mod)) return null;
63096363 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
63106364 .extern_func => |extern_func| extern_func.decl,
6311 .func => |func| mod.funcPtr(func.index).owner_decl,
6365 .func => |func| func.owner_decl,
63126366 .ptr => |ptr| switch (ptr.addr) {
63136367 .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl,
63146368 else => return null,
......@@ -6445,6 +6499,7 @@ fn zirCall(
64456499 defer tracy.end();
64466500
64476501 const mod = sema.mod;
6502 const ip = &mod.intern_pool;
64486503 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
64496504 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
64506505 const call_src = inst_data.src();
......@@ -6493,9 +6548,10 @@ fn zirCall(
64936548 const args_body = sema.code.extra[extra.end..];
64946549
64956550 var input_is_error = false;
6496 const block_index = @as(Air.Inst.Index, @intCast(block.instructions.items.len));
6551 const block_index: Air.Inst.Index = @intCast(block.instructions.items.len);
64976552
6498 const fn_params_len = mod.typeToFunc(func_ty).?.param_types.len;
6553 const func_ty_info = mod.typeToFunc(func_ty).?;
6554 const fn_params_len = func_ty_info.param_types.len;
64996555 const parent_comptime = block.is_comptime;
65006556 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
65016557 var extra_index: usize = 0;
......@@ -6504,13 +6560,12 @@ fn zirCall(
65046560 extra_index += 1;
65056561 arg_index += 1;
65066562 }) {
6507 const func_ty_info = mod.typeToFunc(func_ty).?;
65086563 const arg_end = sema.code.extra[extra.end + extra_index];
65096564 defer arg_start = arg_end;
65106565
65116566 // Generate args to comptime params in comptime block.
65126567 defer block.is_comptime = parent_comptime;
6513 if (arg_index < @min(fn_params_len, 32) and func_ty_info.paramIsComptime(@as(u5, @intCast(arg_index)))) {
6568 if (arg_index < @min(fn_params_len, 32) and func_ty_info.paramIsComptime(@intCast(arg_index))) {
65146569 block.is_comptime = true;
65156570 // TODO set comptime_reason
65166571 }
......@@ -6519,10 +6574,10 @@ fn zirCall(
65196574 if (arg_index >= fn_params_len)
65206575 break :inst Air.Inst.Ref.var_args_param_type;
65216576
6522 if (func_ty_info.param_types[arg_index] == .generic_poison_type)
6577 if (func_ty_info.param_types.get(ip)[arg_index] == .generic_poison_type)
65236578 break :inst Air.Inst.Ref.generic_poison_type;
65246579
6525 break :inst try sema.addType(func_ty_info.param_types[arg_index].toType());
6580 break :inst try sema.addType(func_ty_info.param_types.get(ip)[arg_index].toType());
65266581 });
65276582
65286583 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
......@@ -6535,7 +6590,9 @@ fn zirCall(
65356590 }
65366591 resolved_args[arg_index] = resolved;
65376592 }
6538 if (sema.owner_func == null or !sema.owner_func.?.calls_or_awaits_errorable_fn) {
6593 if (sema.owner_func_index == .none or
6594 !ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn)
6595 {
65396596 input_is_error = false; // input was an error type, but no errorable fn's were actually called
65406597 }
65416598
......@@ -6702,6 +6759,7 @@ fn analyzeCall(
67026759 call_dbg_node: ?Zir.Inst.Index,
67036760) CompileError!Air.Inst.Ref {
67046761 const mod = sema.mod;
6762 const ip = &mod.intern_pool;
67056763
67066764 const callee_ty = sema.typeOf(func);
67076765 const func_ty_info = mod.typeToFunc(func_ty).?;
......@@ -6749,20 +6807,17 @@ fn analyzeCall(
67496807
67506808 var is_generic_call = func_ty_info.is_generic;
67516809 var is_comptime_call = block.is_comptime or modifier == .compile_time;
6752 var comptime_reason_buf: Block.ComptimeReason = undefined;
67536810 var comptime_reason: ?*const Block.ComptimeReason = null;
67546811 if (!is_comptime_call) {
67556812 if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| {
67566813 is_comptime_call = ct;
67576814 if (ct) {
6758 // stage1 can't handle doing this directly
6759 comptime_reason_buf = .{ .comptime_ret_ty = .{
6815 comptime_reason = &.{ .comptime_ret_ty = .{
67606816 .block = block,
67616817 .func = func,
67626818 .func_src = func_src,
67636819 .return_ty = func_ty_info.return_type.toType(),
67646820 } };
6765 comptime_reason = &comptime_reason_buf;
67666821 }
67676822 } else |err| switch (err) {
67686823 error.GenericPoison => is_generic_call = true,
......@@ -6778,7 +6833,6 @@ fn analyzeCall(
67786833 func,
67796834 func_src,
67806835 call_src,
6781 func_ty,
67826836 ensure_result_used,
67836837 uncasted_args,
67846838 call_tag,
......@@ -6793,14 +6847,12 @@ fn analyzeCall(
67936847 error.ComptimeReturn => {
67946848 is_inline_call = true;
67956849 is_comptime_call = true;
6796 // stage1 can't handle doing this directly
6797 comptime_reason_buf = .{ .comptime_ret_ty = .{
6850 comptime_reason = &.{ .comptime_ret_ty = .{
67986851 .block = block,
67996852 .func = func,
68006853 .func_src = func_src,
68016854 .return_ty = func_ty_info.return_type.toType(),
68026855 } };
6803 comptime_reason = &comptime_reason_buf;
68046856 },
68056857 else => |e| return e,
68066858 }
......@@ -6819,9 +6871,9 @@ fn analyzeCall(
68196871 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
68206872 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
68216873 }),
6822 .func => |function| function.index,
6874 .func => func_val.toIntern(),
68236875 .ptr => |ptr| switch (ptr.addr) {
6824 .decl => |decl| mod.declPtr(decl).val.getFunctionIndex(mod).unwrap().?,
6876 .decl => |decl| mod.declPtr(decl).val.toIntern(),
68256877 else => {
68266878 assert(callee_ty.isPtrAtRuntime(mod));
68276879 return sema.fail(block, call_src, "{s} call of function pointer", .{
......@@ -6850,7 +6902,7 @@ fn analyzeCall(
68506902 // This one is shared among sub-blocks within the same callee, but not
68516903 // shared among the entire inline/comptime call stack.
68526904 var inlining: Block.Inlining = .{
6853 .func = null,
6905 .func = .none,
68546906 .comptime_result = undefined,
68556907 .merges = .{
68566908 .src_locs = .{},
......@@ -6862,7 +6914,7 @@ fn analyzeCall(
68626914 // In order to save a bit of stack space, directly modify Sema rather
68636915 // than create a child one.
68646916 const parent_zir = sema.code;
6865 const module_fn = mod.funcPtr(module_fn_index);
6917 const module_fn = mod.funcInfo(module_fn_index);
68666918 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
68676919 sema.code = fn_owner_decl.getFileScope(mod).zir;
68686920 defer sema.code = parent_zir;
......@@ -6877,11 +6929,8 @@ fn analyzeCall(
68776929 sema.inst_map = parent_inst_map;
68786930 }
68796931
6880 const parent_func = sema.func;
68816932 const parent_func_index = sema.func_index;
6882 sema.func = module_fn;
6883 sema.func_index = module_fn_index.toOptional();
6884 defer sema.func = parent_func;
6933 sema.func_index = module_fn_index;
68856934 defer sema.func_index = parent_func_index;
68866935
68876936 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
......@@ -6913,16 +6962,28 @@ fn analyzeCall(
69136962
69146963 try sema.emitBackwardBranch(block, call_src);
69156964
6916 // Whether this call should be memoized, set to false if the call can mutate comptime state.
6965 // Whether this call should be memoized, set to false if the call can
6966 // mutate comptime state.
69176967 var should_memoize = true;
69186968
69196969 // If it's a comptime function call, we need to memoize it as long as no external
69206970 // comptime memory is mutated.
69216971 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
69226972
6923 var new_fn_info = mod.typeToFunc(fn_owner_decl.ty).?;
6924 new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len);
6925 new_fn_info.comptime_bits = 0;
6973 const owner_info = mod.typeToFunc(fn_owner_decl.ty).?;
6974 var new_fn_info: InternPool.GetFuncTypeKey = .{
6975 .param_types = try sema.arena.alloc(InternPool.Index, owner_info.param_types.len),
6976 .return_type = owner_info.return_type,
6977 .comptime_bits = 0,
6978 .noalias_bits = owner_info.noalias_bits,
6979 .alignment = if (owner_info.align_is_generic) null else owner_info.alignment,
6980 .cc = if (owner_info.cc_is_generic) null else owner_info.cc,
6981 .is_var_args = owner_info.is_var_args,
6982 .is_noinline = owner_info.is_noinline,
6983 .section_is_generic = owner_info.section_is_generic,
6984 .addrspace_is_generic = owner_info.addrspace_is_generic,
6985 .is_generic = owner_info.is_generic,
6986 };
69266987
69276988 // This will have return instructions analyzed as break instructions to
69286989 // the block_inst above. Here we are performing "comptime/inline semantic analysis"
......@@ -6934,59 +6995,46 @@ fn analyzeCall(
69346995 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body);
69356996
69366997 var has_comptime_args = false;
6937 var arg_i: usize = 0;
6998 var arg_i: u32 = 0;
69386999 for (fn_info.param_body) |inst| {
6939 sema.analyzeInlineCallArg(
7000 const arg_src: LazySrcLoc = if (arg_i == 0 and bound_arg_src != null)
7001 bound_arg_src.?
7002 else
7003 .{ .call_arg = .{
7004 .decl = block.src_decl,
7005 .call_node_offset = call_src.node_offset.x,
7006 .arg_index = arg_i - @intFromBool(bound_arg_src != null),
7007 } };
7008 try sema.analyzeInlineCallArg(
69407009 block,
69417010 &child_block,
6942 .unneeded,
7011 arg_src,
69437012 inst,
6944 &new_fn_info,
7013 new_fn_info.param_types,
69457014 &arg_i,
69467015 uncasted_args,
69477016 is_comptime_call,
69487017 &should_memoize,
69497018 memoized_arg_values,
6950 mod.typeToFunc(func_ty).?.param_types,
7019 func_ty_info.param_types,
69517020 func,
69527021 &has_comptime_args,
6953 ) catch |err| switch (err) {
6954 error.NeededSourceLocation => {
6955 _ = sema.inst_map.remove(inst);
6956 const decl = mod.declPtr(block.src_decl);
6957 try sema.analyzeInlineCallArg(
6958 block,
6959 &child_block,
6960 mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src),
6961 inst,
6962 &new_fn_info,
6963 &arg_i,
6964 uncasted_args,
6965 is_comptime_call,
6966 &should_memoize,
6967 memoized_arg_values,
6968 mod.typeToFunc(func_ty).?.param_types,
6969 func,
6970 &has_comptime_args,
6971 );
6972 unreachable;
6973 },
6974 else => |e| return e,
6975 };
7022 );
69767023 }
69777024
6978 if (!has_comptime_args and module_fn.state == .sema_failure) return error.AnalysisFail;
7025 if (!has_comptime_args and module_fn.analysis(ip).state == .sema_failure)
7026 return error.AnalysisFail;
69797027
69807028 const recursive_msg = "inline call is recursive";
69817029 var head = if (!has_comptime_args) block else null;
69827030 while (head) |some| {
69837031 const parent_inlining = some.inlining orelse break;
6984 if (parent_inlining.func == module_fn) {
7032 if (parent_inlining.func == module_fn_index) {
69857033 return sema.fail(block, call_src, recursive_msg, .{});
69867034 }
69877035 head = some.parent;
69887036 }
6989 if (!has_comptime_args) inlining.func = module_fn;
7037 if (!has_comptime_args) inlining.func = module_fn_index;
69907038
69917039 // In case it is a generic function with an expression for the return type that depends
69927040 // on parameters, we must now do the same for the return type as we just did with
......@@ -6998,21 +7046,32 @@ fn analyzeCall(
69987046 try sema.resolveInst(fn_info.ret_ty_ref);
69997047 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
70007048 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
7001 // Create a fresh inferred error set type for inline/comptime calls.
7002 const fn_ret_ty = blk: {
7003 if (module_fn.hasInferredErrorSet(mod)) {
7004 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
7005 .func = module_fn_index,
7006 });
7007 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
7008 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
7009 }
7010 break :blk bare_return_type;
7011 };
7012 new_fn_info.return_type = fn_ret_ty.toIntern();
70137049 const parent_fn_ret_ty = sema.fn_ret_ty;
7014 sema.fn_ret_ty = fn_ret_ty;
7050 const parent_fn_ret_ty_ies = sema.fn_ret_ty_ies;
7051 const parent_generic_owner = sema.generic_owner;
7052 const parent_generic_call_src = sema.generic_call_src;
7053 const parent_generic_call_decl = sema.generic_call_decl;
7054 sema.fn_ret_ty = bare_return_type;
7055 sema.fn_ret_ty_ies = null;
7056 sema.generic_owner = .none;
7057 sema.generic_call_src = .unneeded;
7058 sema.generic_call_decl = .none;
70157059 defer sema.fn_ret_ty = parent_fn_ret_ty;
7060 defer sema.fn_ret_ty_ies = parent_fn_ret_ty_ies;
7061 defer sema.generic_owner = parent_generic_owner;
7062 defer sema.generic_call_src = parent_generic_call_src;
7063 defer sema.generic_call_decl = parent_generic_call_decl;
7064
7065 if (module_fn.analysis(ip).inferred_error_set) {
7066 // Create a fresh inferred error set type for inline/comptime calls.
7067 const ies = try sema.arena.create(InferredErrorSet);
7068 ies.* = .{ .func = .none };
7069 sema.fn_ret_ty_ies = ies;
7070 sema.fn_ret_ty = (try ip.get(gpa, .{ .error_union_type = .{
7071 .error_set_type = .adhoc_inferred_error_set_type,
7072 .payload_type = bare_return_type.toIntern(),
7073 } })).toType();
7074 }
70167075
70177076 // This `res2` is here instead of directly breaking from `res` due to a stage1
70187077 // bug generating invalid LLVM IR.
......@@ -7030,9 +7089,10 @@ fn analyzeCall(
70307089 }
70317090 }
70327091
7092 new_fn_info.return_type = sema.fn_ret_ty.toIntern();
70337093 const new_func_resolved_ty = try mod.funcType(new_fn_info);
70347094 if (!is_comptime_call and !block.is_typeof) {
7035 try sema.emitDbgInline(block, parent_func_index.unwrap().?, module_fn_index, new_func_resolved_ty, .dbg_inline_begin);
7095 try sema.emitDbgInline(block, parent_func_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin);
70367096
70377097 const zir_tags = sema.code.instructions.items(.tag);
70387098 for (fn_info.param_body) |param| switch (zir_tags[param]) {
......@@ -7056,7 +7116,7 @@ fn analyzeCall(
70567116 }
70577117
70587118 if (is_comptime_call and ensure_result_used) {
7059 try sema.ensureResultUsed(block, fn_ret_ty, call_src);
7119 try sema.ensureResultUsed(block, sema.fn_ret_ty, call_src);
70607120 }
70617121
70627122 const result = result: {
......@@ -7074,26 +7134,47 @@ fn analyzeCall(
70747134 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);
70757135 };
70767136
7077 if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag(mod) != .NoReturn) {
7137 if (!is_comptime_call and !block.is_typeof and
7138 sema.typeOf(result).zigTypeTag(mod) != .NoReturn)
7139 {
70787140 try sema.emitDbgInline(
70797141 block,
70807142 module_fn_index,
7081 parent_func_index.unwrap().?,
7082 mod.declPtr(parent_func.?.owner_decl).ty,
7143 parent_func_index,
7144 mod.funcOwnerDeclPtr(parent_func_index).ty,
70837145 .dbg_inline_end,
70847146 );
70857147 }
70867148
70877149 if (should_memoize and is_comptime_call) {
70887150 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");
7151 const result_interned = try result_val.intern2(sema.fn_ret_ty, mod);
7152
7153 // Transform ad-hoc inferred error set types into concrete error sets.
7154 const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned);
70897155
70907156 // TODO: check whether any external comptime memory was mutated by the
70917157 // comptime function call. If so, then do not memoize the call here.
70927158 _ = try mod.intern(.{ .memoized_call = .{
70937159 .func = module_fn_index,
70947160 .arg_values = memoized_arg_values,
7095 .result = try result_val.intern(fn_ret_ty, mod),
7161 .result = result_transformed,
70967162 } });
7163
7164 break :res2 Air.internedToRef(result_transformed);
7165 }
7166
7167 if (try sema.resolveMaybeUndefVal(result)) |result_val| {
7168 const result_interned = try result_val.intern2(sema.fn_ret_ty, mod);
7169 const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned);
7170 break :res2 Air.internedToRef(result_transformed);
7171 }
7172
7173 const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern());
7174 if (new_ty != .none) {
7175 // TODO: mutate in place the previous instruction if possible
7176 // rather than adding a bitcast instruction.
7177 break :res2 try block.addBitCast(new_ty.toType(), result);
70977178 }
70987179
70997180 break :res2 result;
......@@ -7110,9 +7191,9 @@ fn analyzeCall(
71107191 if (i < fn_params_len) {
71117192 const opts: CoerceOpts = .{ .param_src = .{
71127193 .func_inst = func,
7113 .param_i = @as(u32, @intCast(i)),
7194 .param_i = @intCast(i),
71147195 } };
7115 const param_ty = mod.typeToFunc(func_ty).?.param_types[i].toType();
7196 const param_ty = func_ty_info.param_types.get(ip)[i].toType();
71167197 args[i] = sema.analyzeCallArg(
71177198 block,
71187199 .unneeded,
......@@ -7152,13 +7233,13 @@ fn analyzeCall(
71527233 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
71537234
71547235 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7155 if (sema.owner_func != null and func_ty_info.return_type.toType().isError(mod)) {
7156 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
7236 if (sema.owner_func_index != .none and func_ty_info.return_type.toType().isError(mod)) {
7237 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
71577238 }
71587239
71597240 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7160 if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| {
7161 try mod.ensureFuncBodyAnalysisQueued(func_index);
7241 if (mod.intern_pool.isFuncBody(func_val.toIntern())) {
7242 try mod.ensureFuncBodyAnalysisQueued(func_val.toIntern());
71627243 }
71637244 }
71647245
......@@ -7219,7 +7300,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
72197300 @tagName(backend), @tagName(target.cpu.arch),
72207301 });
72217302 }
7222 const func_decl = mod.declPtr(sema.owner_func.?.owner_decl);
7303 const func_decl = mod.funcOwnerDeclPtr(sema.owner_func_index);
72237304 if (!func_ty.eql(func_decl.ty, mod)) {
72247305 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{
72257306 func_ty.fmt(mod), func_decl.ty.fmt(mod),
......@@ -7235,17 +7316,18 @@ fn analyzeInlineCallArg(
72357316 param_block: *Block,
72367317 arg_src: LazySrcLoc,
72377318 inst: Zir.Inst.Index,
7238 new_fn_info: *InternPool.Key.FuncType,
7239 arg_i: *usize,
7319 new_param_types: []InternPool.Index,
7320 arg_i: *u32,
72407321 uncasted_args: []const Air.Inst.Ref,
72417322 is_comptime_call: bool,
72427323 should_memoize: *bool,
72437324 memoized_arg_values: []InternPool.Index,
7244 raw_param_types: []const InternPool.Index,
7325 raw_param_types: InternPool.Index.Slice,
72457326 func_inst: Air.Inst.Ref,
72467327 has_comptime_args: *bool,
72477328) !void {
72487329 const mod = sema.mod;
7330 const ip = &mod.intern_pool;
72497331 const zir_tags = sema.code.instructions.items(.tag);
72507332 switch (zir_tags[inst]) {
72517333 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
......@@ -7260,13 +7342,13 @@ fn analyzeInlineCallArg(
72607342 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);
72617343 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
72627344 const param_ty = param_ty: {
7263 const raw_param_ty = raw_param_types[arg_i.*];
7345 const raw_param_ty = raw_param_types.get(ip)[arg_i.*];
72647346 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;
72657347 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
72667348 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
72677349 break :param_ty param_ty.toIntern();
72687350 };
7269 new_fn_info.param_types[arg_i.*] = param_ty;
7351 new_param_types[arg_i.*] = param_ty;
72707352 const uncasted_arg = uncasted_args[arg_i.*];
72717353 if (try sema.typeRequiresComptime(param_ty.toType())) {
72727354 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {
......@@ -7278,7 +7360,7 @@ fn analyzeInlineCallArg(
72787360 }
72797361 const casted_arg = sema.coerceExtra(arg_block, param_ty.toType(), uncasted_arg, arg_src, .{ .param_src = .{
72807362 .func_inst = func_inst,
7281 .param_i = @as(u32, @intCast(arg_i.*)),
7363 .param_i = @intCast(arg_i.*),
72827364 } }) catch |err| switch (err) {
72837365 error.NotCoercible => unreachable,
72847366 else => |e| return e,
......@@ -7317,7 +7399,7 @@ fn analyzeInlineCallArg(
73177399 .param_anytype, .param_anytype_comptime => {
73187400 // No coercion needed.
73197401 const uncasted_arg = uncasted_args[arg_i.*];
7320 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern();
7402 new_param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern();
73217403
73227404 if (is_comptime_call) {
73237405 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
......@@ -7371,50 +7453,12 @@ fn analyzeCallArg(
73717453 };
73727454}
73737455
7374fn analyzeGenericCallArg(
7375 sema: *Sema,
7376 block: *Block,
7377 arg_src: LazySrcLoc,
7378 uncasted_arg: Air.Inst.Ref,
7379 comptime_arg: TypedValue,
7380 runtime_args: []Air.Inst.Ref,
7381 new_fn_info: InternPool.Key.FuncType,
7382 runtime_i: *u32,
7383) !void {
7384 const mod = sema.mod;
7385 const is_runtime = comptime_arg.val.isGenericPoison() and
7386 comptime_arg.ty.hasRuntimeBits(mod) and
7387 !(try sema.typeRequiresComptime(comptime_arg.ty));
7388 if (is_runtime) {
7389 const param_ty = new_fn_info.param_types[runtime_i.*].toType();
7390 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
7391 try sema.queueFullTypeResolution(param_ty);
7392 runtime_args[runtime_i.*] = casted_arg;
7393 runtime_i.* += 1;
7394 } else if (try sema.typeHasOnePossibleValue(comptime_arg.ty)) |_| {
7395 _ = try sema.coerce(block, comptime_arg.ty, uncasted_arg, arg_src);
7396 }
7397}
7398
7399fn analyzeGenericCallArgVal(
7400 sema: *Sema,
7401 block: *Block,
7402 arg_src: LazySrcLoc,
7403 arg_ty: Type,
7404 uncasted_arg: Air.Inst.Ref,
7405 reason: []const u8,
7406) !Value {
7407 const casted_arg = try sema.coerce(block, arg_ty, uncasted_arg, arg_src);
7408 return sema.resolveLazyValue(try sema.resolveValue(block, arg_src, casted_arg, reason));
7409}
7410
74117456fn instantiateGenericCall(
74127457 sema: *Sema,
74137458 block: *Block,
74147459 func: Air.Inst.Ref,
74157460 func_src: LazySrcLoc,
74167461 call_src: LazySrcLoc,
7417 generic_func_ty: Type,
74187462 ensure_result_used: bool,
74197463 uncasted_args: []const Air.Inst.Ref,
74207464 call_tag: Air.Inst.Tag,
......@@ -7423,299 +7467,32 @@ fn instantiateGenericCall(
74237467) CompileError!Air.Inst.Ref {
74247468 const mod = sema.mod;
74257469 const gpa = sema.gpa;
7470 const ip = &mod.intern_pool;
74267471
74277472 const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");
7428 const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7429 .func => |function| function.index,
7430 .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.getFunctionIndex(mod).unwrap().?,
7473 const generic_owner = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7474 .func => func_val.toIntern(),
7475 .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.toIntern(),
74317476 else => unreachable,
74327477 };
7433 const module_fn = mod.funcPtr(module_fn_index);
7434 // Check the Module's generic function map with an adapted context, so that we
7435 // can match against `uncasted_args` rather than doing the work below to create a
7436 // generic Scope only to junk it if it matches an existing instantiation.
7437 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
7478 const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func;
7479
7480 // Even though there may already be a generic instantiation corresponding
7481 // to this callsite, we must evaluate the expressions of the generic
7482 // function signature with the values of the callsite plugged in.
7483 // Importantly, this may include type coercions that determine whether the
7484 // instantiation is a match of a previous instantiation.
7485 // The actual monomorphization happens via adding `func_instance` to
7486 // `InternPool`.
7487
7488 const fn_owner_decl = mod.declPtr(generic_owner_func.owner_decl);
74387489 const namespace_index = fn_owner_decl.src_namespace;
74397490 const namespace = mod.namespacePtr(namespace_index);
74407491 const fn_zir = namespace.file_scope.zir;
7441 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
7442 const zir_tags = fn_zir.instructions.items(.tag);
7443
7444 const monomorphed_args = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(generic_func_ty).?.param_types.len);
7445 const callee_index = callee: {
7446 var arg_i: usize = 0;
7447 var monomorphed_arg_i: u32 = 0;
7448 var known_unique = false;
7449 for (fn_info.param_body) |inst| {
7450 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
7451 var is_comptime = false;
7452 var is_anytype = false;
7453 switch (zir_tags[inst]) {
7454 .param => {
7455 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7456 },
7457 .param_comptime => {
7458 is_comptime = true;
7459 },
7460 .param_anytype => {
7461 is_anytype = true;
7462 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7463 },
7464 .param_anytype_comptime => {
7465 is_anytype = true;
7466 is_comptime = true;
7467 },
7468 else => continue,
7469 }
7470
7471 defer arg_i += 1;
7472 const param_ty = generic_func_ty_info.param_types[arg_i];
7473 const is_generic = !is_anytype and param_ty == .generic_poison_type;
7492 const fn_info = fn_zir.getFnInfo(generic_owner_func.zir_body_inst);
74747493
7475 if (known_unique) {
7476 if (is_comptime or is_anytype or is_generic) {
7477 monomorphed_arg_i += 1;
7478 }
7479 continue;
7480 }
7481
7482 const uncasted_arg = uncasted_args[arg_i];
7483 const arg_ty = if (is_generic) mod.monomorphed_funcs.getAdapted(
7484 Module.MonomorphedFuncAdaptedKey{
7485 .func = module_fn_index,
7486 .args = monomorphed_args[0..monomorphed_arg_i],
7487 },
7488 Module.MonomorphedFuncsAdaptedContext{ .mod = mod },
7489 ) orelse {
7490 known_unique = true;
7491 monomorphed_arg_i += 1;
7492 continue;
7493 } else if (is_anytype) sema.typeOf(uncasted_arg).toIntern() else param_ty;
7494 const was_comptime = is_comptime;
7495 if (!is_comptime and try sema.typeRequiresComptime(arg_ty.toType())) is_comptime = true;
7496 if (is_comptime or is_anytype) {
7497 // Tuple default values are a part of the type and need to be
7498 // resolved to hash the type.
7499 try sema.resolveTupleLazyValues(block, call_src, arg_ty.toType());
7500 }
7501
7502 if (is_comptime) {
7503 const casted_arg = sema.analyzeGenericCallArgVal(block, .unneeded, arg_ty.toType(), uncasted_arg, "") catch |err| switch (err) {
7504 error.NeededSourceLocation => {
7505 const decl = mod.declPtr(block.src_decl);
7506 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7507 _ = try sema.analyzeGenericCallArgVal(
7508 block,
7509 arg_src,
7510 arg_ty.toType(),
7511 uncasted_arg,
7512 if (was_comptime)
7513 "parameter is comptime"
7514 else
7515 "argument to parameter with comptime-only type must be comptime-known",
7516 );
7517 unreachable;
7518 },
7519 else => |e| return e,
7520 };
7521 monomorphed_args[monomorphed_arg_i] = casted_arg.toIntern();
7522 monomorphed_arg_i += 1;
7523 } else if (is_anytype or is_generic) {
7524 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty });
7525 monomorphed_arg_i += 1;
7526 }
7527 }
7528
7529 if (!known_unique) {
7530 if (mod.monomorphed_funcs.getAdapted(
7531 Module.MonomorphedFuncAdaptedKey{
7532 .func = module_fn_index,
7533 .args = monomorphed_args[0..monomorphed_arg_i],
7534 },
7535 Module.MonomorphedFuncsAdaptedContext{ .mod = mod },
7536 )) |callee_func| break :callee mod.intern_pool.indexToKey(callee_func).func.index;
7537 }
7538
7539 const new_module_func_index = try mod.createFunc(undefined);
7540 const new_module_func = mod.funcPtr(new_module_func_index);
7541
7542 new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();
7543 new_module_func.comptime_args = null;
7544
7545 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
7546
7547 // Create a Decl for the new function.
7548 const src_decl_index = namespace.getDeclIndex(mod);
7549 const src_decl = mod.declPtr(src_decl_index);
7550 const new_decl_index = try mod.allocateNewDecl(namespace_index, fn_owner_decl.src_node, src_decl.src_scope);
7551 const new_decl = mod.declPtr(new_decl_index);
7552 // TODO better names for generic function instantiations
7553 const decl_name = try mod.intern_pool.getOrPutStringFmt(gpa, "{}__anon_{d}", .{
7554 fn_owner_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index),
7555 });
7556 new_decl.name = decl_name;
7557 new_decl.src_line = fn_owner_decl.src_line;
7558 new_decl.is_pub = fn_owner_decl.is_pub;
7559 new_decl.is_exported = fn_owner_decl.is_exported;
7560 new_decl.has_align = fn_owner_decl.has_align;
7561 new_decl.has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace;
7562 new_decl.@"linksection" = fn_owner_decl.@"linksection";
7563 new_decl.@"addrspace" = fn_owner_decl.@"addrspace";
7564 new_decl.zir_decl_index = fn_owner_decl.zir_decl_index;
7565 new_decl.alive = true; // This Decl is called at runtime.
7566 new_decl.analysis = .in_progress;
7567 new_decl.generation = mod.generation;
7568
7569 namespace.anon_decls.putAssumeCapacityNoClobber(new_decl_index, {});
7570
7571 // The generic function Decl is guaranteed to be the first dependency
7572 // of each of its instantiations.
7573 assert(new_decl.dependencies.keys().len == 0);
7574 try mod.declareDeclDependencyType(new_decl_index, module_fn.owner_decl, .function_body);
7575
7576 const new_func = sema.resolveGenericInstantiationType(
7577 block,
7578 fn_zir,
7579 new_decl,
7580 new_decl_index,
7581 uncasted_args,
7582 monomorphed_arg_i,
7583 module_fn_index,
7584 new_module_func_index,
7585 namespace_index,
7586 generic_func_ty,
7587 call_src,
7588 bound_arg_src,
7589 ) catch |err| switch (err) {
7590 error.GenericPoison, error.ComptimeReturn => {
7591 // Resolving the new function type below will possibly declare more decl dependencies
7592 // and so we remove them all here in case of error.
7593 for (new_decl.dependencies.keys()) |dep_index| {
7594 const dep = mod.declPtr(dep_index);
7595 dep.removeDependant(new_decl_index);
7596 }
7597 assert(namespace.anon_decls.orderedRemove(new_decl_index));
7598 mod.destroyDecl(new_decl_index);
7599 mod.destroyFunc(new_module_func_index);
7600 return err;
7601 },
7602 else => {
7603 // TODO look up the compile error that happened here and attach a note to it
7604 // pointing here, at the generic instantiation callsite.
7605 if (sema.owner_func) |owner_func| {
7606 owner_func.state = .dependency_failure;
7607 } else {
7608 sema.owner_decl.analysis = .dependency_failure;
7609 }
7610 return err;
7611 },
7612 };
7613
7614 break :callee new_func;
7615 };
7616 const callee = mod.funcPtr(callee_index);
7617 callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);
7618
7619 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);
7620
7621 // Make a runtime call to the new function, making sure to omit the comptime args.
7622 const comptime_args = callee.comptime_args.?;
7623 const func_ty = mod.declPtr(callee.owner_decl).ty;
7624 const runtime_args_len = @as(u32, @intCast(mod.typeToFunc(func_ty).?.param_types.len));
7625 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
7626 {
7627 var runtime_i: u32 = 0;
7628 var total_i: u32 = 0;
7629 for (fn_info.param_body) |inst| {
7630 switch (zir_tags[inst]) {
7631 .param_comptime, .param_anytype_comptime, .param, .param_anytype => {},
7632 else => continue,
7633 }
7634 sema.analyzeGenericCallArg(
7635 block,
7636 .unneeded,
7637 uncasted_args[total_i],
7638 comptime_args[total_i],
7639 runtime_args,
7640 mod.typeToFunc(func_ty).?,
7641 &runtime_i,
7642 ) catch |err| switch (err) {
7643 error.NeededSourceLocation => {
7644 const decl = mod.declPtr(block.src_decl);
7645 _ = try sema.analyzeGenericCallArg(
7646 block,
7647 mod.argSrc(call_src.node_offset.x, decl, total_i, bound_arg_src),
7648 uncasted_args[total_i],
7649 comptime_args[total_i],
7650 runtime_args,
7651 mod.typeToFunc(func_ty).?,
7652 &runtime_i,
7653 );
7654 unreachable;
7655 },
7656 else => |e| return e,
7657 };
7658 total_i += 1;
7659 }
7660
7661 try sema.queueFullTypeResolution(mod.typeToFunc(func_ty).?.return_type.toType());
7662 }
7663
7664 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
7665
7666 if (sema.owner_func != null and mod.typeToFunc(func_ty).?.return_type.toType().isError(mod)) {
7667 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
7668 }
7669
7670 try mod.ensureFuncBodyAnalysisQueued(callee_index);
7671
7672 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
7673 runtime_args_len);
7674 const result = try block.addInst(.{
7675 .tag = call_tag,
7676 .data = .{ .pl_op = .{
7677 .operand = callee_inst,
7678 .payload = sema.addExtraAssumeCapacity(Air.Call{
7679 .args_len = runtime_args_len,
7680 }),
7681 } },
7682 });
7683 sema.appendRefsAssumeCapacity(runtime_args);
7684
7685 if (ensure_result_used) {
7686 try sema.ensureResultUsed(block, sema.typeOf(result), call_src);
7687 }
7688 if (call_tag == .call_always_tail) {
7689 return sema.handleTailCall(block, call_src, func_ty, result);
7690 }
7691 if (func_ty.fnReturnType(mod).isNoReturn(mod)) {
7692 _ = try block.addNoOp(.unreach);
7693 return Air.Inst.Ref.unreachable_value;
7694 }
7695 return result;
7696}
7697
7698fn resolveGenericInstantiationType(
7699 sema: *Sema,
7700 block: *Block,
7701 fn_zir: Zir,
7702 new_decl: *Decl,
7703 new_decl_index: Decl.Index,
7704 uncasted_args: []const Air.Inst.Ref,
7705 monomorphed_args_len: u32,
7706 module_fn_index: Module.Fn.Index,
7707 new_module_func: Module.Fn.Index,
7708 namespace: Namespace.Index,
7709 generic_func_ty: Type,
7710 call_src: LazySrcLoc,
7711 bound_arg_src: ?LazySrcLoc,
7712) !Module.Fn.Index {
7713 const mod = sema.mod;
7714 const gpa = sema.gpa;
7715
7716 const zir_tags = fn_zir.instructions.items(.tag);
7717 const module_fn = mod.funcPtr(module_fn_index);
7718 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
7494 const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len);
7495 @memset(comptime_args, .none);
77197496
77207497 // Re-run the block that creates the function, with the comptime parameters
77217498 // pre-populated inside `inst_map`. This causes `param_comptime` and
......@@ -7726,205 +7503,145 @@ fn resolveGenericInstantiationType(
77267503 .gpa = gpa,
77277504 .arena = sema.arena,
77287505 .code = fn_zir,
7729 .owner_decl = new_decl,
7730 .owner_decl_index = new_decl_index,
7731 .func = null,
7732 .func_index = .none,
7506 // We pass the generic callsite's owner decl here because whatever `Decl`
7507 // dependencies are chased at this point should be attached to the
7508 // callsite, not the `Decl` associated with the `func_instance`.
7509 .owner_decl = sema.owner_decl,
7510 .owner_decl_index = sema.owner_decl_index,
7511 .func_index = sema.owner_func_index,
77337512 .fn_ret_ty = Type.void,
7734 .owner_func = null,
7513 .fn_ret_ty_ies = null,
77357514 .owner_func_index = .none,
7736 // TODO: fully migrate functions into InternPool
7737 .comptime_args = try mod.tmp_hack_arena.allocator().alloc(TypedValue, uncasted_args.len),
7738 .comptime_args_fn_inst = module_fn.zir_body_inst,
7739 .preallocated_new_func = new_module_func.toOptional(),
7740 .is_generic_instantiation = true,
7515 .comptime_args = comptime_args,
7516 .generic_owner = generic_owner,
7517 .generic_call_src = call_src,
7518 .generic_call_decl = block.src_decl.toOptional(),
77417519 .branch_quota = sema.branch_quota,
77427520 .branch_count = sema.branch_count,
77437521 .comptime_mutable_decls = sema.comptime_mutable_decls,
77447522 };
77457523 defer child_sema.deinit();
77467524
7747 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);
7525 var wip_captures = try WipCaptureScope.init(gpa, sema.owner_decl.src_scope);
77487526 defer wip_captures.deinit();
77497527
77507528 var child_block: Block = .{
77517529 .parent = null,
77527530 .sema = &child_sema,
7753 .src_decl = new_decl_index,
7754 .namespace = namespace,
7531 .src_decl = generic_owner_func.owner_decl,
7532 .namespace = namespace_index,
77557533 .wip_capture_scope = wip_captures.scope,
77567534 .instructions = .{},
77577535 .inlining = null,
77587536 .is_comptime = true,
77597537 };
7760 defer {
7761 child_block.instructions.deinit(gpa);
7762 child_block.params.deinit(gpa);
7763 }
7538 defer child_block.instructions.deinit(gpa);
77647539
77657540 try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
77667541
7767 var arg_i: usize = 0;
7768 for (fn_info.param_body) |inst| {
7769 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
7770 var is_comptime = false;
7771 var is_anytype = false;
7772 switch (zir_tags[inst]) {
7773 .param => {
7774 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7775 },
7776 .param_comptime => {
7777 is_comptime = true;
7778 },
7779 .param_anytype => {
7780 is_anytype = true;
7781 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7782 },
7783 .param_anytype_comptime => {
7784 is_anytype = true;
7785 is_comptime = true;
7786 },
7787 else => continue,
7788 }
7789 const arg = uncasted_args[arg_i];
7790 if (is_comptime) {
7791 const arg_val = (try sema.resolveMaybeUndefVal(arg)).?;
7792 const child_arg = try child_sema.addConstant(arg_val);
7793 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7794 } else if (is_anytype) {
7795 const arg_ty = sema.typeOf(arg);
7796 if (try sema.typeRequiresComptime(arg_ty)) {
7797 const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) {
7798 error.NeededSourceLocation => {
7799 const decl = mod.declPtr(block.src_decl);
7800 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7801 _ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known");
7802 unreachable;
7803 },
7804 else => |e| return e,
7805 };
7806 const child_arg = try child_sema.addConstant(arg_val);
7807 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7808 } else {
7809 // We insert into the map an instruction which is runtime-known
7810 // but has the type of the argument.
7811 const child_arg = try child_block.addInst(.{
7812 .tag = .arg,
7813 .data = .{ .arg = .{
7814 .ty = try child_sema.addType(arg_ty),
7815 .src_index = @as(u32, @intCast(arg_i)),
7816 } },
7817 });
7818 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7819 }
7820 }
7821 arg_i += 1;
7542 for (fn_info.param_body[0..uncasted_args.len], uncasted_args, 0..) |inst, arg, i| {
7543 // `child_sema` will use a different `inst_map` which means we have to
7544 // convert from parent-relative `Air.Inst.Ref` to child-relative here.
7545 // Constants are simple; runtime-known values need a new instruction.
7546 child_sema.inst_map.putAssumeCapacityNoClobber(inst, if (try sema.resolveMaybeUndefVal(arg)) |val|
7547 Air.internedToRef(val.toIntern())
7548 else
7549 // We insert into the map an instruction which is runtime-known
7550 // but has the type of the argument.
7551 try child_block.addInst(.{
7552 .tag = .arg,
7553 .data = .{ .arg = .{
7554 .ty = Air.internedToRef(sema.typeOf(arg).toIntern()),
7555 .src_index = @intCast(i),
7556 } },
7557 }));
78227558 }
78237559
7824 // Save the error trace as our first action in the function.
7825 // If this is unnecessary after all, Liveness will clean it up for us.
7826 const error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block);
7827 child_sema.error_return_trace_index_on_fn_entry = error_return_trace_index;
7828 child_block.error_return_trace_index = error_return_trace_index;
7829
78307560 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
7831 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;
7832 const new_func = new_func_val.getFunctionIndex(mod).unwrap().?;
7833 assert(new_func == new_module_func);
7834
7835 const monomorphed_args_index = @as(u32, @intCast(mod.monomorphed_func_keys.items.len));
7836 const monomorphed_args = try mod.monomorphed_func_keys.addManyAsSlice(gpa, monomorphed_args_len);
7837 var monomorphed_arg_i: u32 = 0;
7838 try mod.monomorphed_funcs.ensureUnusedCapacityContext(gpa, monomorphed_args_len + 1, .{ .mod = mod });
7839
7840 arg_i = 0;
7841 for (fn_info.param_body) |inst| {
7842 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
7843 var is_comptime = false;
7844 var is_anytype = false;
7845 switch (zir_tags[inst]) {
7846 .param => {
7847 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7848 },
7849 .param_comptime => {
7850 is_comptime = true;
7851 },
7852 .param_anytype => {
7853 is_anytype = true;
7854 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7855 },
7856 .param_anytype_comptime => {
7857 is_anytype = true;
7858 is_comptime = true;
7859 },
7860 else => continue,
7861 }
7862
7863 const param_ty = generic_func_ty_info.param_types[arg_i];
7864 const is_generic = !is_anytype and param_ty == .generic_poison_type;
7561 const callee_index = (child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern();
78657562
7866 const arg = child_sema.inst_map.get(inst).?;
7867 const arg_ty = child_sema.typeOf(arg);
7868
7869 if (is_generic) if (mod.monomorphed_funcs.fetchPutAssumeCapacityContext(.{
7870 .func = module_fn_index,
7871 .args_index = monomorphed_args_index,
7872 .args_len = monomorphed_arg_i,
7873 }, arg_ty.toIntern(), .{ .mod = mod })) |kv| assert(kv.value == arg_ty.toIntern());
7874 if (!is_comptime and try sema.typeRequiresComptime(arg_ty)) is_comptime = true;
7875
7876 if (is_comptime) {
7877 const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?;
7878 monomorphed_args[monomorphed_arg_i] = arg_val.toIntern();
7879 monomorphed_arg_i += 1;
7880 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = arg_val };
7881 } else {
7882 if (is_anytype or is_generic) {
7883 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty.toIntern() });
7884 monomorphed_arg_i += 1;
7885 }
7886 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = Value.generic_poison };
7887 }
7563 const callee = mod.funcInfo(callee_index);
7564 callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota);
78887565
7889 arg_i += 1;
7890 }
7566 // Make a runtime call to the new function, making sure to omit the comptime args.
7567 const func_ty = callee.ty.toType();
7568 const func_ty_info = mod.typeToFunc(func_ty).?;
78917569
78927570 try wip_captures.finalize();
78937571
7894 // Populate the Decl ty/val with the function and its type.
7895 new_decl.ty = child_sema.typeOf(new_func_inst);
78967572 // If the call evaluated to a return type that requires comptime, never mind
78977573 // our generic instantiation. Instead we need to perform a comptime call.
7898 const new_fn_info = mod.typeToFunc(new_decl.ty).?;
7899 if (try sema.typeRequiresComptime(new_fn_info.return_type.toType())) {
7574 if (try sema.typeRequiresComptime(func_ty_info.return_type.toType())) {
79007575 return error.ComptimeReturn;
79017576 }
79027577 // Similarly, if the call evaluated to a generic type we need to instead
79037578 // call it inline.
7904 if (new_fn_info.is_generic or new_fn_info.cc == .Inline) {
7579 if (func_ty_info.is_generic or func_ty_info.cc == .Inline) {
79057580 return error.GenericPoison;
79067581 }
79077582
7908 new_decl.val = (try mod.intern(.{ .func = .{
7909 .ty = new_decl.ty.toIntern(),
7910 .index = new_func,
7911 } })).toValue();
7912 new_decl.alignment = .none;
7913 new_decl.has_tv = true;
7914 new_decl.owns_tv = true;
7915 new_decl.analysis = .complete;
7583 const runtime_args_len: u32 = func_ty_info.param_types.len;
7584 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
7585 {
7586 var runtime_i: u32 = 0;
7587 for (uncasted_args, 0..) |uncasted_arg, total_i| {
7588 // In the case of a function call generated by the language, the LazySrcLoc
7589 // provided for `call_src` may not point to anything interesting.
7590 const arg_src: LazySrcLoc = if (total_i == 0 and bound_arg_src != null)
7591 bound_arg_src.?
7592 else if (call_src == .node_offset) .{ .call_arg = .{
7593 .decl = block.src_decl,
7594 .call_node_offset = call_src.node_offset.x,
7595 .arg_index = @intCast(total_i),
7596 } } else .unneeded;
7597
7598 const comptime_arg = callee.comptime_args.get(ip)[total_i];
7599 if (comptime_arg == .none) {
7600 const param_ty = func_ty_info.param_types.get(ip)[runtime_i].toType();
7601 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
7602 try sema.queueFullTypeResolution(param_ty);
7603 runtime_args[runtime_i] = casted_arg;
7604 runtime_i += 1;
7605 }
7606 }
7607
7608 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7609 }
7610
7611 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
79167612
7917 mod.monomorphed_funcs.putAssumeCapacityNoClobberContext(.{
7918 .func = module_fn_index,
7919 .args_index = monomorphed_args_index,
7920 .args_len = monomorphed_arg_i,
7921 }, new_decl.val.toIntern(), .{ .mod = mod });
7613 if (sema.owner_func_index != .none and
7614 func_ty_info.return_type.toType().isError(mod))
7615 {
7616 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
7617 }
7618
7619 try mod.ensureFuncBodyAnalysisQueued(callee_index);
79227620
7923 // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field
7924 // will be populated, ensuring it will have `analyzeBody` called with the ZIR
7925 // parameters mapped appropriately.
7926 try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func });
7927 return new_func;
7621 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
7622 runtime_args_len);
7623 const result = try block.addInst(.{
7624 .tag = call_tag,
7625 .data = .{ .pl_op = .{
7626 .operand = Air.internedToRef(callee_index),
7627 .payload = sema.addExtraAssumeCapacity(Air.Call{
7628 .args_len = runtime_args_len,
7629 }),
7630 } },
7631 });
7632 sema.appendRefsAssumeCapacity(runtime_args);
7633
7634 if (ensure_result_used) {
7635 try sema.ensureResultUsed(block, sema.typeOf(result), call_src);
7636 }
7637 if (call_tag == .call_always_tail) {
7638 return sema.handleTailCall(block, call_src, func_ty, result);
7639 }
7640 if (func_ty.fnReturnType(mod).isNoReturn(mod)) {
7641 _ = try block.addNoOp(.unreach);
7642 return Air.Inst.Ref.unreachable_value;
7643 }
7644 return result;
79287645}
79297646
79307647fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
......@@ -7944,8 +7661,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
79447661fn emitDbgInline(
79457662 sema: *Sema,
79467663 block: *Block,
7947 old_func: Module.Fn.Index,
7948 new_func: Module.Fn.Index,
7664 old_func: InternPool.Index,
7665 new_func: InternPool.Index,
79497666 new_func_ty: Type,
79507667 tag: Air.Inst.Tag,
79517668) CompileError!void {
......@@ -8149,6 +7866,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
81497866 defer tracy.end();
81507867
81517868 const mod = sema.mod;
7869 const ip = &mod.intern_pool;
81527870 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
81537871 const src = LazySrcLoc.nodeOffset(extra.node);
81547872 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
......@@ -8159,7 +7877,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
81597877 if (val.isUndef(mod)) {
81607878 return sema.addConstUndef(Type.err_int);
81617879 }
8162 const err_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
7880 const err_name = ip.indexToKey(val.toIntern()).err.name;
81637881 return sema.addConstant(try mod.intValue(
81647882 Type.err_int,
81657883 try mod.getErrorValue(err_name),
......@@ -8167,17 +7885,19 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
81677885 }
81687886
81697887 const op_ty = sema.typeOf(uncasted_operand);
8170 try sema.resolveInferredErrorSetTy(block, src, op_ty);
8171 if (!op_ty.isAnyError(mod)) {
8172 const names = op_ty.errorSetNames(mod);
8173 switch (names.len) {
8174 0 => return sema.addConstant(try mod.intValue(Type.err_int, 0)),
8175 1 => {
8176 const int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(names[0]).?));
8177 return sema.addIntUnsigned(Type.err_int, int);
8178 },
8179 else => {},
8180 }
7888 switch (try sema.resolveInferredErrorSetTy(block, src, op_ty.toIntern())) {
7889 .anyerror_type => {},
7890 else => |err_set_ty_index| {
7891 const names = ip.indexToKey(err_set_ty_index).error_set_type.names;
7892 switch (names.len) {
7893 0 => return sema.addConstant(try mod.intValue(Type.err_int, 0)),
7894 1 => {
7895 const int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[0]).?);
7896 return sema.addIntUnsigned(Type.err_int, int);
7897 },
7898 else => {},
7899 }
7900 },
81817901 }
81827902
81837903 try sema.requireRuntimeBlock(block, src, operand_src);
......@@ -8226,6 +7946,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
82267946 defer tracy.end();
82277947
82287948 const mod = sema.mod;
7949 const ip = &mod.intern_pool;
82297950 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
82307951 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
82317952 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
......@@ -8254,23 +7975,25 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
82547975 return Air.Inst.Ref.anyerror_type;
82557976 }
82567977
8257 if (mod.typeToInferredErrorSetIndex(lhs_ty).unwrap()) |ies_index| {
8258 try sema.resolveInferredErrorSet(block, src, ies_index);
8259 // isAnyError might have changed from a false negative to a true positive after resolution.
8260 if (lhs_ty.isAnyError(mod)) {
8261 return Air.Inst.Ref.anyerror_type;
7978 if (ip.isInferredErrorSetType(lhs_ty.toIntern())) {
7979 switch (try sema.resolveInferredErrorSet(block, src, lhs_ty.toIntern())) {
7980 // isAnyError might have changed from a false negative to a true
7981 // positive after resolution.
7982 .anyerror_type => return .anyerror_type,
7983 else => {},
82627984 }
82637985 }
8264 if (mod.typeToInferredErrorSetIndex(rhs_ty).unwrap()) |ies_index| {
8265 try sema.resolveInferredErrorSet(block, src, ies_index);
8266 // isAnyError might have changed from a false negative to a true positive after resolution.
8267 if (rhs_ty.isAnyError(mod)) {
8268 return Air.Inst.Ref.anyerror_type;
7986 if (ip.isInferredErrorSetType(rhs_ty.toIntern())) {
7987 switch (try sema.resolveInferredErrorSet(block, src, rhs_ty.toIntern())) {
7988 // isAnyError might have changed from a false negative to a true
7989 // positive after resolution.
7990 .anyerror_type => return .anyerror_type,
7991 else => {},
82697992 }
82707993 }
82717994
82727995 const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty);
8273 return sema.addType(err_set_ty);
7996 return Air.internedToRef(err_set_ty.toIntern());
82747997}
82757998
82767999fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -8747,9 +8470,7 @@ fn zirFunc(
87478470 inst: Zir.Inst.Index,
87488471 inferred_error_set: bool,
87498472) CompileError!Air.Inst.Ref {
8750 const tracy = trace(@src());
8751 defer tracy.end();
8752
8473 const mod = sema.mod;
87538474 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
87548475 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
87558476 const target = sema.mod.getTarget();
......@@ -8790,8 +8511,7 @@ fn zirFunc(
87908511 // If this instruction has a body it means it's the type of the `owner_decl`
87918512 // otherwise it's a function type without a `callconv` attribute and should
87928513 // never be `.C`.
8793 // NOTE: revisit when doing #1717
8794 const cc: std.builtin.CallingConvention = if (sema.owner_decl.is_exported and has_body)
8514 const cc: std.builtin.CallingConvention = if (has_body and mod.declPtr(block.src_decl).is_exported)
87958515 .C
87968516 else
87978517 .Unspecified;
......@@ -8802,7 +8522,7 @@ fn zirFunc(
88028522 inst,
88038523 .none,
88048524 target_util.defaultAddressSpace(target, .function),
8805 FuncLinkSection.default,
8525 .default,
88068526 cc,
88078527 ret_ty,
88088528 false,
......@@ -8830,10 +8550,21 @@ fn resolveGenericBody(
88308550 const err = err: {
88318551 // Make sure any nested param instructions don't clobber our work.
88328552 const prev_params = block.params;
8553 const prev_no_partial_func_type = sema.no_partial_func_ty;
8554 const prev_generic_owner = sema.generic_owner;
8555 const prev_generic_call_src = sema.generic_call_src;
8556 const prev_generic_call_decl = sema.generic_call_decl;
88338557 block.params = .{};
8558 sema.no_partial_func_ty = true;
8559 sema.generic_owner = .none;
8560 sema.generic_call_src = .unneeded;
8561 sema.generic_call_decl = .none;
88348562 defer {
8835 block.params.deinit(sema.gpa);
88368563 block.params = prev_params;
8564 sema.no_partial_func_ty = prev_no_partial_func_type;
8565 sema.generic_owner = prev_generic_owner;
8566 sema.generic_call_src = prev_generic_call_src;
8567 sema.generic_call_decl = prev_generic_call_decl;
88378568 }
88388569
88398570 const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err;
......@@ -8952,7 +8683,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
89528683 }
89538684}
89548685
8955const FuncLinkSection = union(enum) {
8686const Section = union(enum) {
89568687 generic,
89578688 default,
89588689 explicit: InternPool.NullTerminatedString,
......@@ -8967,8 +8698,7 @@ fn funcCommon(
89678698 alignment: ?Alignment,
89688699 /// null means generic poison
89698700 address_space: ?std.builtin.AddressSpace,
8970 /// outer null means generic poison; inner null means default link section
8971 section: FuncLinkSection,
8701 section: Section,
89728702 /// null means generic poison
89738703 cc: ?std.builtin.CallingConvention,
89748704 /// this might be Type.generic_poison
......@@ -8984,6 +8714,8 @@ fn funcCommon(
89848714) CompileError!Air.Inst.Ref {
89858715 const mod = sema.mod;
89868716 const gpa = sema.gpa;
8717 const target = mod.getTarget();
8718 const ip = &mod.intern_pool;
89878719 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
89888720 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };
89898721 const func_src = LazySrcLoc.nodeOffset(src_node_offset);
......@@ -9001,226 +8733,150 @@ fn funcCommon(
90018733 try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?);
90028734 }
90038735
9004 var destroy_fn_on_error = false;
9005 const new_func_index = new_func: {
9006 if (!has_body) break :new_func undefined;
9007 if (sema.comptime_args_fn_inst == func_inst) {
9008 const new_func_index = sema.preallocated_new_func.unwrap().?;
9009 sema.preallocated_new_func = .none; // take ownership
9010 break :new_func new_func_index;
9011 }
9012 destroy_fn_on_error = true;
9013 var new_func: Module.Fn = undefined;
9014 // Set this here so that the inferred return type can be printed correctly if it appears in an error.
9015 new_func.owner_decl = sema.owner_decl_index;
9016 const new_func_index = try mod.createFunc(new_func);
9017 break :new_func new_func_index;
9018 };
9019 errdefer if (destroy_fn_on_error) mod.destroyFunc(new_func_index);
8736 const is_source_decl = sema.generic_owner == .none;
90208737
9021 const target = mod.getTarget();
9022 const fn_ty: Type = fn_ty: {
9023 // In the case of generic calling convention, or generic alignment, we use
9024 // default values which are only meaningful for the generic function, *not*
9025 // the instantiation, which can depend on comptime parameters.
9026 // Related proposal: https://github.com/ziglang/zig/issues/11834
9027 const cc_resolved = cc orelse .Unspecified;
9028 const param_types = try sema.arena.alloc(InternPool.Index, block.params.items.len);
9029 var comptime_bits: u32 = 0;
9030 for (param_types, block.params.items, 0..) |*dest_param_ty, param, i| {
9031 const is_noalias = blk: {
9032 const index = std.math.cast(u5, i) orelse break :blk false;
9033 break :blk @as(u1, @truncate(noalias_bits >> index)) != 0;
9034 };
9035 dest_param_ty.* = param.ty.toIntern();
9036 sema.analyzeParameter(
9037 block,
9038 .unneeded,
9039 param,
9040 &comptime_bits,
9041 i,
9042 &is_generic,
9043 cc_resolved,
9044 has_body,
9045 is_noalias,
9046 ) catch |err| switch (err) {
9047 error.NeededSourceLocation => {
9048 const decl = mod.declPtr(block.src_decl);
9049 try sema.analyzeParameter(
9050 block,
9051 Module.paramSrc(src_node_offset, mod, decl, i),
9052 param,
9053 &comptime_bits,
9054 i,
9055 &is_generic,
9056 cc_resolved,
9057 has_body,
9058 is_noalias,
9059 );
9060 unreachable;
9061 },
9062 else => |e| return e,
9063 };
9064 }
9065
9066 var ret_ty_requires_comptime = false;
9067 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
9068 ret_ty_requires_comptime = ret_comptime;
9069 break :rp bare_return_type.isGenericPoison();
9070 } else |err| switch (err) {
9071 error.GenericPoison => rp: {
9072 is_generic = true;
9073 break :rp true;
9074 },
9075 else => |e| return e,
8738 // In the case of generic calling convention, or generic alignment, we use
8739 // default values which are only meaningful for the generic function, *not*
8740 // the instantiation, which can depend on comptime parameters.
8741 // Related proposal: https://github.com/ziglang/zig/issues/11834
8742 const cc_resolved = cc orelse .Unspecified;
8743 var comptime_bits: u32 = 0;
8744 for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| {
8745 const param_ty = param_ty_ip.toType();
8746 const is_noalias = blk: {
8747 const index = std.math.cast(u5, i) orelse break :blk false;
8748 break :blk @as(u1, @truncate(noalias_bits >> index)) != 0;
90768749 };
9077
9078 const return_type: Type = if (!inferred_error_set or ret_poison)
9079 bare_return_type
9080 else blk: {
9081 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
9082 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
9083 .func = new_func_index,
9084 });
9085 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
9086 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
9087 };
9088
9089 if (!return_type.isValidReturnType(mod)) {
9090 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";
8750 const param_src: LazySrcLoc = .{ .fn_proto_param = .{
8751 .decl = block.src_decl,
8752 .fn_proto_node_offset = src_node_offset,
8753 .param_index = @intCast(i),
8754 } };
8755 const requires_comptime = try sema.typeRequiresComptime(param_ty);
8756 if (param_is_comptime or requires_comptime) {
8757 comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error
8758 }
8759 const this_generic = param_ty.isGenericPoison();
8760 is_generic = is_generic or this_generic;
8761 if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) {
8762 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});
8763 }
8764 if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) {
8765 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});
8766 }
8767 if (!param_ty.isValidParamType(mod)) {
8768 const opaque_str = if (param_ty.zigTypeTag(mod) == .Opaque) "opaque " else "";
90918769 const msg = msg: {
9092 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{
9093 opaque_str, return_type.fmt(mod),
8770 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{
8771 opaque_str, param_ty.fmt(mod),
90948772 });
9095 errdefer msg.destroy(gpa);
8773 errdefer msg.destroy(sema.gpa);
90968774
9097 try sema.addDeclaredHereNote(msg, return_type);
8775 try sema.addDeclaredHereNote(msg, param_ty);
90988776 break :msg msg;
90998777 };
91008778 return sema.failWithOwnedErrorMsg(msg);
91018779 }
9102 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and
9103 !try sema.validateExternType(return_type, .ret_ty))
9104 {
8780 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) {
91058781 const msg = msg: {
9106 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
9107 return_type.fmt(mod), @tagName(cc_resolved),
8782 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
8783 param_ty.fmt(mod), @tagName(cc_resolved),
91088784 });
9109 errdefer msg.destroy(gpa);
8785 errdefer msg.destroy(sema.gpa);
91108786
91118787 const src_decl = mod.declPtr(block.src_decl);
9112 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl, mod), return_type, .ret_ty);
8788 try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl, mod), param_ty, .param_ty);
91138789
9114 try sema.addDeclaredHereNote(msg, return_type);
8790 try sema.addDeclaredHereNote(msg, param_ty);
91158791 break :msg msg;
91168792 };
91178793 return sema.failWithOwnedErrorMsg(msg);
91188794 }
8795 if (is_source_decl and requires_comptime and !param_is_comptime and has_body) {
8796 const msg = msg: {
8797 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{
8798 param_ty.fmt(mod),
8799 });
8800 errdefer msg.destroy(sema.gpa);
91198801
9120 // If the return type is comptime-only but not dependent on parameters then all parameter types also need to be comptime
9121 if (!sema.is_generic_instantiation and has_body and ret_ty_requires_comptime) comptime_check: {
9122 for (block.params.items) |param| {
9123 if (!param.is_comptime) break;
9124 } else break :comptime_check;
8802 const src_decl = mod.declPtr(block.src_decl);
8803 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param_ty);
91258804
9126 const msg = try sema.errMsg(
9127 block,
9128 ret_ty_src,
9129 "function with comptime-only return type '{}' requires all parameters to be comptime",
9130 .{return_type.fmt(mod)},
9131 );
9132 try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl, mod), return_type);
9133
9134 const tags = sema.code.instructions.items(.tag);
9135 const data = sema.code.instructions.items(.data);
9136 const param_body = sema.code.getParamBody(func_inst);
9137 for (block.params.items, 0..) |param, i| {
9138 if (!param.is_comptime) {
9139 const param_index = param_body[i];
9140 const param_src = switch (tags[param_index]) {
9141 .param => data[param_index].pl_tok.src(),
9142 .param_anytype => data[param_index].str_tok.src(),
9143 else => unreachable,
9144 };
9145 if (param.name.len != 0) {
9146 try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{param.name});
9147 } else {
9148 try sema.errNote(block, param_src, msg, "param is required to be comptime", .{});
9149 }
9150 }
9151 }
8805 try sema.addDeclaredHereNote(msg, param_ty);
8806 break :msg msg;
8807 };
91528808 return sema.failWithOwnedErrorMsg(msg);
91538809 }
9154
9155 const arch = mod.getTarget().cpu.arch;
9156 if (switch (cc_resolved) {
9157 .Unspecified, .C, .Naked, .Async, .Inline => null,
9158 .Interrupt => switch (arch) {
9159 .x86, .x86_64, .avr, .msp430 => null,
9160 else => @as([]const u8, "x86, x86_64, AVR, and MSP430"),
9161 },
9162 .Signal => switch (arch) {
9163 .avr => null,
9164 else => @as([]const u8, "AVR"),
9165 },
9166 .Stdcall, .Fastcall, .Thiscall => switch (arch) {
9167 .x86 => null,
9168 else => @as([]const u8, "x86"),
9169 },
9170 .Vectorcall => switch (arch) {
9171 .x86, .aarch64, .aarch64_be, .aarch64_32 => null,
9172 else => @as([]const u8, "x86 and AArch64"),
9173 },
9174 .APCS, .AAPCS, .AAPCSVFP => switch (arch) {
9175 .arm, .armeb, .aarch64, .aarch64_be, .aarch64_32, .thumb, .thumbeb => null,
9176 else => @as([]const u8, "ARM"),
9177 },
9178 .SysV, .Win64 => switch (arch) {
9179 .x86_64 => null,
9180 else => @as([]const u8, "x86_64"),
9181 },
9182 .Kernel => switch (arch) {
9183 .nvptx, .nvptx64, .amdgcn, .spirv32, .spirv64 => null,
9184 else => @as([]const u8, "nvptx, amdgcn and SPIR-V"),
9185 },
9186 }) |allowed_platform| {
9187 return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{
9188 @tagName(cc_resolved),
9189 allowed_platform,
9190 @tagName(arch),
9191 });
9192 }
9193
9194 if (cc_resolved == .Inline and is_noinline) {
9195 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
8810 if (is_source_decl and !this_generic and is_noalias and
8811 !(param_ty.zigTypeTag(mod) == .Pointer or param_ty.isPtrLikeOptional(mod)))
8812 {
8813 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
91968814 }
9197 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
9198 is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
8815 }
91998816
9200 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {
9201 // Make sure that StackTrace's fields are resolved so that the backend can
9202 // lower this fn type.
9203 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
9204 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
8817 var ret_ty_requires_comptime = false;
8818 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
8819 ret_ty_requires_comptime = ret_comptime;
8820 break :rp bare_return_type.isGenericPoison();
8821 } else |err| switch (err) {
8822 error.GenericPoison => rp: {
8823 is_generic = true;
8824 break :rp true;
8825 },
8826 else => |e| return e,
8827 };
8828 const final_is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
8829
8830 const param_types = block.params.items(.ty);
8831
8832 if (!is_source_decl) {
8833 assert(has_body);
8834 assert(!is_generic);
8835 assert(comptime_bits == 0);
8836 assert(cc != null);
8837 assert(section != .generic);
8838 assert(address_space != null);
8839 assert(!var_args);
8840 if (inferred_error_set) {
8841 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
92058842 }
9206
9207 break :fn_ty try mod.funcType(.{
8843 const func_index = try ip.getFuncInstance(gpa, .{
92088844 .param_types = param_types,
92098845 .noalias_bits = noalias_bits,
9210 .comptime_bits = comptime_bits,
9211 .return_type = return_type.toIntern(),
8846 .bare_return_type = bare_return_type.toIntern(),
92128847 .cc = cc_resolved,
9213 .cc_is_generic = cc == null,
9214 .alignment = alignment orelse .none,
9215 .align_is_generic = alignment == null,
9216 .section_is_generic = section == .generic,
9217 .addrspace_is_generic = address_space == null,
9218 .is_var_args = var_args,
9219 .is_generic = is_generic,
8848 .alignment = alignment.?,
8849 .section = switch (section) {
8850 .generic => unreachable,
8851 .default => .none,
8852 .explicit => |x| x.toOptional(),
8853 },
92208854 .is_noinline = is_noinline,
8855 .inferred_error_set = inferred_error_set,
8856 .generic_owner = sema.generic_owner,
8857 .comptime_args = sema.comptime_args,
8858 .generation = mod.generation,
92218859 });
9222 };
8860 return finishFunc(
8861 sema,
8862 block,
8863 func_index,
8864 .none,
8865 ret_poison,
8866 bare_return_type,
8867 ret_ty_src,
8868 cc_resolved,
8869 is_source_decl,
8870 ret_ty_requires_comptime,
8871 func_inst,
8872 cc_src,
8873 is_noinline,
8874 is_generic,
8875 final_is_generic,
8876 );
8877 }
92238878
8879 // extern_func and func_decl functions take ownership of `sema.owner_decl`.
92248880 sema.owner_decl.@"linksection" = switch (section) {
92258881 .generic => .none,
92268882 .default => .none,
......@@ -9229,9 +8885,73 @@ fn funcCommon(
92298885 sema.owner_decl.alignment = alignment orelse .none;
92308886 sema.owner_decl.@"addrspace" = address_space orelse .generic;
92318887
8888 if (inferred_error_set) {
8889 assert(!is_extern);
8890 assert(has_body);
8891 if (!ret_poison)
8892 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
8893 const func_index = try ip.getFuncDeclIes(gpa, .{
8894 .owner_decl = sema.owner_decl_index,
8895
8896 .param_types = param_types,
8897 .noalias_bits = noalias_bits,
8898 .comptime_bits = comptime_bits,
8899 .bare_return_type = bare_return_type.toIntern(),
8900 .cc = cc,
8901 .alignment = alignment,
8902 .section_is_generic = section == .generic,
8903 .addrspace_is_generic = address_space == null,
8904 .is_var_args = var_args,
8905 .is_generic = final_is_generic,
8906 .is_noinline = is_noinline,
8907
8908 .zir_body_inst = func_inst,
8909 .lbrace_line = src_locs.lbrace_line,
8910 .rbrace_line = src_locs.rbrace_line,
8911 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
8912 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
8913 });
8914 return finishFunc(
8915 sema,
8916 block,
8917 func_index,
8918 .none,
8919 ret_poison,
8920 bare_return_type,
8921 ret_ty_src,
8922 cc_resolved,
8923 is_source_decl,
8924 ret_ty_requires_comptime,
8925 func_inst,
8926 cc_src,
8927 is_noinline,
8928 is_generic,
8929 final_is_generic,
8930 );
8931 }
8932
8933 const func_ty = try ip.getFuncType(gpa, .{
8934 .param_types = param_types,
8935 .noalias_bits = noalias_bits,
8936 .comptime_bits = comptime_bits,
8937 .return_type = bare_return_type.toIntern(),
8938 .cc = cc,
8939 .alignment = alignment,
8940 .section_is_generic = section == .generic,
8941 .addrspace_is_generic = address_space == null,
8942 .is_var_args = var_args,
8943 .is_generic = final_is_generic,
8944 .is_noinline = is_noinline,
8945 });
8946
92328947 if (is_extern) {
9233 return sema.addConstant((try mod.intern(.{ .extern_func = .{
9234 .ty = fn_ty.toIntern(),
8948 assert(comptime_bits == 0);
8949 assert(cc != null);
8950 assert(section != .generic);
8951 assert(address_space != null);
8952 assert(!is_generic);
8953 const func_index = try ip.getExternFunc(gpa, .{
8954 .ty = func_ty,
92358955 .decl = sema.owner_decl_index,
92368956 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
92378957 gpa,
......@@ -9239,129 +8959,241 @@ fn funcCommon(
92398959 .node_offset_lib_name = src_node_offset,
92408960 }, lib_name),
92418961 )).toOptional() else .none,
9242 } })).toValue());
8962 });
8963 return finishFunc(
8964 sema,
8965 block,
8966 func_index,
8967 func_ty,
8968 ret_poison,
8969 bare_return_type,
8970 ret_ty_src,
8971 cc_resolved,
8972 is_source_decl,
8973 ret_ty_requires_comptime,
8974 func_inst,
8975 cc_src,
8976 is_noinline,
8977 is_generic,
8978 final_is_generic,
8979 );
92438980 }
92448981
9245 if (!has_body) {
9246 return sema.addType(fn_ty);
8982 if (has_body) {
8983 const func_index = try ip.getFuncDecl(gpa, .{
8984 .owner_decl = sema.owner_decl_index,
8985 .ty = func_ty,
8986 .cc = cc,
8987 .is_noinline = is_noinline,
8988 .zir_body_inst = func_inst,
8989 .lbrace_line = src_locs.lbrace_line,
8990 .rbrace_line = src_locs.rbrace_line,
8991 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
8992 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
8993 });
8994 return finishFunc(
8995 sema,
8996 block,
8997 func_index,
8998 func_ty,
8999 ret_poison,
9000 bare_return_type,
9001 ret_ty_src,
9002 cc_resolved,
9003 is_source_decl,
9004 ret_ty_requires_comptime,
9005 func_inst,
9006 cc_src,
9007 is_noinline,
9008 is_generic,
9009 final_is_generic,
9010 );
92479011 }
92489012
9249 const is_inline = fn_ty.fnCallingConvention(mod) == .Inline;
9250 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;
9251
9252 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {
9253 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
9254 } else null;
9255
9256 const new_func = mod.funcPtr(new_func_index);
9257 const hash = new_func.hash;
9258 const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;
9259 new_func.* = .{
9260 .state = anal_state,
9261 .zir_body_inst = func_inst,
9262 .owner_decl = sema.owner_decl_index,
9263 .generic_owner_decl = generic_owner_decl,
9264 .comptime_args = comptime_args,
9265 .hash = hash,
9266 .lbrace_line = src_locs.lbrace_line,
9267 .rbrace_line = src_locs.rbrace_line,
9268 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9269 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9270 .branch_quota = default_branch_quota,
9271 .is_noinline = is_noinline,
9272 };
9273 return sema.addConstant((try mod.intern(.{ .func = .{
9274 .ty = fn_ty.toIntern(),
9275 .index = new_func_index,
9276 } })).toValue());
9013 return finishFunc(
9014 sema,
9015 block,
9016 .none,
9017 func_ty,
9018 ret_poison,
9019 bare_return_type,
9020 ret_ty_src,
9021 cc_resolved,
9022 is_source_decl,
9023 ret_ty_requires_comptime,
9024 func_inst,
9025 cc_src,
9026 is_noinline,
9027 is_generic,
9028 final_is_generic,
9029 );
92779030}
92789031
9279fn analyzeParameter(
9032fn finishFunc(
92809033 sema: *Sema,
92819034 block: *Block,
9282 param_src: LazySrcLoc,
9283 param: Block.Param,
9284 comptime_bits: *u32,
9285 i: usize,
9286 is_generic: *bool,
9287 cc: std.builtin.CallingConvention,
9288 has_body: bool,
9289 is_noalias: bool,
9290) !void {
9035 opt_func_index: InternPool.Index,
9036 func_ty: InternPool.Index,
9037 ret_poison: bool,
9038 bare_return_type: Type,
9039 ret_ty_src: LazySrcLoc,
9040 cc_resolved: std.builtin.CallingConvention,
9041 is_source_decl: bool,
9042 ret_ty_requires_comptime: bool,
9043 func_inst: Zir.Inst.Index,
9044 cc_src: LazySrcLoc,
9045 is_noinline: bool,
9046 is_generic: bool,
9047 final_is_generic: bool,
9048) CompileError!Air.Inst.Ref {
92919049 const mod = sema.mod;
9292 const requires_comptime = try sema.typeRequiresComptime(param.ty);
9293 if (param.is_comptime or requires_comptime) {
9294 comptime_bits.* |= @as(u32, 1) << @as(u5, @intCast(i)); // TODO: handle cast error
9295 }
9296 const this_generic = param.ty.isGenericPoison();
9297 is_generic.* = is_generic.* or this_generic;
9050 const ip = &mod.intern_pool;
9051 const gpa = sema.gpa;
92989052 const target = mod.getTarget();
9299 if (param.is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc)) {
9300 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9301 }
9302 if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc)) {
9303 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9304 }
9305 if (!param.ty.isValidParamType(mod)) {
9306 const opaque_str = if (param.ty.zigTypeTag(mod) == .Opaque) "opaque " else "";
9053
9054 const return_type: Type = if (opt_func_index == .none or ret_poison)
9055 bare_return_type
9056 else
9057 ip.funcTypeReturnType(ip.typeOf(opt_func_index)).toType();
9058
9059 if (!return_type.isValidReturnType(mod)) {
9060 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";
93079061 const msg = msg: {
9308 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{
9309 opaque_str, param.ty.fmt(mod),
9062 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{
9063 opaque_str, return_type.fmt(mod),
93109064 });
9311 errdefer msg.destroy(sema.gpa);
9065 errdefer msg.destroy(gpa);
93129066
9313 try sema.addDeclaredHereNote(msg, param.ty);
9067 try sema.addDeclaredHereNote(msg, return_type);
93149068 break :msg msg;
93159069 };
93169070 return sema.failWithOwnedErrorMsg(msg);
93179071 }
9318 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) {
9072 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and
9073 !try sema.validateExternType(return_type, .ret_ty))
9074 {
93199075 const msg = msg: {
9320 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
9321 param.ty.fmt(mod), @tagName(cc),
9076 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
9077 return_type.fmt(mod), @tagName(cc_resolved),
93229078 });
9323 errdefer msg.destroy(sema.gpa);
9079 errdefer msg.destroy(gpa);
93249080
93259081 const src_decl = mod.declPtr(block.src_decl);
9326 try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl, mod), param.ty, .param_ty);
9082 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl, mod), return_type, .ret_ty);
93279083
9328 try sema.addDeclaredHereNote(msg, param.ty);
9084 try sema.addDeclaredHereNote(msg, return_type);
93299085 break :msg msg;
93309086 };
93319087 return sema.failWithOwnedErrorMsg(msg);
93329088 }
9333 if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) {
9334 const msg = msg: {
9335 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{
9336 param.ty.fmt(mod),
9337 });
9338 errdefer msg.destroy(sema.gpa);
93399089
9340 const src_decl = mod.declPtr(block.src_decl);
9341 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param.ty);
9090 // If the return type is comptime-only but not dependent on parameters then
9091 // all parameter types also need to be comptime.
9092 if (is_source_decl and opt_func_index != .none and ret_ty_requires_comptime) comptime_check: {
9093 for (block.params.items(.is_comptime)) |is_comptime| {
9094 if (!is_comptime) break;
9095 } else break :comptime_check;
93429096
9343 try sema.addDeclaredHereNote(msg, param.ty);
9344 break :msg msg;
9345 };
9097 const msg = try sema.errMsg(
9098 block,
9099 ret_ty_src,
9100 "function with comptime-only return type '{}' requires all parameters to be comptime",
9101 .{return_type.fmt(mod)},
9102 );
9103 try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl, mod), return_type);
9104
9105 const tags = sema.code.instructions.items(.tag);
9106 const data = sema.code.instructions.items(.data);
9107 const param_body = sema.code.getParamBody(func_inst);
9108 for (
9109 block.params.items(.is_comptime),
9110 block.params.items(.name),
9111 param_body[0..block.params.len],
9112 ) |is_comptime, name_nts, param_index| {
9113 if (!is_comptime) {
9114 const param_src = switch (tags[param_index]) {
9115 .param => data[param_index].pl_tok.src(),
9116 .param_anytype => data[param_index].str_tok.src(),
9117 else => unreachable,
9118 };
9119 const name = sema.code.nullTerminatedString2(name_nts);
9120 if (name.len != 0) {
9121 try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{name});
9122 } else {
9123 try sema.errNote(block, param_src, msg, "param is required to be comptime", .{});
9124 }
9125 }
9126 }
93469127 return sema.failWithOwnedErrorMsg(msg);
93479128 }
9348 if (!sema.is_generic_instantiation and !this_generic and is_noalias and
9349 !(param.ty.zigTypeTag(mod) == .Pointer or param.ty.isPtrLikeOptional(mod)))
9350 {
9351 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
9129
9130 const arch = target.cpu.arch;
9131 if (switch (cc_resolved) {
9132 .Unspecified, .C, .Naked, .Async, .Inline => null,
9133 .Interrupt => switch (arch) {
9134 .x86, .x86_64, .avr, .msp430 => null,
9135 else => @as([]const u8, "x86, x86_64, AVR, and MSP430"),
9136 },
9137 .Signal => switch (arch) {
9138 .avr => null,
9139 else => @as([]const u8, "AVR"),
9140 },
9141 .Stdcall, .Fastcall, .Thiscall => switch (arch) {
9142 .x86 => null,
9143 else => @as([]const u8, "x86"),
9144 },
9145 .Vectorcall => switch (arch) {
9146 .x86, .aarch64, .aarch64_be, .aarch64_32 => null,
9147 else => @as([]const u8, "x86 and AArch64"),
9148 },
9149 .APCS, .AAPCS, .AAPCSVFP => switch (arch) {
9150 .arm, .armeb, .aarch64, .aarch64_be, .aarch64_32, .thumb, .thumbeb => null,
9151 else => @as([]const u8, "ARM"),
9152 },
9153 .SysV, .Win64 => switch (arch) {
9154 .x86_64 => null,
9155 else => @as([]const u8, "x86_64"),
9156 },
9157 .Kernel => switch (arch) {
9158 .nvptx, .nvptx64, .amdgcn, .spirv32, .spirv64 => null,
9159 else => @as([]const u8, "nvptx, amdgcn and SPIR-V"),
9160 },
9161 }) |allowed_platform| {
9162 return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{
9163 @tagName(cc_resolved),
9164 allowed_platform,
9165 @tagName(arch),
9166 });
93529167 }
9168
9169 if (cc_resolved == .Inline and is_noinline) {
9170 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
9171 }
9172 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
9173
9174 if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) {
9175 // Make sure that StackTrace's fields are resolved so that the backend can
9176 // lower this fn type.
9177 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
9178 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
9179 }
9180
9181 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);
93539182}
93549183
93559184fn zirParam(
93569185 sema: *Sema,
93579186 block: *Block,
93589187 inst: Zir.Inst.Index,
9188 param_index: u32,
93599189 comptime_syntax: bool,
93609190) CompileError!void {
9191 const mod = sema.mod;
9192 const gpa = sema.gpa;
93619193 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
93629194 const src = inst_data.src();
93639195 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);
9364 const param_name = sema.code.nullTerminatedString(extra.data.name);
9196 const param_name: Zir.NullTerminatedString = @enumFromInt(extra.data.name);
93659197 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
93669198
93679199 // We could be in a generic function instantiation, or we could be evaluating a generic
......@@ -9370,16 +9202,21 @@ fn zirParam(
93709202 const err = err: {
93719203 // Make sure any nested param instructions don't clobber our work.
93729204 const prev_params = block.params;
9373 const prev_preallocated_new_func = sema.preallocated_new_func;
93749205 const prev_no_partial_func_type = sema.no_partial_func_ty;
9206 const prev_generic_owner = sema.generic_owner;
9207 const prev_generic_call_src = sema.generic_call_src;
9208 const prev_generic_call_decl = sema.generic_call_decl;
93759209 block.params = .{};
9376 sema.preallocated_new_func = .none;
93779210 sema.no_partial_func_ty = true;
9211 sema.generic_owner = .none;
9212 sema.generic_call_src = .unneeded;
9213 sema.generic_call_decl = .none;
93789214 defer {
9379 block.params.deinit(sema.gpa);
93809215 block.params = prev_params;
9381 sema.preallocated_new_func = prev_preallocated_new_func;
93829216 sema.no_partial_func_ty = prev_no_partial_func_type;
9217 sema.generic_owner = prev_generic_owner;
9218 sema.generic_call_src = prev_generic_call_src;
9219 sema.generic_call_decl = prev_generic_call_decl;
93839220 }
93849221
93859222 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
......@@ -9390,7 +9227,7 @@ fn zirParam(
93909227 };
93919228 switch (err) {
93929229 error.GenericPoison => {
9393 if (sema.inst_map.get(inst)) |_| {
9230 if (sema.inst_map.contains(inst)) {
93949231 // A generic function is about to evaluate to another generic function.
93959232 // Return an error instead.
93969233 return error.GenericPoison;
......@@ -9398,8 +9235,8 @@ fn zirParam(
93989235 // The type is not available until the generic instantiation.
93999236 // We result the param instruction with a poison value and
94009237 // insert an anytype parameter.
9401 try block.params.append(sema.gpa, .{
9402 .ty = Type.generic_poison,
9238 try block.params.append(sema.arena, .{
9239 .ty = .generic_poison_type,
94039240 .is_comptime = comptime_syntax,
94049241 .name = param_name,
94059242 });
......@@ -9409,9 +9246,10 @@ fn zirParam(
94099246 else => |e| return e,
94109247 }
94119248 };
9249
94129250 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {
94139251 error.GenericPoison => {
9414 if (sema.inst_map.get(inst)) |_| {
9252 if (sema.inst_map.contains(inst)) {
94159253 // A generic function is about to evaluate to another generic function.
94169254 // Return an error instead.
94179255 return error.GenericPoison;
......@@ -9419,8 +9257,8 @@ fn zirParam(
94199257 // The type is not available until the generic instantiation.
94209258 // We result the param instruction with a poison value and
94219259 // insert an anytype parameter.
9422 try block.params.append(sema.gpa, .{
9423 .ty = Type.generic_poison,
9260 try block.params.append(sema.arena, .{
9261 .ty = .generic_poison_type,
94249262 .is_comptime = comptime_syntax,
94259263 .name = param_name,
94269264 });
......@@ -9429,8 +9267,9 @@ fn zirParam(
94299267 },
94309268 else => |e| return e,
94319269 } or comptime_syntax;
9270
94329271 if (sema.inst_map.get(inst)) |arg| {
9433 if (is_comptime and sema.preallocated_new_func != .none) {
9272 if (is_comptime and sema.generic_owner != .none) {
94349273 // We have a comptime value for this parameter so it should be elided from the
94359274 // function type of the function instruction in this block.
94369275 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
......@@ -9440,32 +9279,53 @@ fn zirParam(
94409279 // have the callee source location return `GenericPoison`
94419280 // so that the instantiation is failed and the coercion
94429281 // is handled by comptime call logic instead.
9443 assert(sema.is_generic_instantiation);
9282 assert(sema.generic_owner != .none);
94449283 return error.GenericPoison;
94459284 },
9446 else => return err,
9285 else => |e| return e,
94479286 };
94489287 sema.inst_map.putAssumeCapacity(inst, coerced_arg);
9449 return;
9288 if (try sema.resolveMaybeUndefVal(coerced_arg)) |val| {
9289 sema.comptime_args[param_index] = val.toIntern();
9290 return;
9291 }
9292 const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{
9293 .decl = sema.generic_call_decl.unwrap().?,
9294 .call_node_offset = sema.generic_call_src.node_offset.x,
9295 .arg_index = param_index,
9296 } } else src;
9297 const msg = msg: {
9298 const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod);
9299 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9300 @as([]const u8, "runtime-known argument passed to comptime parameter"),
9301 });
9302 errdefer msg.destroy(gpa);
9303
9304 if (sema.generic_call_decl != .none) {
9305 try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared comptime here")});
9306 }
9307 break :msg msg;
9308 };
9309 return sema.failWithOwnedErrorMsg(msg);
94509310 }
94519311 // Even though a comptime argument is provided, the generic function wants to treat
94529312 // this as a runtime parameter.
94539313 assert(sema.inst_map.remove(inst));
94549314 }
94559315
9456 if (sema.preallocated_new_func != .none) {
9316 if (sema.generic_owner != .none) {
94579317 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
94589318 // In this case we are instantiating a generic function call with a non-comptime
94599319 // non-anytype parameter that ended up being a one-possible-type.
94609320 // We don't want the parameter to be part of the instantiated function type.
9461 const result = try sema.addConstant(opv);
9462 sema.inst_map.putAssumeCapacity(inst, result);
9321 sema.inst_map.putAssumeCapacity(inst, Air.internedToRef(opv.toIntern()));
9322 sema.comptime_args[param_index] = opv.toIntern();
94639323 return;
94649324 }
94659325 }
94669326
9467 try block.params.append(sema.gpa, .{
9468 .ty = param_ty,
9327 try block.params.append(sema.arena, .{
9328 .ty = param_ty.toIntern(),
94699329 .is_comptime = comptime_syntax,
94709330 .name = param_name,
94719331 });
......@@ -9473,17 +9333,15 @@ fn zirParam(
94739333 if (is_comptime) {
94749334 // If this is a comptime parameter we can add a constant generic_poison
94759335 // since this is also a generic parameter.
9476 const result = try sema.addConstant(Value.generic_poison);
9477 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
9336 sema.inst_map.putAssumeCapacityNoClobber(inst, .generic_poison);
94789337 } else {
94799338 // Otherwise we need a dummy runtime instruction.
9480 const result_index = @as(Air.Inst.Index, @intCast(sema.air_instructions.len));
9339 const result_index: Air.Inst.Index = @intCast(sema.air_instructions.len);
94819340 try sema.air_instructions.append(sema.gpa, .{
94829341 .tag = .alloc,
94839342 .data = .{ .ty = param_ty },
94849343 });
9485 const result = Air.indexToRef(result_index);
9486 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
9344 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(result_index));
94879345 }
94889346}
94899347
......@@ -9491,24 +9349,76 @@ fn zirParamAnytype(
94919349 sema: *Sema,
94929350 block: *Block,
94939351 inst: Zir.Inst.Index,
9352 param_index: u32,
94949353 comptime_syntax: bool,
94959354) CompileError!void {
9355 const mod = sema.mod;
9356 const gpa = sema.gpa;
94969357 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
9497 const param_name = inst_data.get(sema.code);
9358 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);
9359 const src = inst_data.src();
94989360
94999361 if (sema.inst_map.get(inst)) |air_ref| {
95009362 const param_ty = sema.typeOf(air_ref);
9501 if (comptime_syntax or try sema.typeRequiresComptime(param_ty)) {
9502 // We have a comptime value for this parameter so it should be elided from the
9503 // function type of the function instruction in this block.
9363 // If we have a comptime value for this parameter, it should be elided
9364 // from the function type of the function instruction in this block.
9365 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
9366 sema.comptime_args[param_index] = opv.toIntern();
95049367 return;
95059368 }
9506 if (null != try sema.typeHasOnePossibleValue(param_ty)) {
9507 return;
9369 const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{
9370 .decl = sema.generic_call_decl.unwrap().?,
9371 .call_node_offset = sema.generic_call_src.node_offset.x,
9372 .arg_index = param_index,
9373 } } else src;
9374
9375 if (comptime_syntax) {
9376 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
9377 sema.comptime_args[param_index] = val.toIntern();
9378 return;
9379 }
9380 const msg = msg: {
9381 const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod);
9382 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9383 @as([]const u8, "runtime-known argument passed to comptime parameter"),
9384 });
9385 errdefer msg.destroy(gpa);
9386
9387 if (sema.generic_call_decl != .none) {
9388 try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared comptime here")});
9389 }
9390 break :msg msg;
9391 };
9392 return sema.failWithOwnedErrorMsg(msg);
95089393 }
9394
9395 if (try sema.typeRequiresComptime(param_ty)) {
9396 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
9397 sema.comptime_args[param_index] = val.toIntern();
9398 return;
9399 }
9400 const msg = msg: {
9401 const src_loc = arg_src.toSrcLoc(mod.declPtr(block.src_decl), mod);
9402 const msg = try Module.ErrorMsg.create(gpa, src_loc, "{s}", .{
9403 @as([]const u8, "runtime-known argument passed to comptime-only type parameter"),
9404 });
9405 errdefer msg.destroy(gpa);
9406
9407 if (sema.generic_call_decl != .none) {
9408 try sema.errNote(block, src, msg, "{s}", .{@as([]const u8, "declared here")});
9409 }
9410
9411 try sema.explainWhyTypeIsComptime(msg, src_loc, param_ty);
9412
9413 break :msg msg;
9414 };
9415 return sema.failWithOwnedErrorMsg(msg);
9416 }
9417
9418 // The parameter is runtime-known.
95099419 // The map is already populated but we do need to add a runtime parameter.
9510 try block.params.append(sema.gpa, .{
9511 .ty = param_ty,
9420 try block.params.append(sema.arena, .{
9421 .ty = param_ty.toIntern(),
95129422 .is_comptime = false,
95139423 .name = param_name,
95149424 });
......@@ -9517,8 +9427,8 @@ fn zirParamAnytype(
95179427
95189428 // We are evaluating a generic function without any comptime args provided.
95199429
9520 try block.params.append(sema.gpa, .{
9521 .ty = Type.generic_poison,
9430 try block.params.append(sema.arena, .{
9431 .ty = .generic_poison_type,
95229432 .is_comptime = comptime_syntax,
95239433 .name = param_name,
95249434 });
......@@ -10673,7 +10583,7 @@ const SwitchProngAnalysis = struct {
1067310583 return sema.bitCast(block, item_ty, spa.operand, operand_src, null);
1067410584 }
1067510585
10676 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10586 var names: InferredErrorSet.NameMap = .{};
1067710587 try names.ensureUnusedCapacity(sema.arena, case_vals.len);
1067810588 for (case_vals) |err| {
1067910589 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;
......@@ -11041,97 +10951,100 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1104110951 }
1104210952 }
1104310953
11044 try sema.resolveInferredErrorSetTy(block, src, operand_ty);
11045
11046 if (operand_ty.isAnyError(mod)) {
11047 if (special_prong != .@"else") {
11048 return sema.fail(
11049 block,
11050 src,
11051 "else prong required when switching on type 'anyerror'",
11052 .{},
11053 );
11054 }
11055 else_error_ty = Type.anyerror;
11056 } else else_validation: {
11057 var maybe_msg: ?*Module.ErrorMsg = null;
11058 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);
10954 switch (try sema.resolveInferredErrorSetTy(block, src, operand_ty.toIntern())) {
10955 .anyerror_type => {
10956 if (special_prong != .@"else") {
10957 return sema.fail(
10958 block,
10959 src,
10960 "else prong required when switching on type 'anyerror'",
10961 .{},
10962 );
10963 }
10964 else_error_ty = Type.anyerror;
10965 },
10966 else => |err_set_ty_index| else_validation: {
10967 const error_names = ip.indexToKey(err_set_ty_index).error_set_type.names;
10968 var maybe_msg: ?*Module.ErrorMsg = null;
10969 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);
10970
10971 for (error_names.get(ip)) |error_name| {
10972 if (!seen_errors.contains(error_name) and special_prong != .@"else") {
10973 const msg = maybe_msg orelse blk: {
10974 maybe_msg = try sema.errMsg(
10975 block,
10976 src,
10977 "switch must handle all possibilities",
10978 .{},
10979 );
10980 break :blk maybe_msg.?;
10981 };
1105910982
11060 for (operand_ty.errorSetNames(mod)) |error_name| {
11061 if (!seen_errors.contains(error_name) and special_prong != .@"else") {
11062 const msg = maybe_msg orelse blk: {
11063 maybe_msg = try sema.errMsg(
10983 try sema.errNote(
1106410984 block,
1106510985 src,
11066 "switch must handle all possibilities",
11067 .{},
10986 msg,
10987 "unhandled error value: 'error.{}'",
10988 .{error_name.fmt(ip)},
1106810989 );
11069 break :blk maybe_msg.?;
11070 };
11071
11072 try sema.errNote(
11073 block,
11074 src,
11075 msg,
11076 "unhandled error value: 'error.{}'",
11077 .{error_name.fmt(ip)},
11078 );
10990 }
1107910991 }
11080 }
1108110992
11082 if (maybe_msg) |msg| {
11083 maybe_msg = null;
11084 try sema.addDeclaredHereNote(msg, operand_ty);
11085 return sema.failWithOwnedErrorMsg(msg);
11086 }
10993 if (maybe_msg) |msg| {
10994 maybe_msg = null;
10995 try sema.addDeclaredHereNote(msg, operand_ty);
10996 return sema.failWithOwnedErrorMsg(msg);
10997 }
1108710998
11088 if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames(mod).len) {
11089 // In order to enable common patterns for generic code allow simple else bodies
11090 // else => unreachable,
11091 // else => return,
11092 // else => |e| return e,
11093 // even if all the possible errors were already handled.
11094 const tags = sema.code.instructions.items(.tag);
11095 for (special.body) |else_inst| switch (tags[else_inst]) {
11096 .dbg_block_begin,
11097 .dbg_block_end,
11098 .dbg_stmt,
11099 .dbg_var_val,
11100 .ret_type,
11101 .as_node,
11102 .ret_node,
11103 .@"unreachable",
11104 .@"defer",
11105 .defer_err_code,
11106 .err_union_code,
11107 .ret_err_value_code,
11108 .restore_err_ret_index,
11109 .is_non_err,
11110 .ret_is_non_err,
11111 .condbr,
11112 => {},
11113 else => break,
11114 } else break :else_validation;
10999 if (special_prong == .@"else" and
11000 seen_errors.count() == error_names.len)
11001 {
11002 // In order to enable common patterns for generic code allow simple else bodies
11003 // else => unreachable,
11004 // else => return,
11005 // else => |e| return e,
11006 // even if all the possible errors were already handled.
11007 const tags = sema.code.instructions.items(.tag);
11008 for (special.body) |else_inst| switch (tags[else_inst]) {
11009 .dbg_block_begin,
11010 .dbg_block_end,
11011 .dbg_stmt,
11012 .dbg_var_val,
11013 .ret_type,
11014 .as_node,
11015 .ret_node,
11016 .@"unreachable",
11017 .@"defer",
11018 .defer_err_code,
11019 .err_union_code,
11020 .ret_err_value_code,
11021 .restore_err_ret_index,
11022 .is_non_err,
11023 .ret_is_non_err,
11024 .condbr,
11025 => {},
11026 else => break,
11027 } else break :else_validation;
1111511028
11116 return sema.fail(
11117 block,
11118 special_prong_src,
11119 "unreachable else prong; all cases already handled",
11120 .{},
11121 );
11122 }
11029 return sema.fail(
11030 block,
11031 special_prong_src,
11032 "unreachable else prong; all cases already handled",
11033 .{},
11034 );
11035 }
1112311036
11124 const error_names = operand_ty.errorSetNames(mod);
11125 var names: Module.Fn.InferredErrorSet.NameMap = .{};
11126 try names.ensureUnusedCapacity(sema.arena, error_names.len);
11127 for (error_names) |error_name| {
11128 if (seen_errors.contains(error_name)) continue;
11037 var names: InferredErrorSet.NameMap = .{};
11038 try names.ensureUnusedCapacity(sema.arena, error_names.len);
11039 for (error_names.get(ip)) |error_name| {
11040 if (seen_errors.contains(error_name)) continue;
1112911041
11130 names.putAssumeCapacityNoClobber(error_name, {});
11131 }
11132 // No need to keep the hash map metadata correct; here we
11133 // extract the (sorted) keys only.
11134 else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
11042 names.putAssumeCapacityNoClobber(error_name, {});
11043 }
11044 // No need to keep the hash map metadata correct; here we
11045 // extract the (sorted) keys only.
11046 else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
11047 },
1113511048 }
1113611049 },
1113711050 .Int, .ComptimeInt => {
......@@ -16295,6 +16208,7 @@ fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
1629516208
1629616209fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1629716210 const mod = sema.mod;
16211 const ip = &mod.intern_pool;
1629816212 const inst_data = sema.code.instructions.items(.data)[inst].inst_node;
1629916213 var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?;
1630016214 // Note: The target closure must be in this scope list.
......@@ -16305,8 +16219,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1630516219
1630616220 // Fail this decl if a scope it depended on failed.
1630716221 if (scope.failed()) {
16308 if (sema.owner_func) |owner_func| {
16309 owner_func.state = .dependency_failure;
16222 if (sema.owner_func_index != .none) {
16223 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
1631016224 } else {
1631116225 sema.owner_decl.analysis = .dependency_failure;
1631216226 }
......@@ -16423,8 +16337,8 @@ fn zirBuiltinSrc(
1642316337 const mod = sema.mod;
1642416338 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;
1642516339 const src = LazySrcLoc.nodeOffset(extra.node);
16426 const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{});
16427 const fn_owner_decl = mod.declPtr(func.owner_decl);
16340 if (sema.func_index == .none) return sema.fail(block, src, "@src outside function", .{});
16341 const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index);
1642816342
1642916343 const func_name_val = blk: {
1643016344 var anon_decl = try block.startAnonDecl();
......@@ -16548,10 +16462,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1654816462 const param_info_decl = mod.declPtr(param_info_decl_index);
1654916463 const param_info_ty = param_info_decl.val.toType();
1655016464
16551 const param_vals = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(ty).?.param_types.len);
16465 const func_ty_info = mod.typeToFunc(ty).?;
16466 const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
1655216467 for (param_vals, 0..) |*param_val, i| {
16553 const info = mod.typeToFunc(ty).?;
16554 const param_ty = info.param_types[i];
16468 const param_ty = func_ty_info.param_types.get(ip)[i];
1655516469 const is_generic = param_ty == .generic_poison_type;
1655616470 const param_ty_val = try ip.get(gpa, .{ .opt = .{
1655716471 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),
......@@ -16560,7 +16474,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1656016474
1656116475 const is_noalias = blk: {
1656216476 const index = std.math.cast(u5, i) orelse break :blk false;
16563 break :blk @as(u1, @truncate(info.noalias_bits >> index)) != 0;
16477 break :blk @as(u1, @truncate(func_ty_info.noalias_bits >> index)) != 0;
1656416478 };
1656516479
1656616480 const param_fields = .{
......@@ -16603,23 +16517,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1660316517 } });
1660416518 };
1660516519
16606 const info = mod.typeToFunc(ty).?;
1660716520 const ret_ty_opt = try mod.intern(.{ .opt = .{
1660816521 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),
16609 .val = if (info.return_type == .generic_poison_type) .none else info.return_type,
16522 .val = if (func_ty_info.return_type == .generic_poison_type)
16523 .none
16524 else
16525 func_ty_info.return_type,
1661016526 } });
1661116527
1661216528 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1661316529
1661416530 const field_values = .{
1661516531 // calling_convention: CallingConvention,
16616 (try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(info.cc))).toIntern(),
16532 (try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(),
1661716533 // alignment: comptime_int,
1661816534 (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).toIntern(),
1661916535 // is_generic: bool,
16620 Value.makeBool(info.is_generic).toIntern(),
16536 Value.makeBool(func_ty_info.is_generic).toIntern(),
1662116537 // is_var_args: bool,
16622 Value.makeBool(info.is_var_args).toIntern(),
16538 Value.makeBool(func_ty_info.is_var_args).toIntern(),
1662316539 // return_type: ?type,
1662416540 ret_ty_opt,
1662516541 // args: []const Fn.Param,
......@@ -16860,50 +16776,51 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1686016776
1686116777 try sema.queueFullTypeResolution(error_field_ty);
1686216778
16863 // If the error set is inferred it must be resolved at this point
16864 try sema.resolveInferredErrorSetTy(block, src, ty);
16865
1686616779 // Build our list of Error values
1686716780 // Optional value is only null if anyerror
1686816781 // Value can be zero-length slice otherwise
16869 const error_field_vals = if (ty.isAnyError(mod)) null else blk: {
16870 const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len);
16871 for (vals, 0..) |*field_val, i| {
16872 // TODO: write something like getCoercedInts to avoid needing to dupe
16873 const name = try sema.arena.dupe(u8, ip.stringToSlice(ty.errorSetNames(mod)[i]));
16874 const name_val = v: {
16875 var anon_decl = try block.startAnonDecl();
16876 defer anon_decl.deinit();
16877 const new_decl_ty = try mod.arrayType(.{
16878 .len = name.len,
16879 .child = .u8_type,
16880 });
16881 const new_decl = try anon_decl.finish(
16882 new_decl_ty,
16883 (try mod.intern(.{ .aggregate = .{
16884 .ty = new_decl_ty.toIntern(),
16885 .storage = .{ .bytes = name },
16886 } })).toValue(),
16887 .none, // default alignment
16888 );
16889 break :v try mod.intern(.{ .ptr = .{
16890 .ty = .slice_const_u8_type,
16891 .addr = .{ .decl = new_decl },
16892 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
16893 } });
16894 };
16782 const error_field_vals = switch (try sema.resolveInferredErrorSetTy(block, src, ty.toIntern())) {
16783 .anyerror_type => null,
16784 else => |err_set_ty_index| blk: {
16785 const names = ip.indexToKey(err_set_ty_index).error_set_type.names;
16786 const vals = try sema.arena.alloc(InternPool.Index, names.len);
16787 for (vals, 0..) |*field_val, i| {
16788 // TODO: write something like getCoercedInts to avoid needing to dupe
16789 const name = try sema.arena.dupe(u8, ip.stringToSlice(names.get(ip)[i]));
16790 const name_val = v: {
16791 var anon_decl = try block.startAnonDecl();
16792 defer anon_decl.deinit();
16793 const new_decl_ty = try mod.arrayType(.{
16794 .len = name.len,
16795 .child = .u8_type,
16796 });
16797 const new_decl = try anon_decl.finish(
16798 new_decl_ty,
16799 (try mod.intern(.{ .aggregate = .{
16800 .ty = new_decl_ty.toIntern(),
16801 .storage = .{ .bytes = name },
16802 } })).toValue(),
16803 .none, // default alignment
16804 );
16805 break :v try mod.intern(.{ .ptr = .{
16806 .ty = .slice_const_u8_type,
16807 .addr = .{ .decl = new_decl },
16808 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
16809 } });
16810 };
1689516811
16896 const error_field_fields = .{
16897 // name: []const u8,
16898 name_val,
16899 };
16900 field_val.* = try mod.intern(.{ .aggregate = .{
16901 .ty = error_field_ty.toIntern(),
16902 .storage = .{ .elems = &error_field_fields },
16903 } });
16904 }
16812 const error_field_fields = .{
16813 // name: []const u8,
16814 name_val,
16815 };
16816 field_val.* = try mod.intern(.{ .aggregate = .{
16817 .ty = error_field_ty.toIntern(),
16818 .storage = .{ .elems = &error_field_fields },
16819 } });
16820 }
1690516821
16906 break :blk vals;
16822 break :blk vals;
16823 },
1690716824 };
1690816825
1690916826 // Build our ?[]const Error value
......@@ -18425,9 +18342,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
1842518342 // This is only relevant at runtime.
1842618343 if (start_block.is_comptime or start_block.is_typeof) return;
1842718344
18428 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
18429 if (!sema.owner_func.?.calls_or_awaits_errorable_fn) return;
18430 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;
18345 const mod = sema.mod;
18346 const ip = &mod.intern_pool;
18347
18348 if (!mod.backendSupportsFeature(.error_return_trace)) return;
18349 if (!ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return;
18350 if (!mod.comp.bin_file.options.error_return_tracing) return;
1843118351
1843218352 const tracy = trace(@src());
1843318353 defer tracy.end();
......@@ -18464,17 +18384,30 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
1846418384
1846518385fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {
1846618386 const mod = sema.mod;
18467 const gpa = sema.gpa;
1846818387 const ip = &mod.intern_pool;
1846918388 assert(sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion);
18389 const err_set_ty = sema.fn_ret_ty.errorUnionSet(mod).toIntern();
18390 switch (err_set_ty) {
18391 .adhoc_inferred_error_set_type => {
18392 const ies = sema.fn_ret_ty_ies.?;
18393 assert(ies.func == .none);
18394 try addToInferredErrorSetPtr(mod, ies, sema.typeOf(uncasted_operand));
18395 },
18396 else => if (ip.isInferredErrorSetType(err_set_ty)) {
18397 const ies = sema.fn_ret_ty_ies.?;
18398 assert(ies.func == sema.func_index);
18399 try addToInferredErrorSetPtr(mod, ies, sema.typeOf(uncasted_operand));
18400 },
18401 }
18402}
1847018403
18471 if (mod.typeToInferredErrorSet(sema.fn_ret_ty.errorUnionSet(mod))) |ies| {
18472 const op_ty = sema.typeOf(uncasted_operand);
18473 switch (op_ty.zigTypeTag(mod)) {
18474 .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa),
18475 .ErrorUnion => try ies.addErrorSet(op_ty.errorUnionSet(mod), ip, gpa),
18476 else => {},
18477 }
18404fn addToInferredErrorSetPtr(mod: *Module, ies: *InferredErrorSet, op_ty: Type) !void {
18405 const gpa = mod.gpa;
18406 const ip = &mod.intern_pool;
18407 switch (op_ty.zigTypeTag(mod)) {
18408 .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa),
18409 .ErrorUnion => try ies.addErrorSet(op_ty.errorUnionSet(mod), ip, gpa),
18410 else => {},
1847818411 }
1847918412}
1848018413
......@@ -18488,7 +18421,7 @@ fn analyzeRet(
1848818421 // add the error tag to the inferred error set of the in-scope function, so
1848918422 // that the coercion below works correctly.
1849018423 const mod = sema.mod;
18491 if (sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion) {
18424 if (sema.fn_ret_ty_ies != null and sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion) {
1849218425 try sema.addToInferredErrorSet(uncasted_operand);
1849318426 }
1849418427 const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, .{ .is_ret = true }) catch |err| switch (err) {
......@@ -19461,13 +19394,14 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
1946119394
1946219395fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
1946319396 const mod = sema.mod;
19397 const ip = &mod.intern_pool;
1946419398 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
1946519399 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
1946619400 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
1946719401 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
1946819402
19469 if (sema.owner_func != null and
19470 sema.owner_func.?.calls_or_awaits_errorable_fn and
19403 if (sema.owner_func_index != .none and
19404 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and
1947119405 mod.comp.bin_file.options.error_return_tracing and
1947219406 mod.backendSupportsFeature(.error_return_trace))
1947319407 {
......@@ -19920,7 +19854,7 @@ fn zirReify(
1992019854 return sema.addType(Type.anyerror);
1992119855
1992219856 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));
19923 var names: Module.Fn.InferredErrorSet.NameMap = .{};
19857 var names: InferredErrorSet.NameMap = .{};
1992419858 try names.ensureUnusedCapacity(sema.arena, len);
1992519859 for (0..len) |i| {
1992619860 const elem_val = try payload_val.elemValue(mod, i);
......@@ -20431,8 +20365,6 @@ fn zirReify(
2043120365 .is_var_args = is_var_args,
2043220366 .is_generic = false,
2043320367 .is_noinline = false,
20434 .align_is_generic = false,
20435 .cc_is_generic = false,
2043620368 .section_is_generic = false,
2043720369 .addrspace_is_generic = false,
2043820370 });
......@@ -20936,8 +20868,8 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
2093620868 break :disjoint true;
2093720869 }
2093820870
20939 try sema.resolveInferredErrorSetTy(block, src, dest_ty);
20940 try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty);
20871 _ = try sema.resolveInferredErrorSetTy(block, src, dest_ty.toIntern());
20872 _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty.toIntern());
2094120873 for (dest_ty.errorSetNames(mod)) |dest_err_name| {
2094220874 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name))
2094320875 break :disjoint false;
......@@ -23917,7 +23849,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2391723849 break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);
2391823850 } else target_util.defaultAddressSpace(target, .function);
2391923851
23920 const @"linksection": FuncLinkSection = if (extra.data.bits.has_section_body) blk: {
23852 const section: Section = if (extra.data.bits.has_section_body) blk: {
2392123853 const body_len = sema.code.extra[extra_index];
2392223854 extra_index += 1;
2392323855 const body = sema.code.extra[extra_index..][0..body_len];
......@@ -23926,20 +23858,20 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2392623858 const ty = Type.slice_const_u8;
2392723859 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");
2392823860 if (val.isGenericPoison()) {
23929 break :blk FuncLinkSection{ .generic = {} };
23861 break :blk .generic;
2393023862 }
23931 break :blk FuncLinkSection{ .explicit = try val.toIpString(ty, mod) };
23863 break :blk .{ .explicit = try val.toIpString(ty, mod) };
2393223864 } else if (extra.data.bits.has_section_ref) blk: {
2393323865 const section_ref = @as(Zir.Inst.Ref, @enumFromInt(sema.code.extra[extra_index]));
2393423866 extra_index += 1;
2393523867 const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) {
2393623868 error.GenericPoison => {
23937 break :blk FuncLinkSection{ .generic = {} };
23869 break :blk .generic;
2393823870 },
2393923871 else => |e| return e,
2394023872 };
23941 break :blk FuncLinkSection{ .explicit = section_name };
23942 } else FuncLinkSection{ .default = {} };
23873 break :blk .{ .explicit = section_name };
23874 } else .default;
2394323875
2394423876 const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
2394523877 const body_len = sema.code.extra[extra_index];
......@@ -24013,7 +23945,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2401323945 inst,
2401423946 @"align",
2401523947 @"addrspace",
24016 @"linksection",
23948 section,
2401723949 cc,
2401823950 ret_ty,
2401923951 is_var_args,
......@@ -24846,9 +24778,9 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {
2484624778 const tv = try mod.declPtr(decl_index).typedValue();
2484724779 assert(tv.ty.zigTypeTag(mod) == .Fn);
2484824780 assert(try sema.fnHasRuntimeBits(tv.ty));
24849 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap().?;
24781 const func_index = tv.val.toIntern();
2485024782 try mod.ensureFuncBodyAnalysisQueued(func_index);
24851 mod.panic_func_index = func_index.toOptional();
24783 mod.panic_func_index = func_index;
2485224784 }
2485324785
2485424786 if (mod.null_stack_trace == .none) {
......@@ -24982,7 +24914,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, msg_inst: Air.Inst.Ref) !void {
2498224914
2498324915 try sema.prepareSimplePanic(block);
2498424916
24985 const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?;
24917 const panic_func = mod.funcInfo(mod.panic_func_index);
2498624918 const panic_fn = try sema.analyzeDeclVal(block, .unneeded, panic_func.owner_decl);
2498724919 const null_stack_trace = try sema.addConstant(mod.null_stack_trace.toValue());
2498824920
......@@ -25688,7 +25620,7 @@ fn fieldCallBind(
2568825620 if (mod.typeToFunc(decl_type)) |func_type| f: {
2568925621 if (func_type.param_types.len == 0) break :f;
2569025622
25691 const first_param_type = func_type.param_types[0].toType();
25623 const first_param_type = func_type.param_types.get(ip)[0].toType();
2569225624 // zig fmt: off
2569325625 if (first_param_type.isGenericPoison() or (
2569425626 first_param_type.zigTypeTag(mod) == .Pointer and
......@@ -27526,7 +27458,7 @@ fn coerceExtra(
2752627458 errdefer msg.destroy(sema.gpa);
2752727459
2752827460 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
27529 const src_decl = mod.declPtr(sema.func.?.owner_decl);
27461 const src_decl = mod.funcOwnerDeclPtr(sema.func_index);
2753027462 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});
2753127463 break :msg msg;
2753227464 };
......@@ -27556,9 +27488,11 @@ fn coerceExtra(
2755627488 try in_memory_result.report(sema, block, inst_src, msg);
2755727489
2755827490 // Add notes about function return type
27559 if (opts.is_ret and mod.test_functions.get(sema.func.?.owner_decl) == null) {
27491 if (opts.is_ret and
27492 mod.test_functions.get(mod.funcOwnerDeclIndex(sema.func_index)) == null)
27493 {
2756027494 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
27561 const src_decl = mod.declPtr(sema.func.?.owner_decl);
27495 const src_decl = mod.funcOwnerDeclPtr(sema.func_index);
2756227496 if (inst_ty.isError(mod) and !dest_ty.isError(mod)) {
2756327497 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});
2756427498 } else {
......@@ -28160,42 +28094,29 @@ fn coerceInMemoryAllowedErrorSets(
2816028094 return .ok;
2816128095 }
2816228096
28163 if (mod.typeToInferredErrorSetIndex(dest_ty).unwrap()) |dst_ies_index| {
28164 const dst_ies = mod.inferredErrorSetPtr(dst_ies_index);
28165 // We will make an effort to return `ok` without resolving either error set, to
28166 // avoid unnecessary "unable to resolve error set" dependency loop errors.
28167 switch (src_ty.toIntern()) {
28168 .anyerror_type => {},
28169 else => switch (ip.indexToKey(src_ty.toIntern())) {
28170 .inferred_error_set_type => |src_index| {
28171 // If both are inferred error sets of functions, and
28172 // the dest includes the source function, the coercion is OK.
28173 // This check is important because it works without forcing a full resolution
28174 // of inferred error sets.
28175 if (dst_ies.inferred_error_sets.contains(src_index)) {
28176 return .ok;
28177 }
28178 },
28179 .error_set_type => |error_set_type| {
28180 for (error_set_type.names) |name| {
28181 if (!dst_ies.errors.contains(name)) break;
28182 } else return .ok;
28183 },
28184 else => unreachable,
28185 },
28186 }
28097 if (dest_ty.toIntern() == .adhoc_inferred_error_set_type) {
28098 // We are trying to coerce an error set to the current function's
28099 // inferred error set.
28100 const dst_ies = sema.fn_ret_ty_ies.?;
28101 try dst_ies.addErrorSet(src_ty, ip, gpa);
28102 return .ok;
28103 }
2818728104
28188 if (dst_ies.func == sema.owner_func_index.unwrap()) {
28189 // We are trying to coerce an error set to the current function's
28190 // inferred error set.
28191 try dst_ies.addErrorSet(src_ty, ip, gpa);
28192 return .ok;
28105 if (ip.isInferredErrorSetType(dest_ty.toIntern())) {
28106 const dst_ies_func_index = ip.iesFuncIndex(dest_ty.toIntern());
28107 if (sema.fn_ret_ty_ies) |dst_ies| {
28108 if (dst_ies.func == dst_ies_func_index) {
28109 // We are trying to coerce an error set to the current function's
28110 // inferred error set.
28111 try dst_ies.addErrorSet(src_ty, ip, gpa);
28112 return .ok;
28113 }
2819328114 }
28194
28195 try sema.resolveInferredErrorSet(block, dest_src, dst_ies_index);
28196 // isAnyError might have changed from a false negative to a true positive after resolution.
28197 if (dest_ty.isAnyError(mod)) {
28198 return .ok;
28115 switch (try sema.resolveInferredErrorSet(block, dest_src, dest_ty.toIntern())) {
28116 // isAnyError might have changed from a false negative to a true
28117 // positive after resolution.
28118 .anyerror_type => return .ok,
28119 else => {},
2819928120 }
2820028121 }
2820128122
......@@ -28210,17 +28131,15 @@ fn coerceInMemoryAllowedErrorSets(
2821028131 },
2821128132
2821228133 else => switch (ip.indexToKey(src_ty.toIntern())) {
28213 .inferred_error_set_type => |src_index| {
28214 const src_data = mod.inferredErrorSetPtr(src_index);
28215
28216 try sema.resolveInferredErrorSet(block, src_src, src_index);
28134 .inferred_error_set_type => {
28135 const resolved_src_ty = try sema.resolveInferredErrorSet(block, src_src, src_ty.toIntern());
2821728136 // src anyerror status might have changed after the resolution.
28218 if (src_ty.isAnyError(mod)) {
28137 if (resolved_src_ty == .anyerror_type) {
2821928138 // dest_ty.isAnyError(mod) == true is already checked for at this point.
2822028139 return .from_anyerror;
2822128140 }
2822228141
28223 for (src_data.errors.keys()) |key| {
28142 for (ip.indexToKey(resolved_src_ty).error_set_type.names.get(ip)) |key| {
2822428143 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) {
2822528144 try missing_error_buf.append(key);
2822628145 }
......@@ -28235,7 +28154,7 @@ fn coerceInMemoryAllowedErrorSets(
2823528154 return .ok;
2823628155 },
2823728156 .error_set_type => |error_set_type| {
28238 for (error_set_type.names) |name| {
28157 for (error_set_type.names.get(ip)) |name| {
2823928158 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) {
2824028159 try missing_error_buf.append(name);
2824128160 }
......@@ -28264,11 +28183,12 @@ fn coerceInMemoryAllowedFns(
2826428183 src_src: LazySrcLoc,
2826528184) !InMemoryCoercionResult {
2826628185 const mod = sema.mod;
28186 const ip = &mod.intern_pool;
2826728187
28268 {
28269 const dest_info = mod.typeToFunc(dest_ty).?;
28270 const src_info = mod.typeToFunc(src_ty).?;
28188 const dest_info = mod.typeToFunc(dest_ty).?;
28189 const src_info = mod.typeToFunc(src_ty).?;
2827128190
28191 {
2827228192 if (dest_info.is_var_args != src_info.is_var_args) {
2827328193 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
2827428194 }
......@@ -28302,9 +28222,6 @@ fn coerceInMemoryAllowedFns(
2830228222 }
2830328223
2830428224 const params_len = params_len: {
28305 const dest_info = mod.typeToFunc(dest_ty).?;
28306 const src_info = mod.typeToFunc(src_ty).?;
28307
2830828225 if (dest_info.param_types.len != src_info.param_types.len) {
2830928226 return InMemoryCoercionResult{ .fn_param_count = .{
2831028227 .actual = src_info.param_types.len,
......@@ -28323,13 +28240,10 @@ fn coerceInMemoryAllowedFns(
2832328240 };
2832428241
2832528242 for (0..params_len) |param_i| {
28326 const dest_info = mod.typeToFunc(dest_ty).?;
28327 const src_info = mod.typeToFunc(src_ty).?;
28328
28329 const dest_param_ty = dest_info.param_types[param_i].toType();
28330 const src_param_ty = src_info.param_types[param_i].toType();
28243 const dest_param_ty = dest_info.param_types.get(ip)[param_i].toType();
28244 const src_param_ty = src_info.param_types.get(ip)[param_i].toType();
2833128245
28332 const param_i_small = @as(u5, @intCast(param_i));
28246 const param_i_small: u5 = @intCast(param_i);
2833328247 if (dest_info.paramIsComptime(param_i_small) != src_info.paramIsComptime(param_i_small)) {
2833428248 return InMemoryCoercionResult{ .fn_param_comptime = .{
2833528249 .index = param_i,
......@@ -30471,6 +30385,7 @@ fn addReferencedBy(
3047130385
3047230386fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
3047330387 const mod = sema.mod;
30388 const ip = &mod.intern_pool;
3047430389 const decl = mod.declPtr(decl_index);
3047530390 if (decl.analysis == .in_progress) {
3047630391 const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(mod), "dependency loop detected", .{});
......@@ -30478,8 +30393,8 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
3047830393 }
3047930394
3048030395 mod.ensureDeclAnalyzed(decl_index) catch |err| {
30481 if (sema.owner_func) |owner_func| {
30482 owner_func.state = .dependency_failure;
30396 if (sema.owner_func_index != .none) {
30397 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
3048330398 } else {
3048430399 sema.owner_decl.analysis = .dependency_failure;
3048530400 }
......@@ -30487,10 +30402,12 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
3048730402 };
3048830403}
3048930404
30490fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void {
30491 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
30492 if (sema.owner_func) |owner_func| {
30493 owner_func.state = .dependency_failure;
30405fn ensureFuncBodyAnalyzed(sema: *Sema, func: InternPool.Index) CompileError!void {
30406 const mod = sema.mod;
30407 const ip = &mod.intern_pool;
30408 mod.ensureFuncBodyAnalyzed(func) catch |err| {
30409 if (sema.owner_func_index != .none) {
30410 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
3049430411 } else {
3049530412 sema.owner_decl.analysis = .dependency_failure;
3049630413 }
......@@ -30566,7 +30483,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {
3056630483 const tv = try decl.typedValue();
3056730484 if (tv.ty.zigTypeTag(mod) != .Fn) return;
3056830485 if (!try sema.fnHasRuntimeBits(tv.ty)) return;
30569 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn
30486 const func_index = tv.val.toIntern();
30487 if (!mod.intern_pool.isFuncBody(func_index)) return; // undef or extern function
3057030488 try mod.ensureFuncBodyAnalysisQueued(func_index);
3057130489}
3057230490
......@@ -30582,7 +30500,7 @@ fn analyzeRef(
3058230500 if (try sema.resolveMaybeUndefVal(operand)) |val| {
3058330501 switch (mod.intern_pool.indexToKey(val.toIntern())) {
3058430502 .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),
30585 .func => |func| return sema.analyzeDeclRef(mod.funcPtr(func.index).owner_decl),
30503 .func => |func| return sema.analyzeDeclRef(func.owner_decl),
3058630504 else => {},
3058730505 }
3058830506 var anon_decl = try block.startAnonDecl();
......@@ -30752,73 +30670,85 @@ fn analyzeIsNonErrComptimeOnly(
3075230670 operand: Air.Inst.Ref,
3075330671) CompileError!Air.Inst.Ref {
3075430672 const mod = sema.mod;
30673 const ip = &mod.intern_pool;
3075530674 const operand_ty = sema.typeOf(operand);
3075630675 const ot = operand_ty.zigTypeTag(mod);
30757 if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true;
30758 if (ot == .ErrorSet) return Air.Inst.Ref.bool_false;
30676 if (ot != .ErrorSet and ot != .ErrorUnion) return .bool_true;
30677 if (ot == .ErrorSet) return .bool_false;
3075930678 assert(ot == .ErrorUnion);
3076030679
3076130680 const payload_ty = operand_ty.errorUnionPayload(mod);
3076230681 if (payload_ty.zigTypeTag(mod) == .NoReturn) {
30763 return Air.Inst.Ref.bool_false;
30682 return .bool_false;
3076430683 }
3076530684
3076630685 if (Air.refToIndex(operand)) |operand_inst| {
3076730686 switch (sema.air_instructions.items(.tag)[operand_inst]) {
30768 .wrap_errunion_payload => return Air.Inst.Ref.bool_true,
30769 .wrap_errunion_err => return Air.Inst.Ref.bool_false,
30687 .wrap_errunion_payload => return .bool_true,
30688 .wrap_errunion_err => return .bool_false,
3077030689 else => {},
3077130690 }
3077230691 } else if (operand == .undef) {
3077330692 return sema.addConstUndef(Type.bool);
3077430693 } else if (@intFromEnum(operand) < InternPool.static_len) {
3077530694 // None of the ref tags can be errors.
30776 return Air.Inst.Ref.bool_true;
30695 return .bool_true;
3077730696 }
3077830697
3077930698 const maybe_operand_val = try sema.resolveMaybeUndefVal(operand);
3078030699
3078130700 // exception if the error union error set is known to be empty,
3078230701 // we allow the comparison but always make it comptime-known.
30783 const set_ty = operand_ty.errorUnionSet(mod);
30784 switch (set_ty.toIntern()) {
30702 const set_ty = ip.errorUnionSet(operand_ty.toIntern());
30703 switch (set_ty) {
3078530704 .anyerror_type => {},
30786 else => switch (mod.intern_pool.indexToKey(set_ty.toIntern())) {
30705 else => switch (ip.indexToKey(set_ty)) {
3078730706 .error_set_type => |error_set_type| {
30788 if (error_set_type.names.len == 0) return Air.Inst.Ref.bool_true;
30707 if (error_set_type.names.len == 0) return .bool_true;
3078930708 },
30790 .inferred_error_set_type => |ies_index| blk: {
30709 .inferred_error_set_type => |func_index| blk: {
3079130710 // If the error set is empty, we must return a comptime true or false.
3079230711 // However we want to avoid unnecessarily resolving an inferred error set
3079330712 // in case it is already non-empty.
30794 const ies = mod.inferredErrorSetPtr(ies_index);
30795 if (ies.is_anyerror) break :blk;
30796 if (ies.errors.count() != 0) break :blk;
30713 switch (ip.funcIesResolved(func_index).*) {
30714 .anyerror_type => break :blk,
30715 .none => {},
30716 else => |i| if (ip.indexToKey(i).error_set_type.names.len != 0) break :blk,
30717 }
3079730718 if (maybe_operand_val == null) {
30798 // Try to avoid resolving inferred error set if possible.
30799 if (ies.errors.count() != 0) break :blk;
30800 if (ies.is_anyerror) break :blk;
30801 for (ies.inferred_error_sets.keys()) |other_ies_index| {
30802 if (ies_index == other_ies_index) continue;
30803 try sema.resolveInferredErrorSet(block, src, other_ies_index);
30804 const other_ies = mod.inferredErrorSetPtr(other_ies_index);
30805 if (other_ies.is_anyerror) {
30806 ies.is_anyerror = true;
30807 ies.is_resolved = true;
30808 break :blk;
30719 if (sema.fn_ret_ty_ies) |ies| {
30720 if (set_ty == .adhoc_inferred_error_set_type or
30721 ies.func == func_index)
30722 {
30723 // Try to avoid resolving inferred error set if possible.
30724 if (ies.errors.count() != 0) return .none;
30725 switch (ies.resolved) {
30726 .anyerror_type => return .none,
30727 .none => {},
30728 else => switch (ip.indexToKey(ies.resolved).error_set_type.names.len) {
30729 0 => return .bool_true,
30730 else => return .none,
30731 },
30732 }
30733 for (ies.inferred_error_sets.keys()) |other_ies_index| {
30734 if (set_ty == other_ies_index) continue;
30735 const other_resolved =
30736 try sema.resolveInferredErrorSet(block, src, other_ies_index);
30737 if (other_resolved == .anyerror_type) {
30738 ies.resolved = .anyerror_type;
30739 return .none;
30740 }
30741 if (ip.indexToKey(other_resolved).error_set_type.names.len != 0)
30742 return .none;
30743 }
30744 return .bool_true;
3080930745 }
30810
30811 if (other_ies.errors.count() != 0) break :blk;
3081230746 }
30813 if (ies.func == sema.owner_func_index.unwrap()) {
30814 // We're checking the inferred errorset of the current function and none of
30815 // its child inferred error sets contained any errors meaning that any value
30816 // so far with this type can't contain errors either.
30817 return Air.Inst.Ref.bool_true;
30818 }
30819 try sema.resolveInferredErrorSet(block, src, ies_index);
30820 if (ies.is_anyerror) break :blk;
30821 if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true;
30747 const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty);
30748 if (resolved_ty == .anyerror_type)
30749 break :blk;
30750 if (ip.indexToKey(resolved_ty).error_set_type.names.len == 0)
30751 return .bool_true;
3082230752 }
3082330753 },
3082430754 else => unreachable,
......@@ -30830,12 +30760,12 @@ fn analyzeIsNonErrComptimeOnly(
3083030760 return sema.addConstUndef(Type.bool);
3083130761 }
3083230762 if (err_union.getErrorName(mod) == .none) {
30833 return Air.Inst.Ref.bool_true;
30763 return .bool_true;
3083430764 } else {
30835 return Air.Inst.Ref.bool_false;
30765 return .bool_false;
3083630766 }
3083730767 }
30838 return Air.Inst.Ref.none;
30768 return .none;
3083930769}
3084030770
3084130771fn analyzeIsNonErr(
......@@ -31768,24 +31698,39 @@ fn wrapErrorUnionSet(
3176831698 const inst_ty = sema.typeOf(inst);
3176931699 const dest_err_set_ty = dest_ty.errorUnionSet(mod);
3177031700 if (try sema.resolveMaybeUndefVal(inst)) |val| {
31701 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
3177131702 switch (dest_err_set_ty.toIntern()) {
3177231703 .anyerror_type => {},
31704 .adhoc_inferred_error_set_type => ok: {
31705 const ies = sema.fn_ret_ty_ies.?;
31706 switch (ies.resolved) {
31707 .anyerror_type => break :ok,
31708 .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
31709 break :ok;
31710 },
31711 else => |i| if (ip.indexToKey(i).error_set_type.nameIndex(ip, expected_name) != null) {
31712 break :ok;
31713 },
31714 }
31715 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
31716 },
3177331717 else => switch (ip.indexToKey(dest_err_set_ty.toIntern())) {
3177431718 .error_set_type => |error_set_type| ok: {
31775 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
3177631719 if (error_set_type.nameIndex(ip, expected_name) != null) break :ok;
3177731720 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
3177831721 },
31779 .inferred_error_set_type => |ies_index| ok: {
31780 const ies = mod.inferredErrorSetPtr(ies_index);
31781 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
31782
31722 .inferred_error_set_type => |func_index| ok: {
3178331723 // We carefully do this in an order that avoids unnecessarily
3178431724 // resolving the destination error set type.
31785 if (ies.is_anyerror) break :ok;
31786
31787 if (ies.errors.contains(expected_name)) break :ok;
31788 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) break :ok;
31725 switch (ip.funcIesResolved(func_index).*) {
31726 .anyerror_type => break :ok,
31727 .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
31728 break :ok;
31729 },
31730 else => |i| if (ip.indexToKey(i).error_set_type.nameIndex(ip, expected_name) != null) {
31731 break :ok;
31732 },
31733 }
3178931734
3179031735 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
3179131736 },
......@@ -31794,9 +31739,7 @@ fn wrapErrorUnionSet(
3179431739 }
3179531740 return sema.addConstant((try mod.intern(.{ .error_union = .{
3179631741 .ty = dest_ty.toIntern(),
31797 .val = .{
31798 .err_name = mod.intern_pool.indexToKey(try val.intern(dest_err_set_ty, mod)).err.name,
31799 },
31742 .val = .{ .err_name = expected_name },
3180031743 } })).toValue());
3180131744 }
3180231745
......@@ -33273,17 +33216,31 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike {
3327333216 };
3327433217}
3327533218
33219pub fn resolveIes(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError!void {
33220 const mod = sema.mod;
33221 const ip = &mod.intern_pool;
33222
33223 if (sema.fn_ret_ty_ies) |ies| {
33224 try sema.resolveInferredErrorSetPtr(block, src, ies);
33225 assert(ies.resolved != .none);
33226 ip.funcIesResolved(sema.func_index).* = ies.resolved;
33227 }
33228}
33229
3327633230pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
3327733231 const mod = sema.mod;
33278 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.return_type.toType());
33232 const ip = &mod.intern_pool;
33233 const fn_ty_info = mod.typeToFunc(fn_ty).?;
33234
33235 try sema.resolveTypeFully(fn_ty_info.return_type.toType());
3327933236
33280 if (mod.comp.bin_file.options.error_return_tracing and mod.typeToFunc(fn_ty).?.return_type.toType().isError(mod)) {
33237 if (mod.comp.bin_file.options.error_return_tracing and fn_ty_info.return_type.toType().isError(mod)) {
3328133238 // Ensure the type exists so that backends can assume that.
3328233239 _ = try sema.getBuiltinType("StackTrace");
3328333240 }
3328433241
33285 for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| {
33286 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType());
33242 for (0..fn_ty_info.param_types.len) |i| {
33243 try sema.resolveTypeFully(fn_ty_info.param_types.get(ip)[i].toType());
3328733244 }
3328833245}
3328933246
......@@ -33448,7 +33405,9 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
3344833405 // the function is instantiated.
3344933406 return;
3345033407 }
33451 for (info.param_types) |param_ty| {
33408 const ip = &mod.intern_pool;
33409 for (0..info.param_types.len) |i| {
33410 const param_ty = info.param_types.get(ip)[i];
3345233411 try sema.resolveTypeLayout(param_ty.toType());
3345333412 }
3345433413 try sema.resolveTypeLayout(info.return_type.toType());
......@@ -33578,10 +33537,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3357833537 .code = zir,
3357933538 .owner_decl = decl,
3358033539 .owner_decl_index = decl_index,
33581 .func = null,
3358233540 .func_index = .none,
3358333541 .fn_ret_ty = Type.void,
33584 .owner_func = null,
33542 .fn_ret_ty_ies = null,
3358533543 .owner_func_index = .none,
3358633544 .comptime_mutable_decls = &comptime_mutable_decls,
3358733545 };
......@@ -33600,10 +33558,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3360033558 .inlining = null,
3360133559 .is_comptime = true,
3360233560 };
33603 defer {
33604 assert(block.instructions.items.len == 0);
33605 block.params.deinit(gpa);
33606 }
33561 defer assert(block.instructions.items.len == 0);
3360733562
3360833563 const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 };
3360933564 const backing_int_ty = blk: {
......@@ -33633,10 +33588,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3363333588 .code = zir,
3363433589 .owner_decl = decl,
3363533590 .owner_decl_index = decl_index,
33636 .func = null,
3363733591 .func_index = .none,
3363833592 .fn_ret_ty = Type.void,
33639 .owner_func = null,
33593 .fn_ret_ty_ies = null,
3364033594 .owner_func_index = .none,
3364133595 .comptime_mutable_decls = undefined,
3364233596 };
......@@ -33808,6 +33762,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3380833762 .bool,
3380933763 .void,
3381033764 .anyerror,
33765 .adhoc_inferred_error_set,
3381133766 .noreturn,
3381233767 .generic_poison,
3381333768 .atomic_order,
......@@ -33943,7 +33898,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
3394333898 // the function is instantiated.
3394433899 return;
3394533900 }
33946 for (info.param_types) |param_ty| {
33901 const ip = &mod.intern_pool;
33902 for (0..info.param_types.len) |i| {
33903 const param_ty = info.param_types.get(ip)[i];
3394733904 try sema.resolveTypeFully(param_ty.toType());
3394833905 }
3394933906 try sema.resolveTypeFully(info.return_type.toType());
......@@ -34056,6 +34013,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
3405634013 .void_type,
3405734014 .type_type,
3405834015 .anyerror_type,
34016 .adhoc_inferred_error_set_type,
3405934017 .comptime_int_type,
3406034018 .comptime_float_type,
3406134019 .noreturn_type,
......@@ -34209,29 +34167,28 @@ fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_obj: *Module.Union) Compi
3420934167 union_obj.status = .have_field_types;
3421034168}
3421134169
34170/// Returns a normal error set corresponding to the fully populated inferred
34171/// error set.
3421234172fn resolveInferredErrorSet(
3421334173 sema: *Sema,
3421434174 block: *Block,
3421534175 src: LazySrcLoc,
34216 ies_index: Module.Fn.InferredErrorSet.Index,
34217) CompileError!void {
34176 ies_index: InternPool.Index,
34177) CompileError!InternPool.Index {
3421834178 const mod = sema.mod;
34219 const ies = mod.inferredErrorSetPtr(ies_index);
34220
34221 if (ies.is_resolved) return;
34222
34223 const func = mod.funcPtr(ies.func);
34224 if (func.state == .in_progress) {
34179 const ip = &mod.intern_pool;
34180 const func_index = ip.iesFuncIndex(ies_index);
34181 const func = mod.funcInfo(func_index);
34182 const resolved_ty = func.resolvedErrorSet(ip).*;
34183 if (resolved_ty != .none) return resolved_ty;
34184 if (func.analysis(ip).state == .in_progress)
3422534185 return sema.fail(block, src, "unable to resolve inferred error set", .{});
34226 }
3422734186
34228 // In order to ensure that all dependencies are properly added to the set, we
34229 // need to ensure the function body is analyzed of the inferred error set.
34230 // However, in the case of comptime/inline function calls with inferred error sets,
34231 // each call gets a new InferredErrorSet object, which contains the same
34232 // `Module.Fn.Index`. Not only is the function not relevant to the inferred error set
34233 // in this case, it may be a generic function which would cause an assertion failure
34234 // if we called `ensureFuncBodyAnalyzed` on it here.
34187 // In order to ensure that all dependencies are properly added to the set,
34188 // we need to ensure the function body is analyzed of the inferred error
34189 // set. However, in the case of comptime/inline function calls with
34190 // inferred error sets, each call gets an adhoc InferredErrorSet object, which
34191 // has no corresponding function body.
3423534192 const ies_func_owner_decl = mod.declPtr(func.owner_decl);
3423634193 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;
3423734194 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
......@@ -34239,7 +34196,7 @@ fn resolveInferredErrorSet(
3423934196 // so here we can simply skip this case.
3424034197 if (ies_func_info.return_type == .generic_poison_type) {
3424134198 assert(ies_func_info.cc == .Inline);
34242 } else if (mod.typeToInferredErrorSet(ies_func_info.return_type.toType().errorUnionSet(mod)).? == ies) {
34199 } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) {
3424334200 if (ies_func_info.is_generic) {
3424434201 const msg = msg: {
3424534202 const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{});
......@@ -34252,33 +34209,101 @@ fn resolveInferredErrorSet(
3425234209 }
3425334210 // In this case we are dealing with the actual InferredErrorSet object that
3425434211 // corresponds to the function, not one created to track an inline/comptime call.
34255 try sema.ensureFuncBodyAnalyzed(ies.func);
34212 try sema.ensureFuncBodyAnalyzed(func_index);
3425634213 }
3425734214
34258 ies.is_resolved = true;
34215 // This will now have been resolved by the logic at the end of `Module.analyzeFnBody`
34216 // which calls `resolveInferredErrorSetPtr`.
34217 const final_resolved_ty = func.resolvedErrorSet(ip).*;
34218 assert(final_resolved_ty != .none);
34219 return final_resolved_ty;
34220}
34221
34222pub fn resolveInferredErrorSetPtr(
34223 sema: *Sema,
34224 block: *Block,
34225 src: LazySrcLoc,
34226 ies: *InferredErrorSet,
34227) CompileError!void {
34228 const mod = sema.mod;
34229 const ip = &mod.intern_pool;
34230
34231 if (ies.resolved != .none) return;
34232
34233 const ies_index = ip.errorUnionSet(sema.fn_ret_ty.toIntern());
3425934234
3426034235 for (ies.inferred_error_sets.keys()) |other_ies_index| {
3426134236 if (ies_index == other_ies_index) continue;
34262 try sema.resolveInferredErrorSet(block, src, other_ies_index);
34263
34264 const other_ies = mod.inferredErrorSetPtr(other_ies_index);
34265 for (other_ies.errors.keys()) |key| {
34266 try ies.errors.put(sema.gpa, key, {});
34237 switch (try sema.resolveInferredErrorSet(block, src, other_ies_index)) {
34238 .anyerror_type => {
34239 ies.resolved = .anyerror_type;
34240 return;
34241 },
34242 else => |error_set_ty_index| {
34243 const names = ip.indexToKey(error_set_ty_index).error_set_type.names;
34244 for (names.get(ip)) |name| {
34245 try ies.errors.put(sema.arena, name, {});
34246 }
34247 },
3426734248 }
34268 if (other_ies.is_anyerror)
34269 ies.is_anyerror = true;
3427034249 }
34250
34251 const resolved_error_set_ty = try mod.errorSetFromUnsortedNames(ies.errors.keys());
34252 ies.resolved = resolved_error_set_ty.toIntern();
34253}
34254
34255fn resolveAdHocInferredErrorSet(
34256 sema: *Sema,
34257 block: *Block,
34258 src: LazySrcLoc,
34259 value: InternPool.Index,
34260) CompileError!InternPool.Index {
34261 const mod = sema.mod;
34262 const gpa = sema.gpa;
34263 const ip = &mod.intern_pool;
34264 const new_ty = try resolveAdHocInferredErrorSetTy(sema, block, src, ip.typeOf(value));
34265 if (new_ty == .none) return value;
34266 return ip.getCoerced(gpa, value, new_ty);
34267}
34268
34269fn resolveAdHocInferredErrorSetTy(
34270 sema: *Sema,
34271 block: *Block,
34272 src: LazySrcLoc,
34273 ty: InternPool.Index,
34274) CompileError!InternPool.Index {
34275 const ies = sema.fn_ret_ty_ies orelse return .none;
34276 const mod = sema.mod;
34277 const gpa = sema.gpa;
34278 const ip = &mod.intern_pool;
34279 const error_union_info = switch (ip.indexToKey(ty)) {
34280 .error_union_type => |x| x,
34281 else => return .none,
34282 };
34283 if (error_union_info.error_set_type != .adhoc_inferred_error_set_type)
34284 return .none;
34285
34286 try sema.resolveInferredErrorSetPtr(block, src, ies);
34287 const new_ty = try ip.get(gpa, .{ .error_union_type = .{
34288 .error_set_type = ies.resolved,
34289 .payload_type = error_union_info.payload_type,
34290 } });
34291 return new_ty;
3427134292}
3427234293
3427334294fn resolveInferredErrorSetTy(
3427434295 sema: *Sema,
3427534296 block: *Block,
3427634297 src: LazySrcLoc,
34277 ty: Type,
34278) CompileError!void {
34298 ty: InternPool.Index,
34299) CompileError!InternPool.Index {
3427934300 const mod = sema.mod;
34280 if (mod.typeToInferredErrorSetIndex(ty).unwrap()) |ies_index| {
34281 try sema.resolveInferredErrorSet(block, src, ies_index);
34301 const ip = &mod.intern_pool;
34302 if (ty == .anyerror_type) return ty;
34303 switch (ip.indexToKey(ty)) {
34304 .error_set_type => return ty,
34305 .inferred_error_set_type => return sema.resolveInferredErrorSet(block, src, ty),
34306 else => unreachable,
3428234307 }
3428334308}
3428434309
......@@ -34346,10 +34371,9 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3434634371 .code = zir,
3434734372 .owner_decl = decl,
3434834373 .owner_decl_index = decl_index,
34349 .func = null,
3435034374 .func_index = .none,
3435134375 .fn_ret_ty = Type.void,
34352 .owner_func = null,
34376 .fn_ret_ty_ies = null,
3435334377 .owner_func_index = .none,
3435434378 .comptime_mutable_decls = &comptime_mutable_decls,
3435534379 };
......@@ -34368,10 +34392,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3436834392 .inlining = null,
3436934393 .is_comptime = true,
3437034394 };
34371 defer {
34372 assert(block_scope.instructions.items.len == 0);
34373 block_scope.params.deinit(gpa);
34374 }
34395 defer assert(block_scope.instructions.items.len == 0);
3437534396
3437634397 struct_obj.fields = .{};
3437734398 try struct_obj.fields.ensureTotalCapacity(mod.tmp_hack_arena.allocator(), fields_len);
......@@ -34693,10 +34714,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3469334714 .code = zir,
3469434715 .owner_decl = decl,
3469534716 .owner_decl_index = decl_index,
34696 .func = null,
3469734717 .func_index = .none,
3469834718 .fn_ret_ty = Type.void,
34699 .owner_func = null,
34719 .fn_ret_ty_ies = null,
3470034720 .owner_func_index = .none,
3470134721 .comptime_mutable_decls = &comptime_mutable_decls,
3470234722 };
......@@ -34715,10 +34735,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3471534735 .inlining = null,
3471634736 .is_comptime = true,
3471734737 };
34718 defer {
34719 assert(block_scope.instructions.items.len == 0);
34720 block_scope.params.deinit(gpa);
34721 }
34738 defer assert(block_scope.instructions.items.len == 0);
3472234739
3472334740 if (body.len != 0) {
3472434741 try sema.analyzeBody(&block_scope, body);
......@@ -35050,7 +35067,7 @@ fn generateUnionTagTypeNumbered(
3505035067 errdefer mod.destroyDecl(new_decl_index);
3505135068 const fqn = try union_obj.getFullyQualifiedName(mod);
3505235069 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});
35053 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
35070 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
3505435071 .ty = Type.noreturn,
3505535072 .val = Value.@"unreachable",
3505635073 }, name);
......@@ -35101,7 +35118,7 @@ fn generateUnionTagTypeSimple(
3510135118 errdefer mod.destroyDecl(new_decl_index);
3510235119 const fqn = try union_obj.getFullyQualifiedName(mod);
3510335120 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});
35104 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
35121 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{
3510535122 .ty = Type.noreturn,
3510635123 .val = Value.@"unreachable",
3510735124 }, name);
......@@ -35148,10 +35165,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
3514835165 .inlining = null,
3514935166 .is_comptime = true,
3515035167 };
35151 defer {
35152 block.instructions.deinit(gpa);
35153 block.params.deinit(gpa);
35154 }
35168 defer block.instructions.deinit(gpa);
3515535169
3515635170 const decl_index = try getBuiltinDecl(sema, &block, name);
3515735171 return sema.analyzeDeclVal(&block, src, decl_index);
......@@ -35202,10 +35216,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
3520235216 .inlining = null,
3520335217 .is_comptime = true,
3520435218 };
35205 defer {
35206 block.instructions.deinit(sema.gpa);
35207 block.params.deinit(sema.gpa);
35208 }
35219 defer block.instructions.deinit(sema.gpa);
3520935220 const src = LazySrcLoc.nodeOffset(0);
3521035221
3521135222 const result_ty = sema.analyzeAsType(&block, src, ty_inst) catch |err| switch (err) {
......@@ -35261,6 +35272,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3526135272 .bool_type,
3526235273 .type_type,
3526335274 .anyerror_type,
35275 .adhoc_inferred_error_set_type,
3526435276 .comptime_int_type,
3526535277 .comptime_float_type,
3526635278 .enum_literal_type,
......@@ -35314,6 +35326,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3531435326 .var_args_param_type,
3531535327 .none,
3531635328 => unreachable,
35329
3531735330 _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
3531835331 .type_int_signed, // i0 handled above
3531935332 .type_int_unsigned, // u0 handled above
......@@ -35322,11 +35335,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3532235335 .type_optional, // ?noreturn handled above
3532335336 .type_anyframe,
3532435337 .type_error_union,
35338 .type_anyerror_union,
3532535339 .type_error_set,
3532635340 .type_inferred_error_set,
3532735341 .type_opaque,
3532835342 .type_function,
3532935343 => null,
35344
3533035345 .simple_type, // handled above
3533135346 // values, not types
3533235347 .undef,
......@@ -35370,7 +35385,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3537035385 .float_comptime_float,
3537135386 .variable,
3537235387 .extern_func,
35373 .func,
35388 .func_decl,
35389 .func_instance,
35390 .func_coerced,
3537435391 .only_possible_value,
3537535392 .union_value,
3537635393 .bytes,
......@@ -35379,6 +35396,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3537935396 // memoized value, not types
3538035397 .memoized_call,
3538135398 => unreachable,
35399
3538235400 .type_array_big,
3538335401 .type_array_small,
3538435402 .type_vector,
......@@ -35911,6 +35929,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3591135929 .prefetch_options,
3591235930 .export_options,
3591335931 .extern_options,
35932 .adhoc_inferred_error_set,
3591435933 => false,
3591535934
3591635935 .type,
......@@ -36772,7 +36791,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {
3677236791 const arena = sema.arena;
3677336792 const lhs_names = lhs.errorSetNames(mod);
3677436793 const rhs_names = rhs.errorSetNames(mod);
36775 var names: Module.Fn.InferredErrorSet.NameMap = .{};
36794 var names: InferredErrorSet.NameMap = .{};
3677636795 try names.ensureUnusedCapacity(arena, lhs_names.len);
3677736796
3677836797 for (lhs_names) |name| {
src/TypedValue.zig+1-1
......@@ -205,7 +205,7 @@ pub fn print(
205205 mod.declPtr(extern_func.decl).name.fmt(ip),
206206 }),
207207 .func => |func| return writer.print("(function '{}')", .{
208 mod.declPtr(mod.funcPtr(func.index).owner_decl).name.fmt(ip),
208 mod.declPtr(func.owner_decl).name.fmt(ip),
209209 }),
210210 .int => |int| switch (int.storage) {
211211 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
src/Zir.zig+20-4
......@@ -65,9 +65,13 @@ pub const ExtraIndex = enum(u32) {
6565 _,
6666};
6767
68fn ExtraData(comptime T: type) type {
69 return struct { data: T, end: usize };
70}
71
6872/// Returns the requested data, as well as the new index which is at the start of the
6973/// trailers for the object.
70pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, end: usize } {
74pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
7175 const fields = @typeInfo(T).Struct.fields;
7276 var i: usize = index;
7377 var result: T = undefined;
......@@ -90,13 +94,24 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
9094 };
9195}
9296
93/// Given an index into `string_bytes` returns the null-terminated string found there.
97/// TODO migrate to use this for type safety
98pub const NullTerminatedString = enum(u32) {
99 _,
100};
101
102/// TODO: migrate to nullTerminatedString2 for type safety
94103pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {
95 var end: usize = index;
104 return nullTerminatedString2(code, @enumFromInt(index));
105}
106
107/// Given an index into `string_bytes` returns the null-terminated string found there.
108pub fn nullTerminatedString2(code: Zir, index: NullTerminatedString) [:0]const u8 {
109 const start = @intFromEnum(index);
110 var end: u32 = start;
96111 while (code.string_bytes[end] != 0) {
97112 end += 1;
98113 }
99 return code.string_bytes[index..end :0];
114 return code.string_bytes[start..end :0];
100115}
101116
102117pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
......@@ -2076,6 +2091,7 @@ pub const Inst = struct {
20762091 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
20772092 optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),
20782093 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),
2094 adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type),
20792095 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
20802096 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),
20812097 undef = @intFromEnum(InternPool.Index.undef),
src/arch/aarch64/CodeGen.zig+36-31
......@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
1313const TypedValue = @import("../../TypedValue.zig");
1414const link = @import("../../link.zig");
1515const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");
1617const Compilation = @import("../../Compilation.zig");
1718const ErrorMsg = Module.ErrorMsg;
1819const Target = std.Target;
......@@ -49,7 +50,8 @@ liveness: Liveness,
4950bin_file: *link.File,
5051debug_output: DebugInfoOutput,
5152target: *const std.Target,
52mod_fn: *const Module.Fn,
53func_index: InternPool.Index,
54owner_decl: Module.Decl.Index,
5355err_msg: ?*ErrorMsg,
5456args: []MCValue,
5557ret_mcv: MCValue,
......@@ -199,7 +201,7 @@ const DbgInfoReloc = struct {
199201 else => unreachable, // not a possible argument
200202
201203 };
202 try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc);
204 try dw.genArgDbgInfo(reloc.name, reloc.ty, function.owner_decl, loc);
203205 },
204206 .plan9 => {},
205207 .none => {},
......@@ -245,7 +247,7 @@ const DbgInfoReloc = struct {
245247 break :blk .nop;
246248 },
247249 };
248 try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc);
250 try dw.genVarDbgInfo(reloc.name, reloc.ty, function.owner_decl, is_ptr, loc);
249251 },
250252 .plan9 => {},
251253 .none => {},
......@@ -328,7 +330,7 @@ const Self = @This();
328330pub fn generate(
329331 bin_file: *link.File,
330332 src_loc: Module.SrcLoc,
331 module_fn_index: Module.Fn.Index,
333 func_index: InternPool.Index,
332334 air: Air,
333335 liveness: Liveness,
334336 code: *std.ArrayList(u8),
......@@ -339,8 +341,8 @@ pub fn generate(
339341 }
340342
341343 const mod = bin_file.options.module.?;
342 const module_fn = mod.funcPtr(module_fn_index);
343 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
344 const func = mod.funcInfo(func_index);
345 const fn_owner_decl = mod.declPtr(func.owner_decl);
344346 assert(fn_owner_decl.has_tv);
345347 const fn_type = fn_owner_decl.ty;
346348
......@@ -359,7 +361,8 @@ pub fn generate(
359361 .debug_output = debug_output,
360362 .target = &bin_file.options.target,
361363 .bin_file = bin_file,
362 .mod_fn = module_fn,
364 .func_index = func_index,
365 .owner_decl = func.owner_decl,
363366 .err_msg = null,
364367 .args = undefined, // populated after `resolveCallingConventionValues`
365368 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
......@@ -368,8 +371,8 @@ pub fn generate(
368371 .branch_stack = &branch_stack,
369372 .src_loc = src_loc,
370373 .stack_align = undefined,
371 .end_di_line = module_fn.rbrace_line,
372 .end_di_column = module_fn.rbrace_column,
374 .end_di_line = func.rbrace_line,
375 .end_di_column = func.rbrace_column,
373376 };
374377 defer function.stack.deinit(bin_file.allocator);
375378 defer function.blocks.deinit(bin_file.allocator);
......@@ -416,8 +419,8 @@ pub fn generate(
416419 .src_loc = src_loc,
417420 .code = code,
418421 .prev_di_pc = 0,
419 .prev_di_line = module_fn.lbrace_line,
420 .prev_di_column = module_fn.lbrace_column,
422 .prev_di_line = func.lbrace_line,
423 .prev_di_column = func.lbrace_column,
421424 .stack_size = function.max_end_stack,
422425 .saved_regs_stack_space = function.saved_regs_stack_space,
423426 };
......@@ -4011,12 +4014,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
40114014 const atom_index = switch (self.bin_file.tag) {
40124015 .macho => blk: {
40134016 const macho_file = self.bin_file.cast(link.File.MachO).?;
4014 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4017 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
40154018 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
40164019 },
40174020 .coff => blk: {
40184021 const coff_file = self.bin_file.cast(link.File.Coff).?;
4019 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4022 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
40204023 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
40214024 },
40224025 else => unreachable, // unsupported target format
......@@ -4190,10 +4193,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
41904193 while (self.args[arg_index] == .none) arg_index += 1;
41914194 self.arg_index = arg_index + 1;
41924195
4196 const mod = self.bin_file.options.module.?;
41934197 const ty = self.typeOfIndex(inst);
41944198 const tag = self.air.instructions.items(.tag)[inst];
41954199 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4196 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
4200 const name = mod.getParamName(self.func_index, src_index);
41974201
41984202 try self.dbg_info_relocs.append(self.gpa, .{
41994203 .tag = tag,
......@@ -4348,7 +4352,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43484352 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
43494353 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
43504354 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
4351 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4355 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
43524356 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
43534357 _ = try self.addInst(.{
43544358 .tag = .call_extern,
......@@ -4617,9 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
46174621fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
46184622 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
46194623 const mod = self.bin_file.options.module.?;
4620 const function = mod.funcPtr(ty_fn.func);
4624 const func = mod.funcInfo(ty_fn.func);
46214625 // TODO emit debug info for function change
4622 _ = function;
4626 _ = func;
46234627 return self.finishAir(inst, .dead, .{ .none, .none, .none });
46244628}
46254629
......@@ -5529,12 +5533,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
55295533 const atom_index = switch (self.bin_file.tag) {
55305534 .macho => blk: {
55315535 const macho_file = self.bin_file.cast(link.File.MachO).?;
5532 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5536 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
55335537 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
55345538 },
55355539 .coff => blk: {
55365540 const coff_file = self.bin_file.cast(link.File.Coff).?;
5537 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5541 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
55385542 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
55395543 },
55405544 else => unreachable, // unsupported target format
......@@ -5650,12 +5654,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56505654 const atom_index = switch (self.bin_file.tag) {
56515655 .macho => blk: {
56525656 const macho_file = self.bin_file.cast(link.File.MachO).?;
5653 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5657 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
56545658 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
56555659 },
56565660 .coff => blk: {
56575661 const coff_file = self.bin_file.cast(link.File.Coff).?;
5658 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5662 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
56595663 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
56605664 },
56615665 else => unreachable, // unsupported target format
......@@ -5847,12 +5851,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
58475851 const atom_index = switch (self.bin_file.tag) {
58485852 .macho => blk: {
58495853 const macho_file = self.bin_file.cast(link.File.MachO).?;
5850 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5854 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
58515855 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
58525856 },
58535857 .coff => blk: {
58545858 const coff_file = self.bin_file.cast(link.File.Coff).?;
5855 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5859 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
58565860 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
58575861 },
58585862 else => unreachable, // unsupported target format
......@@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
61646168 self.bin_file,
61656169 self.src_loc,
61666170 arg_tv,
6167 self.mod_fn.owner_decl,
6171 self.owner_decl,
61686172 )) {
61696173 .mcv => |mcv| switch (mcv) {
61706174 .none => .none,
......@@ -6198,6 +6202,7 @@ const CallMCValues = struct {
61986202/// Caller must call `CallMCValues.deinit`.
61996203fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62006204 const mod = self.bin_file.options.module.?;
6205 const ip = &mod.intern_pool;
62016206 const fn_info = mod.typeToFunc(fn_ty).?;
62026207 const cc = fn_info.cc;
62036208 var result: CallMCValues = .{
......@@ -6240,10 +6245,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62406245 }
62416246 }
62426247
6243 for (fn_info.param_types, 0..) |ty, i| {
6248 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
62446249 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
62456250 if (param_size == 0) {
6246 result.args[i] = .{ .none = {} };
6251 result_arg.* = .{ .none = {} };
62476252 continue;
62486253 }
62496254
......@@ -6256,7 +6261,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62566261
62576262 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
62586263 if (param_size <= 8) {
6259 result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };
6264 result_arg.* = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };
62606265 ncrn += 1;
62616266 } else {
62626267 return self.fail("TODO MCValues with multiple registers", .{});
......@@ -6273,7 +6278,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62736278 }
62746279 }
62756280
6276 result.args[i] = .{ .stack_argument_offset = nsaa };
6281 result_arg.* = .{ .stack_argument_offset = nsaa };
62776282 nsaa += param_size;
62786283 }
62796284 }
......@@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
63056310
63066311 var stack_offset: u32 = 0;
63076312
6308 for (fn_info.param_types, 0..) |ty, i| {
6313 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
63096314 if (ty.toType().abiSize(mod) > 0) {
63106315 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
63116316 const param_alignment = ty.toType().abiAlignment(mod);
63126317
63136318 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
6314 result.args[i] = .{ .stack_argument_offset = stack_offset };
6319 result_arg.* = .{ .stack_argument_offset = stack_offset };
63156320 stack_offset += param_size;
63166321 } else {
6317 result.args[i] = .{ .none = {} };
6322 result_arg.* = .{ .none = {} };
63186323 }
63196324 }
63206325
src/arch/arm/CodeGen.zig+27-21
......@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
1313const TypedValue = @import("../../TypedValue.zig");
1414const link = @import("../../link.zig");
1515const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");
1617const Compilation = @import("../../Compilation.zig");
1718const ErrorMsg = Module.ErrorMsg;
1819const Target = std.Target;
......@@ -50,7 +51,7 @@ liveness: Liveness,
5051bin_file: *link.File,
5152debug_output: DebugInfoOutput,
5253target: *const std.Target,
53mod_fn: *const Module.Fn,
54func_index: InternPool.Index,
5455err_msg: ?*ErrorMsg,
5556args: []MCValue,
5657ret_mcv: MCValue,
......@@ -258,6 +259,7 @@ const DbgInfoReloc = struct {
258259 }
259260
260261 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
262 const mod = function.bin_file.options.module.?;
261263 switch (function.debug_output) {
262264 .dwarf => |dw| {
263265 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {
......@@ -278,7 +280,7 @@ const DbgInfoReloc = struct {
278280 else => unreachable, // not a possible argument
279281 };
280282
281 try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc);
283 try dw.genArgDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), loc);
282284 },
283285 .plan9 => {},
284286 .none => {},
......@@ -286,6 +288,7 @@ const DbgInfoReloc = struct {
286288 }
287289
288290 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
291 const mod = function.bin_file.options.module.?;
289292 const is_ptr = switch (reloc.tag) {
290293 .dbg_var_ptr => true,
291294 .dbg_var_val => false,
......@@ -321,7 +324,7 @@ const DbgInfoReloc = struct {
321324 break :blk .nop;
322325 },
323326 };
324 try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc);
327 try dw.genVarDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), is_ptr, loc);
325328 },
326329 .plan9 => {},
327330 .none => {},
......@@ -334,7 +337,7 @@ const Self = @This();
334337pub fn generate(
335338 bin_file: *link.File,
336339 src_loc: Module.SrcLoc,
337 module_fn_index: Module.Fn.Index,
340 func_index: InternPool.Index,
338341 air: Air,
339342 liveness: Liveness,
340343 code: *std.ArrayList(u8),
......@@ -345,8 +348,8 @@ pub fn generate(
345348 }
346349
347350 const mod = bin_file.options.module.?;
348 const module_fn = mod.funcPtr(module_fn_index);
349 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
351 const func = mod.funcInfo(func_index);
352 const fn_owner_decl = mod.declPtr(func.owner_decl);
350353 assert(fn_owner_decl.has_tv);
351354 const fn_type = fn_owner_decl.ty;
352355
......@@ -365,7 +368,7 @@ pub fn generate(
365368 .target = &bin_file.options.target,
366369 .bin_file = bin_file,
367370 .debug_output = debug_output,
368 .mod_fn = module_fn,
371 .func_index = func_index,
369372 .err_msg = null,
370373 .args = undefined, // populated after `resolveCallingConventionValues`
371374 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
......@@ -374,8 +377,8 @@ pub fn generate(
374377 .branch_stack = &branch_stack,
375378 .src_loc = src_loc,
376379 .stack_align = undefined,
377 .end_di_line = module_fn.rbrace_line,
378 .end_di_column = module_fn.rbrace_column,
380 .end_di_line = func.rbrace_line,
381 .end_di_column = func.rbrace_column,
379382 };
380383 defer function.stack.deinit(bin_file.allocator);
381384 defer function.blocks.deinit(bin_file.allocator);
......@@ -422,8 +425,8 @@ pub fn generate(
422425 .src_loc = src_loc,
423426 .code = code,
424427 .prev_di_pc = 0,
425 .prev_di_line = module_fn.lbrace_line,
426 .prev_di_column = module_fn.lbrace_column,
428 .prev_di_line = func.lbrace_line,
429 .prev_di_column = func.lbrace_column,
427430 .stack_size = function.max_end_stack,
428431 .saved_regs_stack_space = function.saved_regs_stack_space,
429432 };
......@@ -4163,10 +4166,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
41634166 while (self.args[arg_index] == .none) arg_index += 1;
41644167 self.arg_index = arg_index + 1;
41654168
4169 const mod = self.bin_file.options.module.?;
41664170 const ty = self.typeOfIndex(inst);
41674171 const tag = self.air.instructions.items(.tag)[inst];
41684172 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4169 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
4173 const name = mod.getParamName(self.func_index, src_index);
41704174
41714175 try self.dbg_info_relocs.append(self.gpa, .{
41724176 .tag = tag,
......@@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
45694573fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
45704574 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
45714575 const mod = self.bin_file.options.module.?;
4572 const function = mod.funcPtr(ty_fn.func);
4576 const func = mod.funcInfo(ty_fn.func);
45734577 // TODO emit debug info for function change
4574 _ = function;
4578 _ = func;
45754579 return self.finishAir(inst, .dead, .{ .none, .none, .none });
45764580}
45774581
......@@ -6113,11 +6117,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
61136117}
61146118
61156119fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6120 const mod = self.bin_file.options.module.?;
61166121 const mcv: MCValue = switch (try codegen.genTypedValue(
61176122 self.bin_file,
61186123 self.src_loc,
61196124 arg_tv,
6120 self.mod_fn.owner_decl,
6125 mod.funcOwnerDeclIndex(self.func_index),
61216126 )) {
61226127 .mcv => |mcv| switch (mcv) {
61236128 .none => .none,
......@@ -6149,6 +6154,7 @@ const CallMCValues = struct {
61496154/// Caller must call `CallMCValues.deinit`.
61506155fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
61516156 const mod = self.bin_file.options.module.?;
6157 const ip = &mod.intern_pool;
61526158 const fn_info = mod.typeToFunc(fn_ty).?;
61536159 const cc = fn_info.cc;
61546160 var result: CallMCValues = .{
......@@ -6194,14 +6200,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
61946200 }
61956201 }
61966202
6197 for (fn_info.param_types, 0..) |ty, i| {
6203 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
61986204 if (ty.toType().abiAlignment(mod) == 8)
61996205 ncrn = std.mem.alignForward(usize, ncrn, 2);
62006206
62016207 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
62026208 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
62036209 if (param_size <= 4) {
6204 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };
6210 result_arg.* = .{ .register = c_abi_int_param_regs[ncrn] };
62056211 ncrn += 1;
62066212 } else {
62076213 return self.fail("TODO MCValues with multiple registers", .{});
......@@ -6213,7 +6219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62136219 if (ty.toType().abiAlignment(mod) == 8)
62146220 nsaa = std.mem.alignForward(u32, nsaa, 8);
62156221
6216 result.args[i] = .{ .stack_argument_offset = nsaa };
6222 result_arg.* = .{ .stack_argument_offset = nsaa };
62176223 nsaa += param_size;
62186224 }
62196225 }
......@@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62446250
62456251 var stack_offset: u32 = 0;
62466252
6247 for (fn_info.param_types, 0..) |ty, i| {
6253 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
62486254 if (ty.toType().abiSize(mod) > 0) {
62496255 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
62506256 const param_alignment = ty.toType().abiAlignment(mod);
62516257
62526258 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
6253 result.args[i] = .{ .stack_argument_offset = stack_offset };
6259 result_arg.* = .{ .stack_argument_offset = stack_offset };
62546260 stack_offset += param_size;
62556261 } else {
6256 result.args[i] = .{ .none = {} };
6262 result_arg.* = .{ .none = {} };
62576263 }
62586264 }
62596265
src/arch/riscv64/CodeGen.zig+46-37
......@@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value;
1212const TypedValue = @import("../../TypedValue.zig");
1313const link = @import("../../link.zig");
1414const Module = @import("../../Module.zig");
15const InternPool = @import("../../InternPool.zig");
1516const Compilation = @import("../../Compilation.zig");
1617const ErrorMsg = Module.ErrorMsg;
1718const Target = std.Target;
......@@ -43,7 +44,7 @@ air: Air,
4344liveness: Liveness,
4445bin_file: *link.File,
4546target: *const std.Target,
46mod_fn: *const Module.Fn,
47func_index: InternPool.Index,
4748code: *std.ArrayList(u8),
4849debug_output: DebugInfoOutput,
4950err_msg: ?*ErrorMsg,
......@@ -217,7 +218,7 @@ const Self = @This();
217218pub fn generate(
218219 bin_file: *link.File,
219220 src_loc: Module.SrcLoc,
220 module_fn_index: Module.Fn.Index,
221 func_index: InternPool.Index,
221222 air: Air,
222223 liveness: Liveness,
223224 code: *std.ArrayList(u8),
......@@ -228,8 +229,8 @@ pub fn generate(
228229 }
229230
230231 const mod = bin_file.options.module.?;
231 const module_fn = mod.funcPtr(module_fn_index);
232 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
232 const func = mod.funcInfo(func_index);
233 const fn_owner_decl = mod.declPtr(func.owner_decl);
233234 assert(fn_owner_decl.has_tv);
234235 const fn_type = fn_owner_decl.ty;
235236
......@@ -247,7 +248,7 @@ pub fn generate(
247248 .liveness = liveness,
248249 .target = &bin_file.options.target,
249250 .bin_file = bin_file,
250 .mod_fn = module_fn,
251 .func_index = func_index,
251252 .code = code,
252253 .debug_output = debug_output,
253254 .err_msg = null,
......@@ -258,8 +259,8 @@ pub fn generate(
258259 .branch_stack = &branch_stack,
259260 .src_loc = src_loc,
260261 .stack_align = undefined,
261 .end_di_line = module_fn.rbrace_line,
262 .end_di_column = module_fn.rbrace_column,
262 .end_di_line = func.rbrace_line,
263 .end_di_column = func.rbrace_column,
263264 };
264265 defer function.stack.deinit(bin_file.allocator);
265266 defer function.blocks.deinit(bin_file.allocator);
......@@ -301,8 +302,8 @@ pub fn generate(
301302 .src_loc = src_loc,
302303 .code = code,
303304 .prev_di_pc = 0,
304 .prev_di_line = module_fn.lbrace_line,
305 .prev_di_column = module_fn.lbrace_column,
305 .prev_di_line = func.lbrace_line,
306 .prev_di_column = func.lbrace_column,
306307 };
307308 defer emit.deinit();
308309
......@@ -1627,13 +1628,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
16271628}
16281629
16291630fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
1631 const mod = self.bin_file.options.module.?;
16301632 const arg = self.air.instructions.items(.data)[inst].arg;
16311633 const ty = self.air.getRefType(arg.ty);
1632 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
1634 const owner_decl = mod.funcOwnerDeclIndex(self.func_index);
1635 const name = mod.getParamName(self.func_index, arg.src_index);
16331636
16341637 switch (self.debug_output) {
16351638 .dwarf => |dw| switch (mcv) {
1636 .register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{
1639 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
16371640 .register = reg.dwarfLocOp(),
16381641 }),
16391642 .stack_offset => {},
......@@ -1742,24 +1745,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
17421745 }
17431746
17441747 if (try self.air.value(callee, mod)) |func_value| {
1745 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
1746 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1747 const atom = elf_file.getAtom(atom_index);
1748 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1749 const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1750 try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
1751 _ = try self.addInst(.{
1752 .tag = .jalr,
1753 .data = .{ .i_type = .{
1754 .rd = .ra,
1755 .rs1 = .ra,
1756 .imm12 = 0,
1757 } },
1758 });
1759 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
1760 return self.fail("TODO implement calling extern functions", .{});
1761 } else {
1762 return self.fail("TODO implement calling bitcasted functions", .{});
1748 switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
1749 .func => |func| {
1750 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1751 const atom = elf_file.getAtom(atom_index);
1752 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1753 const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1754 try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
1755 _ = try self.addInst(.{
1756 .tag = .jalr,
1757 .data = .{ .i_type = .{
1758 .rd = .ra,
1759 .rs1 = .ra,
1760 .imm12 = 0,
1761 } },
1762 });
1763 },
1764 .extern_func => {
1765 return self.fail("TODO implement calling extern functions", .{});
1766 },
1767 else => {
1768 return self.fail("TODO implement calling bitcasted functions", .{});
1769 },
17631770 }
17641771 } else {
17651772 return self.fail("TODO implement calling runtime-known function pointer", .{});
......@@ -1876,9 +1883,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
18761883fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
18771884 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
18781885 const mod = self.bin_file.options.module.?;
1879 const function = mod.funcPtr(ty_fn.func);
1886 const func = mod.funcInfo(ty_fn.func);
18801887 // TODO emit debug info for function change
1881 _ = function;
1888 _ = func;
18821889 return self.finishAir(inst, .dead, .{ .none, .none, .none });
18831890}
18841891
......@@ -2569,11 +2576,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
25692576}
25702577
25712578fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
2579 const mod = self.bin_file.options.module.?;
25722580 const mcv: MCValue = switch (try codegen.genTypedValue(
25732581 self.bin_file,
25742582 self.src_loc,
25752583 typed_value,
2576 self.mod_fn.owner_decl,
2584 mod.funcOwnerDeclIndex(self.func_index),
25772585 )) {
25782586 .mcv => |mcv| switch (mcv) {
25792587 .none => .none,
......@@ -2605,6 +2613,7 @@ const CallMCValues = struct {
26052613/// Caller must call `CallMCValues.deinit`.
26062614fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26072615 const mod = self.bin_file.options.module.?;
2616 const ip = &mod.intern_pool;
26082617 const fn_info = mod.typeToFunc(fn_ty).?;
26092618 const cc = fn_info.cc;
26102619 var result: CallMCValues = .{
......@@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26362645 var next_stack_offset: u32 = 0;
26372646 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
26382647
2639 for (fn_info.param_types, 0..) |ty, i| {
2648 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
26402649 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
26412650 if (param_size <= 8) {
26422651 if (next_register < argument_registers.len) {
2643 result.args[i] = .{ .register = argument_registers[next_register] };
2652 result_arg.* = .{ .register = argument_registers[next_register] };
26442653 next_register += 1;
26452654 } else {
2646 result.args[i] = .{ .stack_offset = next_stack_offset };
2655 result_arg.* = .{ .stack_offset = next_stack_offset };
26472656 next_register += next_stack_offset;
26482657 }
26492658 } else if (param_size <= 16) {
......@@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26522661 } else if (next_register < argument_registers.len) {
26532662 return self.fail("TODO MCValues split register + stack", .{});
26542663 } else {
2655 result.args[i] = .{ .stack_offset = next_stack_offset };
2664 result_arg.* = .{ .stack_offset = next_stack_offset };
26562665 next_register += next_stack_offset;
26572666 }
26582667 } else {
2659 result.args[i] = .{ .stack_offset = next_stack_offset };
2668 result_arg.* = .{ .stack_offset = next_stack_offset };
26602669 next_register += next_stack_offset;
26612670 }
26622671 }
src/arch/sparc64/CodeGen.zig+55-46
......@@ -11,6 +11,7 @@ const Allocator = mem.Allocator;
1111const builtin = @import("builtin");
1212const link = @import("../../link.zig");
1313const Module = @import("../../Module.zig");
14const InternPool = @import("../../InternPool.zig");
1415const TypedValue = @import("../../TypedValue.zig");
1516const ErrorMsg = Module.ErrorMsg;
1617const codegen = @import("../../codegen.zig");
......@@ -52,7 +53,7 @@ air: Air,
5253liveness: Liveness,
5354bin_file: *link.File,
5455target: *const std.Target,
55mod_fn: *const Module.Fn,
56func_index: InternPool.Index,
5657code: *std.ArrayList(u8),
5758debug_output: DebugInfoOutput,
5859err_msg: ?*ErrorMsg,
......@@ -260,7 +261,7 @@ const BigTomb = struct {
260261pub fn generate(
261262 bin_file: *link.File,
262263 src_loc: Module.SrcLoc,
263 module_fn_index: Module.Fn.Index,
264 func_index: InternPool.Index,
264265 air: Air,
265266 liveness: Liveness,
266267 code: *std.ArrayList(u8),
......@@ -271,8 +272,8 @@ pub fn generate(
271272 }
272273
273274 const mod = bin_file.options.module.?;
274 const module_fn = mod.funcPtr(module_fn_index);
275 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
275 const func = mod.funcInfo(func_index);
276 const fn_owner_decl = mod.declPtr(func.owner_decl);
276277 assert(fn_owner_decl.has_tv);
277278 const fn_type = fn_owner_decl.ty;
278279
......@@ -289,8 +290,8 @@ pub fn generate(
289290 .air = air,
290291 .liveness = liveness,
291292 .target = &bin_file.options.target,
293 .func_index = func_index,
292294 .bin_file = bin_file,
293 .mod_fn = module_fn,
294295 .code = code,
295296 .debug_output = debug_output,
296297 .err_msg = null,
......@@ -301,8 +302,8 @@ pub fn generate(
301302 .branch_stack = &branch_stack,
302303 .src_loc = src_loc,
303304 .stack_align = undefined,
304 .end_di_line = module_fn.rbrace_line,
305 .end_di_column = module_fn.rbrace_column,
305 .end_di_line = func.rbrace_line,
306 .end_di_column = func.rbrace_column,
306307 };
307308 defer function.stack.deinit(bin_file.allocator);
308309 defer function.blocks.deinit(bin_file.allocator);
......@@ -344,8 +345,8 @@ pub fn generate(
344345 .src_loc = src_loc,
345346 .code = code,
346347 .prev_di_pc = 0,
347 .prev_di_line = module_fn.lbrace_line,
348 .prev_di_column = module_fn.lbrace_column,
348 .prev_di_line = func.lbrace_line,
349 .prev_di_column = func.lbrace_column,
349350 };
350351 defer emit.deinit();
351352
......@@ -1345,37 +1346,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13451346 // on linking.
13461347 if (try self.air.value(callee, mod)) |func_value| {
13471348 if (self.bin_file.tag == link.File.Elf.base_tag) {
1348 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
1349 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1350 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1351 const atom = elf_file.getAtom(atom_index);
1352 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1353 break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1354 } else unreachable;
1349 switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
1350 .func => |func| {
1351 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1352 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1353 const atom = elf_file.getAtom(atom_index);
1354 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1355 break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1356 } else unreachable;
13551357
1356 try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });
1358 try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });
13571359
1358 _ = try self.addInst(.{
1359 .tag = .jmpl,
1360 .data = .{
1361 .arithmetic_3op = .{
1362 .is_imm = false,
1363 .rd = .o7,
1364 .rs1 = .o7,
1365 .rs2_or_imm = .{ .rs2 = .g0 },
1360 _ = try self.addInst(.{
1361 .tag = .jmpl,
1362 .data = .{
1363 .arithmetic_3op = .{
1364 .is_imm = false,
1365 .rd = .o7,
1366 .rs1 = .o7,
1367 .rs2_or_imm = .{ .rs2 = .g0 },
1368 },
13661369 },
1367 },
1368 });
1370 });
13691371
1370 // TODO Find a way to fill this delay slot
1371 _ = try self.addInst(.{
1372 .tag = .nop,
1373 .data = .{ .nop = {} },
1374 });
1375 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
1376 return self.fail("TODO implement calling extern functions", .{});
1377 } else {
1378 return self.fail("TODO implement calling bitcasted functions", .{});
1372 // TODO Find a way to fill this delay slot
1373 _ = try self.addInst(.{
1374 .tag = .nop,
1375 .data = .{ .nop = {} },
1376 });
1377 },
1378 .extern_func => {
1379 return self.fail("TODO implement calling extern functions", .{});
1380 },
1381 else => {
1382 return self.fail("TODO implement calling bitcasted functions", .{});
1383 },
13791384 }
13801385 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
13811386 } else {
......@@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
16601665fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
16611666 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
16621667 const mod = self.bin_file.options.module.?;
1663 const function = mod.funcPtr(ty_fn.func);
1668 const func = mod.funcInfo(ty_fn.func);
16641669 // TODO emit debug info for function change
1665 _ = function;
1670 _ = func;
16661671 return self.finishAir(inst, .dead, .{ .none, .none, .none });
16671672}
16681673
......@@ -3595,13 +3600,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
35953600}
35963601
35973602fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
3603 const mod = self.bin_file.options.module.?;
35983604 const arg = self.air.instructions.items(.data)[inst].arg;
35993605 const ty = self.air.getRefType(arg.ty);
3600 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
3606 const owner_decl = mod.funcOwnerDeclIndex(self.func_index);
3607 const name = mod.getParamName(self.func_index, arg.src_index);
36013608
36023609 switch (self.debug_output) {
36033610 .dwarf => |dw| switch (mcv) {
3604 .register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{
3611 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
36053612 .register = reg.dwarfLocOp(),
36063613 }),
36073614 else => {},
......@@ -4127,11 +4134,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re
41274134}
41284135
41294136fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
4137 const mod = self.bin_file.options.module.?;
41304138 const mcv: MCValue = switch (try codegen.genTypedValue(
41314139 self.bin_file,
41324140 self.src_loc,
41334141 typed_value,
4134 self.mod_fn.owner_decl,
4142 mod.funcOwnerDeclIndex(self.func_index),
41354143 )) {
41364144 .mcv => |mcv| switch (mcv) {
41374145 .none => .none,
......@@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 {
44524460/// Caller must call `CallMCValues.deinit`.
44534461fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
44544462 const mod = self.bin_file.options.module.?;
4463 const ip = &mod.intern_pool;
44554464 const fn_info = mod.typeToFunc(fn_ty).?;
44564465 const cc = fn_info.cc;
44574466 var result: CallMCValues = .{
......@@ -4486,14 +4495,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
44864495 .callee => abi.c_abi_int_param_regs_callee_view,
44874496 };
44884497
4489 for (fn_info.param_types, 0..) |ty, i| {
4498 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
44904499 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
44914500 if (param_size <= 8) {
44924501 if (next_register < argument_registers.len) {
4493 result.args[i] = .{ .register = argument_registers[next_register] };
4502 result_arg.* = .{ .register = argument_registers[next_register] };
44944503 next_register += 1;
44954504 } else {
4496 result.args[i] = .{ .stack_offset = next_stack_offset };
4505 result_arg.* = .{ .stack_offset = next_stack_offset };
44974506 next_register += next_stack_offset;
44984507 }
44994508 } else if (param_size <= 16) {
......@@ -4502,11 +4511,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
45024511 } else if (next_register < argument_registers.len) {
45034512 return self.fail("TODO MCValues split register + stack", .{});
45044513 } else {
4505 result.args[i] = .{ .stack_offset = next_stack_offset };
4514 result_arg.* = .{ .stack_offset = next_stack_offset };
45064515 next_register += next_stack_offset;
45074516 }
45084517 } else {
4509 result.args[i] = .{ .stack_offset = next_stack_offset };
4518 result_arg.* = .{ .stack_offset = next_stack_offset };
45104519 next_register += next_stack_offset;
45114520 }
45124521 }
src/arch/wasm/CodeGen.zig+16-12
......@@ -650,7 +650,7 @@ air: Air,
650650liveness: Liveness,
651651gpa: mem.Allocator,
652652debug_output: codegen.DebugInfoOutput,
653mod_fn: *const Module.Fn,
653func_index: InternPool.Index,
654654/// Contains a list of current branches.
655655/// When we return from a branch, the branch will be popped from this list,
656656/// which means branches can only contain references from within its own branch,
......@@ -1202,7 +1202,7 @@ fn genFunctype(
12021202pub fn generate(
12031203 bin_file: *link.File,
12041204 src_loc: Module.SrcLoc,
1205 func_index: Module.Fn.Index,
1205 func_index: InternPool.Index,
12061206 air: Air,
12071207 liveness: Liveness,
12081208 code: *std.ArrayList(u8),
......@@ -1210,7 +1210,7 @@ pub fn generate(
12101210) codegen.CodeGenError!codegen.Result {
12111211 _ = src_loc;
12121212 const mod = bin_file.options.module.?;
1213 const func = mod.funcPtr(func_index);
1213 const func = mod.funcInfo(func_index);
12141214 var code_gen: CodeGen = .{
12151215 .gpa = bin_file.allocator,
12161216 .air = air,
......@@ -1223,7 +1223,7 @@ pub fn generate(
12231223 .target = bin_file.options.target,
12241224 .bin_file = bin_file.cast(link.File.Wasm).?,
12251225 .debug_output = debug_output,
1226 .mod_fn = func,
1226 .func_index = func_index,
12271227 };
12281228 defer code_gen.deinit();
12291229
......@@ -1237,8 +1237,9 @@ pub fn generate(
12371237
12381238fn genFunc(func: *CodeGen) InnerError!void {
12391239 const mod = func.bin_file.base.options.module.?;
1240 const ip = &mod.intern_pool;
12401241 const fn_info = mod.typeToFunc(func.decl.ty).?;
1241 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
1242 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod);
12421243 defer func_type.deinit(func.gpa);
12431244 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);
12441245
......@@ -1347,6 +1348,7 @@ const CallWValues = struct {
13471348
13481349fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
13491350 const mod = func.bin_file.base.options.module.?;
1351 const ip = &mod.intern_pool;
13501352 const fn_info = mod.typeToFunc(fn_ty).?;
13511353 const cc = fn_info.cc;
13521354 var result: CallWValues = .{
......@@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13691371
13701372 switch (cc) {
13711373 .Unspecified => {
1372 for (fn_info.param_types) |ty| {
1374 for (fn_info.param_types.get(ip)) |ty| {
13731375 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
13741376 continue;
13751377 }
......@@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13791381 }
13801382 },
13811383 .C => {
1382 for (fn_info.param_types) |ty| {
1384 for (fn_info.param_types.get(ip)) |ty| {
13831385 const ty_classes = abi.classifyType(ty.toType(), mod);
13841386 for (ty_classes) |class| {
13851387 if (class == .none) continue;
......@@ -2185,6 +2187,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
21852187 const ty = func.typeOf(pl_op.operand);
21862188
21872189 const mod = func.bin_file.base.options.module.?;
2190 const ip = &mod.intern_pool;
21882191 const fn_ty = switch (ty.zigTypeTag(mod)) {
21892192 .Fn => ty,
21902193 .Pointer => ty.childType(mod),
......@@ -2203,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22032206 } else if (func_val.getExternFunc(mod)) |extern_func| {
22042207 const ext_decl = mod.declPtr(extern_func.decl);
22052208 const ext_info = mod.typeToFunc(ext_decl.ty).?;
2206 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);
2209 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types.get(ip), ext_info.return_type.toType(), mod);
22072210 defer func_type.deinit(func.gpa);
22082211 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
22092212 const atom = func.bin_file.getAtomPtr(atom_index);
......@@ -2253,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22532256 const operand = try func.resolveInst(pl_op.operand);
22542257 try func.emitWValue(operand);
22552258
2256 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
2259 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod);
22572260 defer fn_type.deinit(func.gpa);
22582261
22592262 const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);
......@@ -2564,8 +2567,8 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
25642567 switch (func.debug_output) {
25652568 .dwarf => |dwarf| {
25662569 const src_index = func.air.instructions.items(.data)[inst].arg.src_index;
2567 const name = func.mod_fn.getParamName(func.bin_file.base.options.module.?, src_index);
2568 try dwarf.genArgDbgInfo(name, arg_ty, func.mod_fn.owner_decl, .{
2570 const name = mod.getParamName(func.func_index, src_index);
2571 try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{
25692572 .wasm_local = arg.local.value,
25702573 });
25712574 },
......@@ -6198,6 +6201,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
61986201fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
61996202 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
62006203
6204 const mod = func.bin_file.base.options.module.?;
62016205 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
62026206 const ty = func.typeOf(pl_op.operand);
62036207 const operand = try func.resolveInst(pl_op.operand);
......@@ -6214,7 +6218,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
62146218 break :blk .nop;
62156219 },
62166220 };
6217 try func.debug_output.dwarf.genVarDbgInfo(name, ty, func.mod_fn.owner_decl, is_ptr, loc);
6221 try func.debug_output.dwarf.genVarDbgInfo(name, ty, mod.funcOwnerDeclIndex(func.func_index), is_ptr, loc);
62186222
62196223 func.finishAir(inst, .none, &.{});
62206224}
src/arch/x86_64/CodeGen.zig+23-22
......@@ -110,20 +110,21 @@ const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
110110const RegisterOffset = struct { reg: Register, off: i32 = 0 };
111111
112112const Owner = union(enum) {
113 mod_fn: *const Module.Fn,
113 func_index: InternPool.Index,
114114 lazy_sym: link.File.LazySymbol,
115115
116116 fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {
117117 return switch (owner) {
118 .mod_fn => |mod_fn| mod_fn.owner_decl,
118 .func_index => |func_index| mod.funcOwnerDeclIndex(func_index),
119119 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod),
120120 };
121121 }
122122
123123 fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 {
124124 switch (owner) {
125 .mod_fn => |mod_fn| {
126 const decl_index = mod_fn.owner_decl;
125 .func_index => |func_index| {
126 const mod = ctx.bin_file.options.module.?;
127 const decl_index = mod.funcOwnerDeclIndex(func_index);
127128 if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
128129 const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
129130 return macho_file.getAtom(atom).getSymbolIndex().?;
......@@ -638,7 +639,7 @@ const Self = @This();
638639pub fn generate(
639640 bin_file: *link.File,
640641 src_loc: Module.SrcLoc,
641 module_fn_index: Module.Fn.Index,
642 func_index: InternPool.Index,
642643 air: Air,
643644 liveness: Liveness,
644645 code: *std.ArrayList(u8),
......@@ -649,8 +650,8 @@ pub fn generate(
649650 }
650651
651652 const mod = bin_file.options.module.?;
652 const module_fn = mod.funcPtr(module_fn_index);
653 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
653 const func = mod.funcInfo(func_index);
654 const fn_owner_decl = mod.declPtr(func.owner_decl);
654655 assert(fn_owner_decl.has_tv);
655656 const fn_type = fn_owner_decl.ty;
656657
......@@ -662,15 +663,15 @@ pub fn generate(
662663 .target = &bin_file.options.target,
663664 .bin_file = bin_file,
664665 .debug_output = debug_output,
665 .owner = .{ .mod_fn = module_fn },
666 .owner = .{ .func_index = func_index },
666667 .err_msg = null,
667668 .args = undefined, // populated after `resolveCallingConventionValues`
668669 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
669670 .fn_type = fn_type,
670671 .arg_index = 0,
671672 .src_loc = src_loc,
672 .end_di_line = module_fn.rbrace_line,
673 .end_di_column = module_fn.rbrace_column,
673 .end_di_line = func.rbrace_line,
674 .end_di_column = func.rbrace_column,
674675 };
675676 defer {
676677 function.frame_allocs.deinit(gpa);
......@@ -687,17 +688,16 @@ pub fn generate(
687688 if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa);
688689 }
689690
690 wip_mir_log.debug("{}:", .{function.fmtDecl(module_fn.owner_decl)});
691 wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)});
692
693 const ip = &mod.intern_pool;
691694
692695 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
693696 function.frame_allocs.set(
694697 @intFromEnum(FrameIndex.stack_frame),
695698 FrameAlloc.init(.{
696699 .size = 0,
697 .alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack|
698 @intCast(set_align_stack.alignment.toByteUnitsOptional().?)
699 else
700 1,
700 .alignment = @intCast(func.analysis(ip).stack_alignment.toByteUnitsOptional() orelse 1),
701701 }),
702702 );
703703 function.frame_allocs.set(
......@@ -761,8 +761,8 @@ pub fn generate(
761761 .debug_output = debug_output,
762762 .code = code,
763763 .prev_di_pc = 0,
764 .prev_di_line = module_fn.lbrace_line,
765 .prev_di_column = module_fn.lbrace_column,
764 .prev_di_line = func.lbrace_line,
765 .prev_di_column = func.lbrace_column,
766766 };
767767 defer emit.deinit();
768768 emit.emitMir() catch |err| switch (err) {
......@@ -7942,7 +7942,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
79427942
79437943 const ty = self.typeOfIndex(inst);
79447944 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
7945 const name = self.owner.mod_fn.getParamName(mod, src_index);
7945 const name = mod.getParamName(self.owner.func_index, src_index);
79467946 try self.genArgDbgInfo(ty, name, dst_mcv);
79477947
79487948 break :result dst_mcv;
......@@ -8139,7 +8139,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81398139 if (try self.air.value(callee, mod)) |func_value| {
81408140 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
81418141 if (switch (func_key) {
8142 .func => |func| mod.funcPtr(func.index).owner_decl,
8142 .func => |func| func.owner_decl,
81438143 .ptr => |ptr| switch (ptr.addr) {
81448144 .decl => |decl| decl,
81458145 else => null,
......@@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
85828582fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
85838583 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
85848584 const mod = self.bin_file.options.module.?;
8585 const function = mod.funcPtr(ty_fn.func);
8585 const func = mod.funcInfo(ty_fn.func);
85868586 // TODO emit debug info for function change
8587 _ = function;
8587 _ = func;
85888588 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
85898589}
85908590
......@@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues(
1171911719 stack_frame_base: FrameIndex,
1172011720) !CallMCValues {
1172111721 const mod = self.bin_file.options.module.?;
11722 const ip = &mod.intern_pool;
1172211723 const cc = fn_info.cc;
1172311724 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
1172411725 defer self.gpa.free(param_types);
1172511726
11726 for (param_types[0..fn_info.param_types.len], fn_info.param_types) |*dest, src| {
11727 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {
1172711728 dest.* = src.toType();
1172811729 }
1172911730 // TODO: promote var arg types
src/codegen.zig+1-1
......@@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
6767pub fn generateFunction(
6868 bin_file: *link.File,
6969 src_loc: Module.SrcLoc,
70 func_index: Module.Fn.Index,
70 func_index: InternPool.Index,
7171 air: Air,
7272 liveness: Liveness,
7373 code: *std.ArrayList(u8),
src/codegen/c.zig+15-8
......@@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
257257 return .{ .data = ident };
258258}
259259
260/// This data is available when outputting .c code for a `Module.Fn.Index`.
260/// This data is available when outputting .c code for a `InternPool.Index`
261/// that corresponds to `func`.
261262/// It is not available when generating .h file.
262263pub const Function = struct {
263264 air: Air,
......@@ -268,7 +269,7 @@ pub const Function = struct {
268269 next_block_index: usize = 0,
269270 object: Object,
270271 lazy_fns: LazyFnMap,
271 func_index: Module.Fn.Index,
272 func_index: InternPool.Index,
272273 /// All the locals, to be emitted at the top of the function.
273274 locals: std.ArrayListUnmanaged(Local) = .{},
274275 /// Which locals are available for reuse, based on Type.
......@@ -1487,6 +1488,7 @@ pub const DeclGen = struct {
14871488 ) !void {
14881489 const store = &dg.ctypes.set;
14891490 const mod = dg.module;
1491 const ip = &mod.intern_pool;
14901492
14911493 const fn_decl = mod.declPtr(fn_decl_index);
14921494 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);
......@@ -1499,7 +1501,7 @@ pub const DeclGen = struct {
14991501 else => unreachable,
15001502 }
15011503 }
1502 if (fn_decl.val.getFunction(mod)) |func| if (func.is_cold) try w.writeAll("zig_cold ");
1504 if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold) try w.writeAll("zig_cold ");
15031505 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
15041506
15051507 const trailing = try renderTypePrefix(
......@@ -1744,7 +1746,7 @@ pub const DeclGen = struct {
17441746 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
17451747 .variable => |variable| mod.decl_exports.contains(variable.decl),
17461748 .extern_func => true,
1747 .func => |func| mod.decl_exports.contains(mod.funcPtr(func.index).owner_decl),
1749 .func => |func| mod.decl_exports.contains(func.owner_decl),
17481750 else => unreachable,
17491751 };
17501752 }
......@@ -1800,7 +1802,12 @@ pub const DeclGen = struct {
18001802 }
18011803 }
18021804
1803 fn writeCValueMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
1805 fn writeCValueMember(
1806 dg: *DeclGen,
1807 writer: anytype,
1808 c_value: CValue,
1809 member: CValue,
1810 ) error{ OutOfMemory, AnalysisFail }!void {
18041811 try dg.writeCValue(writer, c_value);
18051812 try writer.writeByte('.');
18061813 try dg.writeCValue(writer, member);
......@@ -4161,7 +4168,7 @@ fn airCall(
41614168 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
41624169 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
41634170 .extern_func => |extern_func| extern_func.decl,
4164 .func => |func| mod.funcPtr(func.index).owner_decl,
4171 .func => |func| func.owner_decl,
41654172 .ptr => |ptr| switch (ptr.addr) {
41664173 .decl => |decl| decl,
41674174 else => break :known,
......@@ -4238,9 +4245,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
42384245 const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;
42394246 const mod = f.object.dg.module;
42404247 const writer = f.object.writer();
4241 const function = mod.funcPtr(ty_fn.func);
4248 const owner_decl = mod.funcOwnerDeclPtr(ty_fn.func);
42424249 try writer.print("/* dbg func:{s} */\n", .{
4243 mod.intern_pool.stringToSlice(mod.declPtr(function.owner_decl).name),
4250 mod.intern_pool.stringToSlice(owner_decl.name),
42444251 });
42454252 return .none;
42464253}
src/codegen/c/type.zig+9-5
......@@ -1722,6 +1722,7 @@ pub const CType = extern union {
17221722
17231723 .Fn => {
17241724 const info = mod.typeToFunc(ty).?;
1725 const ip = &mod.intern_pool;
17251726 if (!info.is_generic) {
17261727 if (lookup.isMutable()) {
17271728 const param_kind: Kind = switch (kind) {
......@@ -1730,7 +1731,7 @@ pub const CType = extern union {
17301731 .payload => unreachable,
17311732 };
17321733 _ = try lookup.typeToIndex(info.return_type.toType(), param_kind);
1733 for (info.param_types) |param_type| {
1734 for (info.param_types.get(ip)) |param_type| {
17341735 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
17351736 _ = try lookup.typeToIndex(param_type.toType(), param_kind);
17361737 }
......@@ -2014,6 +2015,7 @@ pub const CType = extern union {
20142015 .function,
20152016 .varargs_function,
20162017 => {
2018 const ip = &mod.intern_pool;
20172019 const info = mod.typeToFunc(ty).?;
20182020 assert(!info.is_generic);
20192021 const param_kind: Kind = switch (kind) {
......@@ -2023,14 +2025,14 @@ pub const CType = extern union {
20232025 };
20242026
20252027 var c_params_len: usize = 0;
2026 for (info.param_types) |param_type| {
2028 for (info.param_types.get(ip)) |param_type| {
20272029 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
20282030 c_params_len += 1;
20292031 }
20302032
20312033 const params_pl = try arena.alloc(Index, c_params_len);
20322034 var c_param_i: usize = 0;
2033 for (info.param_types) |param_type| {
2035 for (info.param_types.get(ip)) |param_type| {
20342036 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
20352037 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
20362038 c_param_i += 1;
......@@ -2147,6 +2149,7 @@ pub const CType = extern union {
21472149 => {
21482150 if (ty.zigTypeTag(mod) != .Fn) return false;
21492151
2152 const ip = &mod.intern_pool;
21502153 const info = mod.typeToFunc(ty).?;
21512154 assert(!info.is_generic);
21522155 const data = cty.cast(Payload.Function).?.data;
......@@ -2160,7 +2163,7 @@ pub const CType = extern union {
21602163 return false;
21612164
21622165 var c_param_i: usize = 0;
2163 for (info.param_types) |param_type| {
2166 for (info.param_types.get(ip)) |param_type| {
21642167 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
21652168
21662169 if (c_param_i >= data.param_types.len) return false;
......@@ -2202,6 +2205,7 @@ pub const CType = extern union {
22022205 autoHash(hasher, t);
22032206
22042207 const mod = self.lookup.getModule();
2208 const ip = &mod.intern_pool;
22052209 switch (t) {
22062210 .fwd_anon_struct,
22072211 .fwd_anon_union,
......@@ -2270,7 +2274,7 @@ pub const CType = extern union {
22702274 };
22712275
22722276 self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);
2273 for (info.param_types) |param_type| {
2277 for (info.param_types.get(ip)) |param_type| {
22742278 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
22752279 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
22762280 }
src/codegen/llvm.zig+75-68
......@@ -867,14 +867,15 @@ pub const Object = struct {
867867 pub fn updateFunc(
868868 o: *Object,
869869 mod: *Module,
870 func_index: Module.Fn.Index,
870 func_index: InternPool.Index,
871871 air: Air,
872872 liveness: Liveness,
873873 ) !void {
874 const func = mod.funcPtr(func_index);
874 const func = mod.funcInfo(func_index);
875875 const decl_index = func.owner_decl;
876876 const decl = mod.declPtr(decl_index);
877877 const target = mod.getTarget();
878 const ip = &mod.intern_pool;
878879
879880 var dg: DeclGen = .{
880881 .object = o,
......@@ -885,24 +886,23 @@ pub const Object = struct {
885886
886887 const llvm_func = try o.resolveLlvmFunction(decl_index);
887888
888 if (mod.align_stack_fns.get(func_index)) |align_info| {
889 o.addFnAttrInt(llvm_func, "alignstack", align_info.alignment.toByteUnitsOptional().?);
889 if (func.analysis(ip).is_noinline) {
890890 o.addFnAttr(llvm_func, "noinline");
891891 } else {
892 Object.removeFnAttr(llvm_func, "alignstack");
893 if (!func.is_noinline) Object.removeFnAttr(llvm_func, "noinline");
892 Object.removeFnAttr(llvm_func, "noinline");
894893 }
895894
896 if (func.is_cold) {
897 o.addFnAttr(llvm_func, "cold");
895 if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {
896 o.addFnAttrInt(llvm_func, "alignstack", alignment);
897 o.addFnAttr(llvm_func, "noinline");
898898 } else {
899 Object.removeFnAttr(llvm_func, "cold");
899 Object.removeFnAttr(llvm_func, "alignstack");
900900 }
901901
902 if (func.is_noinline) {
903 o.addFnAttr(llvm_func, "noinline");
902 if (func.analysis(ip).is_cold) {
903 o.addFnAttr(llvm_func, "cold");
904904 } else {
905 Object.removeFnAttr(llvm_func, "noinline");
905 Object.removeFnAttr(llvm_func, "cold");
906906 }
907907
908908 // TODO: disable this if safety is off for the function scope
......@@ -921,7 +921,7 @@ pub const Object = struct {
921921 o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
922922 }
923923
924 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
924 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
925925 llvm_func.setSection(section);
926926
927927 // Remove all the basic blocks of a function in order to start over, generating
......@@ -968,7 +968,7 @@ pub const Object = struct {
968968 .byval => {
969969 assert(!it.byval_attr);
970970 const param_index = it.zig_index - 1;
971 const param_ty = fn_info.param_types[param_index].toType();
971 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
972972 const param = llvm_func.getParam(llvm_arg_i);
973973 try args.ensureUnusedCapacity(1);
974974
......@@ -987,7 +987,7 @@ pub const Object = struct {
987987 llvm_arg_i += 1;
988988 },
989989 .byref => {
990 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
990 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
991991 const param_llvm_ty = try o.lowerType(param_ty);
992992 const param = llvm_func.getParam(llvm_arg_i);
993993 const alignment = param_ty.abiAlignment(mod);
......@@ -1006,7 +1006,7 @@ pub const Object = struct {
10061006 }
10071007 },
10081008 .byref_mut => {
1009 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1009 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
10101010 const param_llvm_ty = try o.lowerType(param_ty);
10111011 const param = llvm_func.getParam(llvm_arg_i);
10121012 const alignment = param_ty.abiAlignment(mod);
......@@ -1026,7 +1026,7 @@ pub const Object = struct {
10261026 },
10271027 .abi_sized_int => {
10281028 assert(!it.byval_attr);
1029 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1029 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
10301030 const param = llvm_func.getParam(llvm_arg_i);
10311031 llvm_arg_i += 1;
10321032
......@@ -1053,7 +1053,7 @@ pub const Object = struct {
10531053 },
10541054 .slice => {
10551055 assert(!it.byval_attr);
1056 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1056 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
10571057 const ptr_info = param_ty.ptrInfo(mod);
10581058
10591059 if (math.cast(u5, it.zig_index - 1)) |i| {
......@@ -1083,7 +1083,7 @@ pub const Object = struct {
10831083 .multiple_llvm_types => {
10841084 assert(!it.byval_attr);
10851085 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];
1086 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1086 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
10871087 const param_llvm_ty = try o.lowerType(param_ty);
10881088 const param_alignment = param_ty.abiAlignment(mod);
10891089 const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
......@@ -1114,7 +1114,7 @@ pub const Object = struct {
11141114 args.appendAssumeCapacity(casted);
11151115 },
11161116 .float_array => {
1117 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1117 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
11181118 const param_llvm_ty = try o.lowerType(param_ty);
11191119 const param = llvm_func.getParam(llvm_arg_i);
11201120 llvm_arg_i += 1;
......@@ -1132,7 +1132,7 @@ pub const Object = struct {
11321132 }
11331133 },
11341134 .i32_array, .i64_array => {
1135 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1135 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
11361136 const param_llvm_ty = try o.lowerType(param_ty);
11371137 const param = llvm_func.getParam(llvm_arg_i);
11381138 llvm_arg_i += 1;
......@@ -1168,7 +1168,7 @@ pub const Object = struct {
11681168 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
11691169 const subprogram = dib.createFunction(
11701170 di_file.?.toScope(),
1171 mod.intern_pool.stringToSlice(decl.name),
1171 ip.stringToSlice(decl.name),
11721172 llvm_func.getValueName(),
11731173 di_file.?,
11741174 line_number,
......@@ -1460,6 +1460,7 @@ pub const Object = struct {
14601460 const target = o.target;
14611461 const dib = o.di_builder.?;
14621462 const mod = o.module;
1463 const ip = &mod.intern_pool;
14631464 switch (ty.zigTypeTag(mod)) {
14641465 .Void, .NoReturn => {
14651466 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
......@@ -1492,7 +1493,6 @@ pub const Object = struct {
14921493 return enum_di_ty;
14931494 }
14941495
1495 const ip = &mod.intern_pool;
14961496 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
14971497
14981498 const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);
......@@ -1518,7 +1518,7 @@ pub const Object = struct {
15181518 if (@sizeOf(usize) == @sizeOf(u64)) {
15191519 enumerators[i] = dib.createEnumerator2(
15201520 field_name_z,
1521 @as(c_uint, @intCast(bigint.limbs.len)),
1521 @intCast(bigint.limbs.len),
15221522 bigint.limbs.ptr,
15231523 int_info.bits,
15241524 int_info.signedness == .unsigned,
......@@ -2320,8 +2320,8 @@ pub const Object = struct {
23202320 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
23212321 }
23222322
2323 for (0..mod.typeToFunc(ty).?.param_types.len) |i| {
2324 const param_ty = mod.typeToFunc(ty).?.param_types[i].toType();
2323 for (0..fn_info.param_types.len) |i| {
2324 const param_ty = fn_info.param_types.get(ip)[i].toType();
23252325 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
23262326
23272327 if (isByRef(param_ty, mod)) {
......@@ -2475,9 +2475,10 @@ pub const Object = struct {
24752475 const fn_type = try o.lowerType(zig_fn_type);
24762476
24772477 const fqn = try decl.getFullyQualifiedName(mod);
2478 const ip = &mod.intern_pool;
24782479
24792480 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
2480 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(mod.intern_pool.stringToSlice(fqn), fn_type, llvm_addrspace);
2481 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(ip.stringToSlice(fqn), fn_type, llvm_addrspace);
24812482 gop.value_ptr.* = llvm_fn;
24822483
24832484 const is_extern = decl.isExtern(mod);
......@@ -2486,8 +2487,8 @@ pub const Object = struct {
24862487 llvm_fn.setUnnamedAddr(.True);
24872488 } else {
24882489 if (target.isWasm()) {
2489 o.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name));
2490 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
2490 o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
2491 if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
24912492 if (!std.mem.eql(u8, lib_name, "c")) {
24922493 o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
24932494 }
......@@ -2546,13 +2547,13 @@ pub const Object = struct {
25462547 while (it.next()) |lowering| switch (lowering) {
25472548 .byval => {
25482549 const param_index = it.zig_index - 1;
2549 const param_ty = fn_info.param_types[param_index].toType();
2550 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
25502551 if (!isByRef(param_ty, mod)) {
25512552 o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
25522553 }
25532554 },
25542555 .byref => {
2555 const param_ty = fn_info.param_types[it.zig_index - 1];
2556 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1];
25562557 const param_llvm_ty = try o.lowerType(param_ty.toType());
25572558 const alignment = param_ty.toType().abiAlignment(mod);
25582559 o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
......@@ -3031,6 +3032,7 @@ pub const Object = struct {
30313032
30323033 fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {
30333034 const mod = o.module;
3035 const ip = &mod.intern_pool;
30343036 const fn_info = mod.typeToFunc(fn_ty).?;
30353037 const llvm_ret_ty = try lowerFnRetTy(o, fn_info);
30363038
......@@ -3052,19 +3054,19 @@ pub const Object = struct {
30523054 while (it.next()) |lowering| switch (lowering) {
30533055 .no_bits => continue,
30543056 .byval => {
3055 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3057 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
30563058 try llvm_params.append(try o.lowerType(param_ty));
30573059 },
30583060 .byref, .byref_mut => {
30593061 try llvm_params.append(o.context.pointerType(0));
30603062 },
30613063 .abi_sized_int => {
3062 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3064 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
30633065 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
30643066 try llvm_params.append(o.context.intType(abi_size * 8));
30653067 },
30663068 .slice => {
3067 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3069 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
30683070 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
30693071 param_ty.optionalChild(mod).slicePtrFieldType(mod)
30703072 else
......@@ -3083,7 +3085,7 @@ pub const Object = struct {
30833085 try llvm_params.append(o.context.intType(16));
30843086 },
30853087 .float_array => |count| {
3086 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3088 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
30873089 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
30883090 const field_count = @as(c_uint, @intCast(count));
30893091 const arr_ty = float_ty.arrayType(field_count);
......@@ -3137,8 +3139,7 @@ pub const Object = struct {
31373139 return llvm_type.getUndef();
31383140 }
31393141
3140 const val_key = mod.intern_pool.indexToKey(tv.val.toIntern());
3141 switch (val_key) {
3142 switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
31423143 .int_type,
31433144 .ptr_type,
31443145 .array_type,
......@@ -3175,12 +3176,14 @@ pub const Object = struct {
31753176 .enum_literal,
31763177 .empty_enum_value,
31773178 => unreachable, // non-runtime values
3178 .extern_func, .func => {
3179 const fn_decl_index = switch (val_key) {
3180 .extern_func => |extern_func| extern_func.decl,
3181 .func => |func| mod.funcPtr(func.index).owner_decl,
3182 else => unreachable,
3183 };
3179 .extern_func => |extern_func| {
3180 const fn_decl_index = extern_func.decl;
3181 const fn_decl = mod.declPtr(fn_decl_index);
3182 try mod.markDeclAlive(fn_decl);
3183 return o.resolveLlvmFunction(fn_decl_index);
3184 },
3185 .func => |func| {
3186 const fn_decl_index = func.owner_decl;
31843187 const fn_decl = mod.declPtr(fn_decl_index);
31853188 try mod.markDeclAlive(fn_decl);
31863189 return o.resolveLlvmFunction(fn_decl_index);
......@@ -4598,6 +4601,7 @@ pub const FuncGen = struct {
45984601 const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));
45994602 const o = self.dg.object;
46004603 const mod = o.module;
4604 const ip = &mod.intern_pool;
46014605 const callee_ty = self.typeOf(pl_op.operand);
46024606 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
46034607 .Fn => callee_ty,
......@@ -4801,14 +4805,14 @@ pub const FuncGen = struct {
48014805 while (it.next()) |lowering| switch (lowering) {
48024806 .byval => {
48034807 const param_index = it.zig_index - 1;
4804 const param_ty = fn_info.param_types[param_index].toType();
4808 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
48054809 if (!isByRef(param_ty, mod)) {
48064810 o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
48074811 }
48084812 },
48094813 .byref => {
48104814 const param_index = it.zig_index - 1;
4811 const param_ty = fn_info.param_types[param_index].toType();
4815 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
48124816 const param_llvm_ty = try o.lowerType(param_ty);
48134817 const alignment = param_ty.abiAlignment(mod);
48144818 o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
......@@ -4828,7 +4832,7 @@ pub const FuncGen = struct {
48284832
48294833 .slice => {
48304834 assert(!it.byval_attr);
4831 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
4835 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
48324836 const ptr_info = param_ty.ptrInfo(mod);
48334837 const llvm_arg_i = it.llvm_index - 2;
48344838
......@@ -4930,7 +4934,7 @@ pub const FuncGen = struct {
49304934 fg.context.pointerType(0).constNull(),
49314935 null_opt_addr_global,
49324936 };
4933 const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?;
4937 const panic_func = mod.funcInfo(mod.panic_func_index);
49344938 const panic_decl = mod.declPtr(panic_func.owner_decl);
49354939 const fn_info = mod.typeToFunc(panic_decl.ty).?;
49364940 const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);
......@@ -6030,7 +6034,7 @@ pub const FuncGen = struct {
60306034 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
60316035
60326036 const mod = o.module;
6033 const func = mod.funcPtr(ty_fn.func);
6037 const func = mod.funcInfo(ty_fn.func);
60346038 const decl_index = func.owner_decl;
60356039 const decl = mod.declPtr(decl_index);
60366040 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
......@@ -6039,7 +6043,7 @@ pub const FuncGen = struct {
60396043 const cur_debug_location = self.builder.getCurrentDebugLocation2();
60406044
60416045 try self.dbg_inlined.append(self.gpa, .{
6042 .loc = @as(*llvm.DILocation, @ptrCast(cur_debug_location)),
6046 .loc = @ptrCast(cur_debug_location),
60436047 .scope = self.di_scope.?,
60446048 .base_line = self.base_line,
60456049 });
......@@ -6057,8 +6061,6 @@ pub const FuncGen = struct {
60576061 .is_var_args = false,
60586062 .is_generic = false,
60596063 .is_noinline = false,
6060 .align_is_generic = false,
6061 .cc_is_generic = false,
60626064 .section_is_generic = false,
60636065 .addrspace_is_generic = false,
60646066 });
......@@ -6090,8 +6092,7 @@ pub const FuncGen = struct {
60906092 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
60916093
60926094 const mod = o.module;
6093 const func = mod.funcPtr(ty_fn.func);
6094 const decl = mod.declPtr(func.owner_decl);
6095 const decl = mod.funcOwnerDeclPtr(ty_fn.func);
60956096 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
60966097 self.di_file = di_file;
60976098 const old = self.dbg_inlined.pop();
......@@ -8137,12 +8138,13 @@ pub const FuncGen = struct {
81378138 }
81388139
81398140 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
8140 const func = self.dg.decl.getOwnedFunction(mod).?;
8141 const func_index = self.dg.decl.getOwnedFunctionIndex();
8142 const func = mod.funcInfo(func_index);
81418143 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
81428144 const lbrace_col = func.lbrace_column + 1;
81438145 const di_local_var = dib.createParameterVariable(
81448146 self.di_scope.?,
8145 func.getParamName(mod, src_index).ptr, // TODO test 0 bit args
8147 mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args
81468148 self.di_file.?,
81478149 lbrace_line,
81488150 try o.lowerDebugType(inst_ty, .full),
......@@ -10653,30 +10655,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
1065310655}
1065410656
1065510657fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool {
10656 if (!fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) return false;
10658 const return_type = fn_info.return_type.toType();
10659 if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) return false;
1065710660
1065810661 const target = mod.getTarget();
1065910662 switch (fn_info.cc) {
10660 .Unspecified, .Inline => return isByRef(fn_info.return_type.toType(), mod),
10663 .Unspecified, .Inline => return isByRef(return_type, mod),
1066110664 .C => switch (target.cpu.arch) {
1066210665 .mips, .mipsel => return false,
1066310666 .x86_64 => switch (target.os.tag) {
10664 .windows => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10665 else => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
10667 .windows => return x86_64_abi.classifyWindows(return_type, mod) == .memory,
10668 else => return firstParamSRetSystemV(return_type, mod),
1066610669 },
10667 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type.toType(), mod)[0] == .indirect,
10668 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
10669 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type.toType(), mod, .ret)) {
10670 .wasm32 => return wasm_c_abi.classifyType(return_type, mod)[0] == .indirect,
10671 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(return_type, mod) == .memory,
10672 .arm, .armeb => switch (arm_c_abi.classifyType(return_type, mod, .ret)) {
1067010673 .memory, .i64_array => return true,
1067110674 .i32_array => |size| return size != 1,
1067210675 .byval => return false,
1067310676 },
10674 .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
10677 .riscv32, .riscv64 => return riscv_c_abi.classifyType(return_type, mod) == .memory,
1067510678 else => return false, // TODO investigate C ABI for other architectures
1067610679 },
10677 .SysV => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
10678 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10679 .Stdcall => return !isScalar(mod, fn_info.return_type.toType()),
10680 .SysV => return firstParamSRetSystemV(return_type, mod),
10681 .Win64 => return x86_64_abi.classifyWindows(return_type, mod) == .memory,
10682 .Stdcall => return !isScalar(mod, return_type),
1068010683 else => return false,
1068110684 }
1068210685}
......@@ -10888,13 +10891,17 @@ const ParamTypeIterator = struct {
1088810891
1088910892 pub fn next(it: *ParamTypeIterator) ?Lowering {
1089010893 if (it.zig_index >= it.fn_info.param_types.len) return null;
10891 const ty = it.fn_info.param_types[it.zig_index];
10894 const mod = it.object.module;
10895 const ip = &mod.intern_pool;
10896 const ty = it.fn_info.param_types.get(ip)[it.zig_index];
1089210897 it.byval_attr = false;
1089310898 return nextInner(it, ty.toType());
1089410899 }
1089510900
1089610901 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
1089710902 pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) ?Lowering {
10903 const mod = it.object.module;
10904 const ip = &mod.intern_pool;
1089810905 if (it.zig_index >= it.fn_info.param_types.len) {
1089910906 if (it.zig_index >= args.len) {
1090010907 return null;
......@@ -10902,7 +10909,7 @@ const ParamTypeIterator = struct {
1090210909 return nextInner(it, fg.typeOf(args[it.zig_index]));
1090310910 }
1090410911 } else {
10905 return nextInner(it, it.fn_info.param_types[it.zig_index].toType());
10912 return nextInner(it, it.fn_info.param_types.get(ip)[it.zig_index].toType());
1090610913 }
1090710914 }
1090810915
src/codegen/spirv.zig+12-8
......@@ -238,7 +238,7 @@ pub const DeclGen = struct {
238238 if (ty.zigTypeTag(mod) == .Fn) {
239239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
240240 .extern_func => |extern_func| extern_func.decl,
241 .func => |func| mod.funcPtr(func.index).owner_decl,
241 .func => |func| func.owner_decl,
242242 else => unreachable,
243243 };
244244 const spv_decl_index = try self.resolveDecl(fn_decl_index);
......@@ -255,13 +255,14 @@ pub const DeclGen = struct {
255255 /// Fetch or allocate a result id for decl index. This function also marks the decl as alive.
256256 /// Note: Function does not actually generate the decl.
257257 fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
258 const decl = self.module.declPtr(decl_index);
259 try self.module.markDeclAlive(decl);
258 const mod = self.module;
259 const decl = mod.declPtr(decl_index);
260 try mod.markDeclAlive(decl);
260261
261262 const entry = try self.decl_link.getOrPut(decl_index);
262263 if (!entry.found_existing) {
263264 // TODO: Extern fn?
264 const kind: SpvModule.DeclKind = if (decl.val.getFunctionIndex(self.module) != .none)
265 const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod))
265266 .func
266267 else
267268 .global;
......@@ -1268,6 +1269,7 @@ pub const DeclGen = struct {
12681269 },
12691270 .Fn => switch (repr) {
12701271 .direct => {
1272 const ip = &mod.intern_pool;
12711273 const fn_info = mod.typeToFunc(ty).?;
12721274 // TODO: Put this somewhere in Sema.zig
12731275 if (fn_info.is_var_args)
......@@ -1275,8 +1277,8 @@ pub const DeclGen = struct {
12751277
12761278 const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);
12771279 defer self.gpa.free(param_ty_refs);
1278 for (param_ty_refs, 0..) |*param_type, i| {
1279 param_type.* = try self.resolveType(fn_info.param_types[i].toType(), .direct);
1280 for (param_ty_refs, fn_info.param_types.get(ip)) |*param_type, fn_param_type| {
1281 param_type.* = try self.resolveType(fn_param_type.toType(), .direct);
12801282 }
12811283 const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct);
12821284
......@@ -1576,6 +1578,7 @@ pub const DeclGen = struct {
15761578
15771579 fn genDecl(self: *DeclGen) !void {
15781580 const mod = self.module;
1581 const ip = &mod.intern_pool;
15791582 const decl = mod.declPtr(self.decl_index);
15801583 const spv_decl_index = try self.resolveDecl(self.decl_index);
15811584
......@@ -1594,7 +1597,8 @@ pub const DeclGen = struct {
15941597 const fn_info = mod.typeToFunc(decl.ty).?;
15951598
15961599 try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
1597 for (fn_info.param_types) |param_type| {
1600 for (0..fn_info.param_types.len) |i| {
1601 const param_type = fn_info.param_types.get(ip)[i];
15981602 const param_type_id = try self.resolveTypeId(param_type.toType());
15991603 const arg_result_id = self.spv.allocId();
16001604 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
......@@ -1621,7 +1625,7 @@ pub const DeclGen = struct {
16211625 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
16221626 try self.spv.addFunction(spv_decl_index, self.func);
16231627
1624 const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(self.module));
1628 const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module));
16251629
16261630 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
16271631 .target = decl_id,
src/link.zig+2-1
......@@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig");
1616const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
1717const Liveness = @import("Liveness.zig");
1818const Module = @import("Module.zig");
19const InternPool = @import("InternPool.zig");
1920const Package = @import("Package.zig");
2021const Type = @import("type.zig").Type;
2122const TypedValue = @import("TypedValue.zig");
......@@ -562,7 +563,7 @@ pub const File = struct {
562563 }
563564
564565 /// May be called before or after updateDeclExports for any given Decl.
565 pub fn updateFunc(base: *File, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
566 pub fn updateFunc(base: *File, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
566567 if (build_options.only_c) {
567568 assert(base.tag == .c);
568569 return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness);
src/link/C.zig+2-2
......@@ -88,13 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
8888 }
8989}
9090
91pub fn updateFunc(self: *C, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
91pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
9292 const tracy = trace(@src());
9393 defer tracy.end();
9494
9595 const gpa = self.base.allocator;
9696
97 const func = module.funcPtr(func_index);
97 const func = module.funcInfo(func_index);
9898 const decl_index = func.owner_decl;
9999 const gop = try self.decl_table.getOrPut(gpa, decl_index);
100100 if (!gop.found_existing) {
src/link/Coff.zig+3-3
......@@ -1032,7 +1032,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
10321032 self.getAtomPtr(atom_index).sym_index = 0;
10331033}
10341034
1035pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
1035pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
10361036 if (build_options.skip_non_native and builtin.object_format != .coff) {
10371037 @panic("Attempted to compile for object format that was disabled by build configuration");
10381038 }
......@@ -1044,7 +1044,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: A
10441044 const tracy = trace(@src());
10451045 defer tracy.end();
10461046
1047 const func = mod.funcPtr(func_index);
1047 const func = mod.funcInfo(func_index);
10481048 const decl_index = func.owner_decl;
10491049 const decl = mod.declPtr(decl_index);
10501050
......@@ -1424,7 +1424,7 @@ pub fn updateDeclExports(
14241424 // detect the default subsystem.
14251425 for (exports) |exp| {
14261426 const exported_decl = mod.declPtr(exp.exported_decl);
1427 if (exported_decl.getOwnedFunctionIndex(mod) == .none) continue;
1427 if (exported_decl.getOwnedFunction(mod) == null) continue;
14281428 const winapi_cc = switch (self.base.options.target.cpu.arch) {
14291429 .x86 => std.builtin.CallingConvention.Stdcall,
14301430 else => std.builtin.CallingConvention.C,
src/link/Dwarf.zig+23-34
......@@ -1043,6 +1043,7 @@ pub fn commitDeclState(
10431043 var dbg_line_buffer = &decl_state.dbg_line;
10441044 var dbg_info_buffer = &decl_state.dbg_info;
10451045 const decl = mod.declPtr(decl_index);
1046 const ip = &mod.intern_pool;
10461047
10471048 const target_endian = self.target.cpu.arch.endian();
10481049
......@@ -1241,20 +1242,9 @@ pub fn commitDeclState(
12411242 while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) {
12421243 const symbol = &decl_state.abbrev_table.items[sym_index];
12431244 const ty = symbol.type;
1244 const deferred: bool = blk: {
1245 if (ty.isAnyError(mod)) break :blk true;
1246 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1247 .inferred_error_set_type => |ies_index| {
1248 const ies = mod.inferredErrorSetPtr(ies_index);
1249 if (!ies.is_resolved) break :blk true;
1250 },
1251 else => {},
1252 }
1253 break :blk false;
1254 };
1255 if (deferred) continue;
1245 if (ip.isErrorSetType(ty.toIntern())) continue;
12561246
1257 symbol.offset = @as(u32, @intCast(dbg_info_buffer.items.len));
1247 symbol.offset = @intCast(dbg_info_buffer.items.len);
12581248 try decl_state.addDbgInfoType(mod, di_atom_index, ty);
12591249 }
12601250 }
......@@ -1265,18 +1255,7 @@ pub fn commitDeclState(
12651255 if (reloc.target) |target| {
12661256 const symbol = decl_state.abbrev_table.items[target];
12671257 const ty = symbol.type;
1268 const deferred: bool = blk: {
1269 if (ty.isAnyError(mod)) break :blk true;
1270 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1271 .inferred_error_set_type => |ies_index| {
1272 const ies = mod.inferredErrorSetPtr(ies_index);
1273 if (!ies.is_resolved) break :blk true;
1274 },
1275 else => {},
1276 }
1277 break :blk false;
1278 };
1279 if (deferred) {
1258 if (ip.isErrorSetType(ty.toIntern())) {
12801259 log.debug("resolving %{d} deferred until flush", .{target});
12811260 try self.global_abbrev_relocs.append(gpa, .{
12821261 .target = null,
......@@ -2505,18 +2484,18 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
25052484 defer arena_alloc.deinit();
25062485 const arena = arena_alloc.allocator();
25072486
2508 // TODO: don't create a zig type for this, just make the dwarf info
2509 // without touching the zig type system.
2510 const names = try arena.dupe(InternPool.NullTerminatedString, module.global_error_set.keys());
2511 std.mem.sort(InternPool.NullTerminatedString, names, {}, InternPool.NullTerminatedString.indexLessThan);
2512
2513 const error_ty = try module.intern(.{ .error_set_type = .{ .names = names } });
25142487 var dbg_info_buffer = std.ArrayList(u8).init(arena);
2515 try addDbgInfoErrorSet(module, error_ty.toType(), self.target, &dbg_info_buffer);
2488 try addDbgInfoErrorSetNames(
2489 module,
2490 Type.anyerror,
2491 module.global_error_set.keys(),
2492 self.target,
2493 &dbg_info_buffer,
2494 );
25162495
25172496 const di_atom_index = try self.createAtom(.di_atom);
25182497 log.debug("updateDeclDebugInfoAllocation in flushModule", .{});
2519 try self.updateDeclDebugInfoAllocation(di_atom_index, @as(u32, @intCast(dbg_info_buffer.items.len)));
2498 try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(dbg_info_buffer.items.len));
25202499 log.debug("writeDeclDebugInfo in flushModule", .{});
25212500 try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items);
25222501
......@@ -2633,6 +2612,17 @@ fn addDbgInfoErrorSet(
26332612 ty: Type,
26342613 target: std.Target,
26352614 dbg_info_buffer: *std.ArrayList(u8),
2615) !void {
2616 return addDbgInfoErrorSetNames(mod, ty, ty.errorSetNames(mod), target, dbg_info_buffer);
2617}
2618
2619fn addDbgInfoErrorSetNames(
2620 mod: *Module,
2621 /// Used for printing the type name only.
2622 ty: Type,
2623 error_names: []const InternPool.NullTerminatedString,
2624 target: std.Target,
2625 dbg_info_buffer: *std.ArrayList(u8),
26362626) !void {
26372627 const target_endian = target.cpu.arch.endian();
26382628
......@@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet(
26552645 // DW.AT.const_value, DW.FORM.data8
26562646 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
26572647
2658 const error_names = ty.errorSetNames(mod);
26592648 for (error_names) |error_name_ip| {
26602649 const int = try mod.getErrorValue(error_name_ip);
26612650 const error_name = mod.intern_pool.stringToSlice(error_name_ip);
src/link/Elf.zig+2-2
......@@ -2575,7 +2575,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
25752575 return local_sym;
25762576}
25772577
2578pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
2578pub fn updateFunc(self: *Elf, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
25792579 if (build_options.skip_non_native and builtin.object_format != .elf) {
25802580 @panic("Attempted to compile for object format that was disabled by build configuration");
25812581 }
......@@ -2586,7 +2586,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Ai
25862586 const tracy = trace(@src());
25872587 defer tracy.end();
25882588
2589 const func = mod.funcPtr(func_index);
2589 const func = mod.funcInfo(func_index);
25902590 const decl_index = func.owner_decl;
25912591 const decl = mod.declPtr(decl_index);
25922592
src/link/MachO.zig+2-2
......@@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
18451845 self.markRelocsDirtyByTarget(target);
18461846}
18471847
1848pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
1848pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
18491849 if (build_options.skip_non_native and builtin.object_format != .macho) {
18501850 @panic("Attempted to compile for object format that was disabled by build configuration");
18511851 }
......@@ -1855,7 +1855,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air:
18551855 const tracy = trace(@src());
18561856 defer tracy.end();
18571857
1858 const func = mod.funcPtr(func_index);
1858 const func = mod.funcInfo(func_index);
18591859 const decl_index = func.owner_decl;
18601860 const decl = mod.declPtr(decl_index);
18611861
src/link/NvPtx.zig+2-1
......@@ -13,6 +13,7 @@ const assert = std.debug.assert;
1313const log = std.log.scoped(.link);
1414
1515const Module = @import("../Module.zig");
16const InternPool = @import("../InternPool.zig");
1617const Compilation = @import("../Compilation.zig");
1718const link = @import("../link.zig");
1819const trace = @import("../tracy.zig").trace;
......@@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void {
6869 self.base.allocator.free(self.ptx_file_name);
6970}
7071
71pub fn updateFunc(self: *NvPtx, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
72pub fn updateFunc(self: *NvPtx, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
7273 if (!build_options.have_llvm) return;
7374 try self.llvm_object.updateFunc(module, func_index, air, liveness);
7475}
src/link/Plan9.zig+4-3
......@@ -4,6 +4,7 @@
44const Plan9 = @This();
55const link = @import("../link.zig");
66const Module = @import("../Module.zig");
7const InternPool = @import("../InternPool.zig");
78const Compilation = @import("../Compilation.zig");
89const aout = @import("Plan9/aout.zig");
910const codegen = @import("../codegen.zig");
......@@ -344,12 +345,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi
344345 }
345346}
346347
347pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
348pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
348349 if (build_options.skip_non_native and builtin.object_format != .plan9) {
349350 @panic("Attempted to compile for object format that was disabled by build configuration");
350351 }
351352
352 const func = mod.funcPtr(func_index);
353 const func = mod.funcInfo(func_index);
353354 const decl_index = func.owner_decl;
354355 const decl = mod.declPtr(decl_index);
355356 self.freeUnnamedConsts(decl_index);
......@@ -908,7 +909,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
908909 // in the deleteUnusedDecl function.
909910 const mod = self.base.options.module.?;
910911 const decl = mod.declPtr(decl_index);
911 const is_fn = decl.val.getFunctionIndex(mod) != .none;
912 const is_fn = decl.val.isFuncBody(mod);
912913 if (is_fn) {
913914 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
914915 var submap = symidx_and_submap.functions;
src/link/SpirV.zig+4-3
......@@ -29,6 +29,7 @@ const assert = std.debug.assert;
2929const log = std.log.scoped(.link);
3030
3131const Module = @import("../Module.zig");
32const InternPool = @import("../InternPool.zig");
3233const Compilation = @import("../Compilation.zig");
3334const link = @import("../link.zig");
3435const codegen = @import("../codegen/spirv.zig");
......@@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void {
103104 self.decl_link.deinit();
104105}
105106
106pub fn updateFunc(self: *SpirV, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
107pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
107108 if (build_options.skip_non_native) {
108109 @panic("Attempted to compile for architecture that was disabled by build configuration");
109110 }
110111
111 const func = module.funcPtr(func_index);
112 const func = module.funcInfo(func_index);
112113
113114 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
114115 defer decl_gen.deinit();
......@@ -138,7 +139,7 @@ pub fn updateDeclExports(
138139 exports: []const *Module.Export,
139140) !void {
140141 const decl = mod.declPtr(decl_index);
141 if (decl.val.getFunctionIndex(mod) != .none and decl.ty.fnCallingConvention(mod) == .Kernel) {
142 if (decl.val.isFuncBody(mod) and decl.ty.fnCallingConvention(mod) == .Kernel) {
142143 // TODO: Unify with resolveDecl in spirv.zig.
143144 const entry = try self.decl_link.getOrPut(decl_index);
144145 if (!entry.found_existing) {
src/link/Wasm.zig+3-2
......@@ -12,6 +12,7 @@ const log = std.log.scoped(.link);
1212pub const Atom = @import("Wasm/Atom.zig");
1313const Dwarf = @import("Dwarf.zig");
1414const Module = @import("../Module.zig");
15const InternPool = @import("../InternPool.zig");
1516const Compilation = @import("../Compilation.zig");
1617const CodeGen = @import("../arch/wasm/CodeGen.zig");
1718const codegen = @import("../codegen.zig");
......@@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
13381339 return index;
13391340}
13401341
1341pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
1342pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
13421343 if (build_options.skip_non_native and builtin.object_format != .wasm) {
13431344 @panic("Attempted to compile for object format that was disabled by build configuration");
13441345 }
......@@ -1349,7 +1350,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: A
13491350 const tracy = trace(@src());
13501351 defer tracy.end();
13511352
1352 const func = mod.funcPtr(func_index);
1353 const func = mod.funcInfo(func_index);
13531354 const decl_index = func.owner_decl;
13541355 const decl = mod.declPtr(decl_index);
13551356 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
src/print_air.zig+1-1
......@@ -665,7 +665,7 @@ const Writer = struct {
665665 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
666666 const ty_fn = w.air.instructions.items(.data)[inst].ty_fn;
667667 const func_index = ty_fn.func;
668 const owner_decl = w.module.declPtr(w.module.funcPtr(func_index).owner_decl);
668 const owner_decl = w.module.funcOwnerDeclPtr(func_index);
669669 try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});
670670 }
671671
src/type.zig+53-43
......@@ -250,21 +250,19 @@ pub const Type = struct {
250250 try print(error_union_type.payload_type.toType(), writer, mod);
251251 return;
252252 },
253 .inferred_error_set_type => |index| {
254 const ies = mod.inferredErrorSetPtr(index);
255 const func = ies.func;
256
253 .inferred_error_set_type => |func_index| {
257254 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
258 const owner_decl = mod.declPtr(mod.funcPtr(func).owner_decl);
255 const owner_decl = mod.funcOwnerDeclPtr(func_index);
259256 try owner_decl.renderFullyQualifiedName(mod, writer);
260257 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
261258 },
262259 .error_set_type => |error_set_type| {
260 const ip = &mod.intern_pool;
263261 const names = error_set_type.names;
264262 try writer.writeAll("error{");
265 for (names, 0..) |name, i| {
263 for (names.get(ip), 0..) |name, i| {
266264 if (i != 0) try writer.writeByte(',');
267 try writer.print("{}", .{name.fmt(&mod.intern_pool)});
265 try writer.print("{}", .{name.fmt(ip)});
268266 }
269267 try writer.writeAll("}");
270268 },
......@@ -294,6 +292,7 @@ pub const Type = struct {
294292 .comptime_int,
295293 .comptime_float,
296294 .noreturn,
295 .adhoc_inferred_error_set,
297296 => return writer.writeAll(@tagName(s)),
298297
299298 .null,
......@@ -367,7 +366,8 @@ pub const Type = struct {
367366 try writer.writeAll("noinline ");
368367 }
369368 try writer.writeAll("fn(");
370 for (fn_info.param_types, 0..) |param_ty, i| {
369 const param_types = fn_info.param_types.get(&mod.intern_pool);
370 for (param_types, 0..) |param_ty, i| {
371371 if (i != 0) try writer.writeAll(", ");
372372 if (std.math.cast(u5, i)) |index| {
373373 if (fn_info.paramIsComptime(index)) {
......@@ -384,7 +384,7 @@ pub const Type = struct {
384384 }
385385 }
386386 if (fn_info.is_var_args) {
387 if (fn_info.param_types.len != 0) {
387 if (param_types.len != 0) {
388388 try writer.writeAll(", ");
389389 }
390390 try writer.writeAll("...");
......@@ -534,6 +534,7 @@ pub const Type = struct {
534534 .c_longdouble,
535535 .bool,
536536 .anyerror,
537 .adhoc_inferred_error_set,
537538 .anyopaque,
538539 .atomic_order,
539540 .atomic_rmw_op,
......@@ -697,6 +698,7 @@ pub const Type = struct {
697698 => true,
698699
699700 .anyerror,
701 .adhoc_inferred_error_set,
700702 .anyopaque,
701703 .atomic_order,
702704 .atomic_rmw_op,
......@@ -955,7 +957,9 @@ pub const Type = struct {
955957 },
956958
957959 // TODO revisit this when we have the concept of the error tag type
958 .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 },
960 .anyerror,
961 .adhoc_inferred_error_set,
962 => return AbiAlignmentAdvanced{ .scalar = 2 },
959963
960964 .void,
961965 .type,
......@@ -1419,7 +1423,9 @@ pub const Type = struct {
14191423 => return AbiSizeAdvanced{ .scalar = 0 },
14201424
14211425 // TODO revisit this when we have the concept of the error tag type
1422 .anyerror => return AbiSizeAdvanced{ .scalar = 2 },
1426 .anyerror,
1427 .adhoc_inferred_error_set,
1428 => return AbiSizeAdvanced{ .scalar = 2 },
14231429
14241430 .prefetch_options => unreachable, // missing call to resolveTypeFields
14251431 .export_options => unreachable, // missing call to resolveTypeFields
......@@ -1662,7 +1668,9 @@ pub const Type = struct {
16621668 .void => return 0,
16631669
16641670 // TODO revisit this when we have the concept of the error tag type
1665 .anyerror => return 16,
1671 .anyerror,
1672 .adhoc_inferred_error_set,
1673 => return 16,
16661674
16671675 .anyopaque => unreachable,
16681676 .type => unreachable,
......@@ -2050,21 +2058,19 @@ pub const Type = struct {
20502058
20512059 /// Asserts that the type is an error union.
20522060 pub fn errorUnionSet(ty: Type, mod: *Module) Type {
2053 return mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.error_set_type.toType();
2061 return mod.intern_pool.errorUnionSet(ty.toIntern()).toType();
20542062 }
20552063
20562064 /// Returns false for unresolved inferred error sets.
20572065 pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool {
2066 const ip = &mod.intern_pool;
20582067 return switch (ty.toIntern()) {
20592068 .anyerror_type => false,
2060 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2069 else => switch (ip.indexToKey(ty.toIntern())) {
20612070 .error_set_type => |error_set_type| error_set_type.names.len == 0,
2062 .inferred_error_set_type => |index| {
2063 const inferred_error_set = mod.inferredErrorSetPtr(index);
2064 // Can't know for sure.
2065 if (!inferred_error_set.is_resolved) return false;
2066 if (inferred_error_set.is_anyerror) return false;
2067 return inferred_error_set.errors.count() == 0;
2071 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2072 .none, .anyerror_type => false,
2073 else => |t| ip.indexToKey(t).error_set_type.names.len == 0,
20682074 },
20692075 else => unreachable,
20702076 },
......@@ -2075,10 +2081,11 @@ pub const Type = struct {
20752081 /// Note that the result may be a false negative if the type did not get error set
20762082 /// resolution prior to this call.
20772083 pub fn isAnyError(ty: Type, mod: *Module) bool {
2084 const ip = &mod.intern_pool;
20782085 return switch (ty.toIntern()) {
20792086 .anyerror_type => true,
20802087 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2081 .inferred_error_set_type => |i| mod.inferredErrorSetPtr(i).is_anyerror,
2088 .inferred_error_set_type => |i| ip.funcIesResolved(i).* == .anyerror_type,
20822089 else => false,
20832090 },
20842091 };
......@@ -2102,13 +2109,11 @@ pub const Type = struct {
21022109 return switch (ty) {
21032110 .anyerror_type => true,
21042111 else => switch (ip.indexToKey(ty)) {
2105 .error_set_type => |error_set_type| {
2106 return error_set_type.nameIndex(ip, name) != null;
2107 },
2108 .inferred_error_set_type => |index| {
2109 const ies = ip.inferredErrorSetPtrConst(index);
2110 if (ies.is_anyerror) return true;
2111 return ies.errors.contains(name);
2112 .error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null,
2113 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2114 .anyerror_type => true,
2115 .none => false,
2116 else => |t| ip.indexToKey(t).error_set_type.nameIndex(ip, name) != null,
21122117 },
21132118 else => unreachable,
21142119 },
......@@ -2128,12 +2133,14 @@ pub const Type = struct {
21282133 const field_name_interned = ip.getString(name).unwrap() orelse return false;
21292134 return error_set_type.nameIndex(ip, field_name_interned) != null;
21302135 },
2131 .inferred_error_set_type => |index| {
2132 const ies = ip.inferredErrorSetPtr(index);
2133 if (ies.is_anyerror) return true;
2134 // If the string is not interned, then the field certainly is not present.
2135 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2136 return ies.errors.contains(field_name_interned);
2136 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2137 .anyerror_type => true,
2138 .none => false,
2139 else => |t| {
2140 // If the string is not interned, then the field certainly is not present.
2141 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2142 return ip.indexToKey(t).error_set_type.nameIndex(ip, field_name_interned) != null;
2143 },
21372144 },
21382145 else => unreachable,
21392146 },
......@@ -2231,7 +2238,7 @@ pub const Type = struct {
22312238 var ty = starting_ty;
22322239
22332240 while (true) switch (ty.toIntern()) {
2234 .anyerror_type => {
2241 .anyerror_type, .adhoc_inferred_error_set_type => {
22352242 // TODO revisit this when error sets support custom int types
22362243 return .{ .signedness = .unsigned, .bits = 16 };
22372244 },
......@@ -2365,7 +2372,7 @@ pub const Type = struct {
23652372
23662373 /// Asserts the type is a function or a function pointer.
23672374 pub fn fnReturnType(ty: Type, mod: *Module) Type {
2368 return mod.intern_pool.funcReturnType(ty.toIntern()).toType();
2375 return mod.intern_pool.funcTypeReturnType(ty.toIntern()).toType();
23692376 }
23702377
23712378 /// Asserts the type is a function.
......@@ -2505,6 +2512,7 @@ pub const Type = struct {
25052512 .export_options,
25062513 .extern_options,
25072514 .type_info,
2515 .adhoc_inferred_error_set,
25082516 => return null,
25092517
25102518 .void => return Value.void,
......@@ -2699,6 +2707,7 @@ pub const Type = struct {
26992707 .bool,
27002708 .void,
27012709 .anyerror,
2710 .adhoc_inferred_error_set,
27022711 .noreturn,
27032712 .generic_poison,
27042713 .atomic_order,
......@@ -2942,14 +2951,15 @@ pub const Type = struct {
29422951 }
29432952
29442953 // Asserts that `ty` is an error set and not `anyerror`.
2954 // Asserts that `ty` is resolved if it is an inferred error set.
29452955 pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
2946 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2947 .error_set_type => |x| x.names,
2948 .inferred_error_set_type => |index| {
2949 const inferred_error_set = mod.inferredErrorSetPtr(index);
2950 assert(inferred_error_set.is_resolved);
2951 assert(!inferred_error_set.is_anyerror);
2952 return inferred_error_set.errors.keys();
2956 const ip = &mod.intern_pool;
2957 return switch (ip.indexToKey(ty.toIntern())) {
2958 .error_set_type => |x| x.names.get(ip),
2959 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2960 .none => unreachable, // unresolved inferred error set
2961 .anyerror_type => unreachable,
2962 else => |t| ip.indexToKey(t).error_set_type.names.get(ip),
29532963 },
29542964 else => unreachable,
29552965 };
src/value.zig+13-5
......@@ -262,6 +262,11 @@ pub const Value = struct {
262262 return ip.getOrPutTrailingString(gpa, len);
263263 }
264264
265 pub fn intern2(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
266 if (val.ip_index != .none) return val.ip_index;
267 return intern(val, ty, mod);
268 }
269
265270 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
266271 if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();
267272 switch (val.tag()) {
......@@ -473,12 +478,15 @@ pub const Value = struct {
473478 };
474479 }
475480
476 pub fn getFunction(val: Value, mod: *Module) ?*Module.Fn {
477 return mod.funcPtrUnwrap(val.getFunctionIndex(mod));
481 pub fn isFuncBody(val: Value, mod: *Module) bool {
482 return mod.intern_pool.isFuncBody(val.toIntern());
478483 }
479484
480 pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex {
481 return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.toIntern()) else .none;
485 pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func {
486 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
487 .func => |x| x,
488 else => null,
489 };
482490 }
483491
484492 pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
......@@ -1462,7 +1470,7 @@ pub const Value = struct {
14621470 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
14631471 .variable => |variable| variable.decl,
14641472 .extern_func => |extern_func| extern_func.decl,
1465 .func => |func| mod.funcPtr(func.index).owner_decl,
1473 .func => |func| func.owner_decl,
14661474 .ptr => |ptr| switch (ptr.addr) {
14671475 .decl => |decl| decl,
14681476 .mut_decl => |mut_decl| mut_decl.decl,
test/behavior/generics.zig+13
......@@ -443,3 +443,16 @@ test "generic function passed as comptime argument" {
443443 };
444444 try S.doMath(std.math.add, 5, 6);
445445}
446
447test "return type of generic function is function pointer" {
448 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
449 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
450
451 const S = struct {
452 fn b(comptime T: type) ?*const fn () error{}!T {
453 return null;
454 }
455 };
456
457 try expect(null == S.b(void));
458}
test/cases/compile_errors/anytype_param_requires_comptime.zig+4-2
......@@ -16,5 +16,7 @@ pub export fn entry() void {
1616// backend=stage2
1717// target=native
1818//
19// :7:14: error: unable to resolve comptime value
20// :7:14: note: argument to parameter with comptime-only type must be comptime-known
19// :7:14: error: runtime-known argument passed to comptime-only type parameter
20// :9:12: note: declared here
21// :4:16: note: struct requires comptime because of this field
22// :4:16: note: types are not available at runtime
test/cases/compile_errors/export_function_with_comptime_parameter.zig+1-1
......@@ -6,4 +6,4 @@ export fn foo(comptime x: anytype, y: i32) i32 {
66// backend=stage2
77// target=native
88//
9// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
9// :1:27: error: comptime parameters not allowed in function with calling convention 'C'
test/cases/compile_errors/export_generic_function.zig+1-1
......@@ -7,4 +7,4 @@ export fn foo(num: anytype) i32 {
77// backend=stage2
88// target=native
99//
10// :1:15: error: generic parameters not allowed in function with calling convention 'C'
10// :1:20: error: generic parameters not allowed in function with calling convention 'C'
test/cases/compile_errors/extern_function_with_comptime_parameter.zig+1-1
......@@ -19,5 +19,5 @@ comptime {
1919// target=native
2020//
2121// :5:30: error: comptime parameters not allowed in function with calling convention 'C'
22// :6:30: error: generic parameters not allowed in function with calling convention 'C'
22// :6:41: error: generic parameters not allowed in function with calling convention 'C'
2323// :1:15: error: comptime parameters not allowed in function with calling convention 'C'
test/cases/compile_errors/generic_function_instance_with_non-constant_expression.zig+2-2
......@@ -13,5 +13,5 @@ export fn entry() usize {
1313// backend=stage2
1414// target=native
1515//
16// :5:16: error: unable to resolve comptime value
17// :5:16: note: parameter is comptime
16// :5:16: error: runtime-known argument passed to comptime parameter
17// :1:17: note: declared comptime here
test/standalone.zig-4
......@@ -213,10 +213,6 @@ pub const build_cases = [_]BuildCase{
213213 // .build_root = "test/standalone/sigpipe",
214214 // .import = @import("standalone/sigpipe/build.zig"),
215215 //},
216 .{
217 .build_root = "test/standalone/issue_13030",
218 .import = @import("standalone/issue_13030/build.zig"),
219 },
220216 // TODO restore this test
221217 //.{
222218 // .build_root = "test/standalone/options",
test/standalone/issue_13030/build.zig deleted-24
......@@ -1,24 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const CrossTarget = std.zig.CrossTarget;
4
5pub fn build(b: *std.Build) void {
6 const test_step = b.step("test", "Test it");
7 b.default_step = test_step;
8
9 add(b, test_step, .Debug);
10 add(b, test_step, .ReleaseFast);
11 add(b, test_step, .ReleaseSmall);
12 add(b, test_step, .ReleaseSafe);
13}
14
15fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
16 const obj = b.addObject(.{
17 .name = "main",
18 .root_source_file = .{ .path = "main.zig" },
19 .optimize = optimize,
20 .target = .{},
21 });
22
23 test_step.dependOn(&obj.step);
24}
test/standalone/issue_13030/main.zig deleted-7
......@@ -1,7 +0,0 @@
1fn b(comptime T: type) ?*const fn () error{}!T {
2 return null;
3}
4
5export fn entry() void {
6 _ = b(void);
7}