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(...@@ -1669,8 +1669,9 @@ pub fn ArrayHashMapUnmanaged(
16691669
1670 inline fn checkedHash(ctx: anytype, key: anytype) u32 {1670 inline fn checkedHash(ctx: anytype, key: anytype) u32 {
1671 comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(key), K, u32, true);1671 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 that1672 // If you get a compile error on the next line, it means that your
1673 const hash = ctx.hash(key); // your generic hash function doesn't accept your key1673 // generic hash function doesn't accept your key.
1674 const hash = ctx.hash(key);
1674 if (@TypeOf(hash) != u32) {1675 if (@TypeOf(hash) != u32) {
1675 @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic hash function that returns the wrong type!\n" ++1676 @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic hash function that returns the wrong type!\n" ++
1676 @typeName(u32) ++ " was expected, but found " ++ @typeName(@TypeOf(hash)));1677 @typeName(u32) ++ " was expected, but found " ++ @typeName(@TypeOf(hash)));
...@@ -1679,8 +1680,9 @@ pub fn ArrayHashMapUnmanaged(...@@ -1679,8 +1680,9 @@ pub fn ArrayHashMapUnmanaged(
1679 }1680 }
1680 inline fn checkedEql(ctx: anytype, a: anytype, b: K, b_index: usize) bool {1681 inline fn checkedEql(ctx: anytype, a: anytype, b: K, b_index: usize) bool {
1681 comptime std.hash_map.verifyContext(@TypeOf(ctx), @TypeOf(a), K, u32, true);1682 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 that1683 // If you get a compile error on the next line, it means that your
1683 const eql = ctx.eql(a, b, b_index); // your generic eql function doesn't accept (self, adapt key, K, index)1684 // generic eql function doesn't accept (self, adapt key, K, index).
1685 const eql = ctx.eql(a, b, b_index);
1684 if (@TypeOf(eql) != bool) {1686 if (@TypeOf(eql) != bool) {
1685 @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic eql function that returns the wrong type!\n" ++1687 @compileError("Context " ++ @typeName(@TypeOf(ctx)) ++ " has a generic eql function that returns the wrong type!\n" ++
1686 @typeName(bool) ++ " was expected, but found " ++ @typeName(@TypeOf(eql)));1688 @typeName(bool) ++ " was expected, but found " ++ @typeName(@TypeOf(eql)));
src/Air.zig+3-2
...@@ -946,6 +946,7 @@ pub const Inst = struct {...@@ -946,6 +946,7 @@ pub const Inst = struct {
946 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),946 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
947 optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),947 optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),
948 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),948 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),
949 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),950 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
950 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),951 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),
951 undef = @intFromEnum(InternPool.Index.undef),952 undef = @intFromEnum(InternPool.Index.undef),
...@@ -1003,7 +1004,7 @@ pub const Inst = struct {...@@ -1003,7 +1004,7 @@ pub const Inst = struct {
1003 },1004 },
1004 ty_fn: struct {1005 ty_fn: struct {
1005 ty: Ref,1006 ty: Ref,
1006 func: Module.Fn.Index,1007 func: InternPool.Index,
1007 },1008 },
1008 br: struct {1009 br: struct {
1009 block_inst: Index,1010 block_inst: Index,
...@@ -1436,7 +1437,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)...@@ -1436,7 +1437,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
14361437
1437 .call, .call_always_tail, .call_never_tail, .call_never_inline => {1438 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
1438 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);1439 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();
1440 },1441 },
14411442
1442 .slice_elem_val, .ptr_elem_val, .array_elem_val => {1443 .slice_elem_val, .ptr_elem_val, .array_elem_val => {
src/AstGen.zig+4-1
...@@ -12095,7 +12095,10 @@ const GenZir = struct {...@@ -12095,7 +12095,10 @@ const GenZir = struct {
12095 return gz.addAsIndex(.{12095 return gz.addAsIndex(.{
12096 .tag = .save_err_ret_index,12096 .tag = .save_err_ret_index,
12097 .data = .{ .save_err_ret_index = .{12097 .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 },
12099 } },12102 } },
12100 });12103 });
12101 }12104 }
src/Autodoc.zig+1
...@@ -281,6 +281,7 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -281,6 +281,7 @@ pub fn generateZirData(self: *Autodoc) !void {
281 // Poison and special tag281 // Poison and special tag
282 .generic_poison_type,282 .generic_poison_type,
283 .var_args_param_type,283 .var_args_param_type,
284 .adhoc_inferred_error_set_type,
284 => .{285 => .{
285 .Type = .{ .name = try tmpbuf.toOwnedSlice() },286 .Type = .{ .name = try tmpbuf.toOwnedSlice() },
286 },287 },
src/Compilation.zig+5-10
...@@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig");...@@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig");
29const fatal = @import("main.zig").fatal;29const fatal = @import("main.zig").fatal;
30const clangMain = @import("main.zig").clangMain;30const clangMain = @import("main.zig").clangMain;
31const Module = @import("Module.zig");31const Module = @import("Module.zig");
32const InternPool = @import("InternPool.zig");
32const BuildId = std.Build.CompileStep.BuildId;33const BuildId = std.Build.CompileStep.BuildId;
33const Cache = std.Build.Cache;34const Cache = std.Build.Cache;
34const translate_c = @import("translate_c.zig");35const translate_c = @import("translate_c.zig");
...@@ -227,7 +228,8 @@ const Job = union(enum) {...@@ -227,7 +228,8 @@ const Job = union(enum) {
227 /// Write the constant value for a Decl to the output file.228 /// Write the constant value for a Decl to the output file.
228 codegen_decl: Module.Decl.Index,229 codegen_decl: Module.Decl.Index,
229 /// Write the machine code for a function to the output file.230 /// 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,
231 /// Render the .h file snippet for the Decl.233 /// Render the .h file snippet for the Decl.
232 emit_h_decl: Module.Decl.Index,234 emit_h_decl: Module.Decl.Index,
233 /// The Decl needs to be analyzed and possibly export itself.235 /// 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...@@ -2053,15 +2055,9 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2053 const decl = module.declPtr(decl_index);2055 const decl = module.declPtr(decl_index);
2054 assert(decl.deletion_flag);2056 assert(decl.deletion_flag);
2055 assert(decl.dependants.count() == 0);2057 assert(decl.dependants.count() == 0);
2056 const is_anon = if (decl.zir_decl_index == 0) blk: {2058 assert(decl.zir_decl_index != 0);
2057 break :blk module.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index);
2058 } else false;
20592059
2060 try module.clearDecl(decl_index, null);2060 try module.clearDecl(decl_index, null);
2061
2062 if (is_anon) {
2063 module.destroyDecl(decl_index);
2064 }
2065 }2061 }
20662062
2067 try module.processExports();2063 try module.processExports();
...@@ -3216,8 +3212,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v...@@ -3216,8 +3212,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
3216 // Tests are always emitted in test binaries. The decl_refs are created by3212 // Tests are always emitted in test binaries. The decl_refs are created by
3217 // Module.populateTestFunctions, but this will not queue body analysis, so do3213 // Module.populateTestFunctions, but this will not queue body analysis, so do
3218 // that now.3214 // that now.
3219 const func_index = module.intern_pool.indexToFunc(decl.val.ip_index).unwrap().?;3215 try module.ensureFuncBodyAnalysisQueued(decl.val.toIntern());
3220 try module.ensureFuncBodyAnalysisQueued(func_index);
3221 }3216 }
3222 },3217 },
3223 .update_embed_file => |embed_file| {3218 .update_embed_file => |embed_file| {
src/InternPool.zig+1679-574
...@@ -20,6 +20,25 @@ limbs: std.ArrayListUnmanaged(u64) = .{},...@@ -20,6 +20,25 @@ limbs: std.ArrayListUnmanaged(u64) = .{},
20/// `string_bytes` array is agnostic to either usage.20/// `string_bytes` array is agnostic to either usage.
21string_bytes: std.ArrayListUnmanaged(u8) = .{},21string_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
23/// Struct objects are stored in this data structure because:42/// Struct objects are stored in this data structure because:
24/// * They contain pointers such as the field maps.43/// * They contain pointers such as the field maps.
25/// * They need to be mutated after creation.44/// * They need to be mutated after creation.
...@@ -34,25 +53,11 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},...@@ -34,25 +53,11 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},
34/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.53/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.
35unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},54unions_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
51/// Some types such as enums, structs, and unions need to store mappings from field names56/// Some types such as enums, structs, and unions need to store mappings from field names
52/// to field index, or value to field index. In such cases, they will store the underlying57/// to field index, or value to field index. In such cases, they will store the underlying
53/// field names and values directly, relying on one of these maps, stored separately,58/// field names and values directly, relying on one of these maps, stored separately,
54/// to provide lookup.59/// to provide lookup.
55maps: std.ArrayListUnmanaged(std.AutoArrayHashMapUnmanaged(void, void)) = .{},60maps: std.ArrayListUnmanaged(FieldMap) = .{},
5661
57/// Used for finding the index inside `string_bytes`.62/// Used for finding the index inside `string_bytes`.
58string_table: std.HashMapUnmanaged(63string_table: std.HashMapUnmanaged(
...@@ -62,6 +67,10 @@ string_table: std.HashMapUnmanaged(...@@ -62,6 +67,10 @@ string_table: std.HashMapUnmanaged(
62 std.hash_map.default_max_load_percentage,67 std.hash_map.default_max_load_percentage,
63) = .{},68) = .{},
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
65const builtin = @import("builtin");74const builtin = @import("builtin");
66const std = @import("std");75const std = @import("std");
67const Allocator = std.mem.Allocator;76const Allocator = std.mem.Allocator;
...@@ -73,6 +82,7 @@ const Hash = std.hash.Wyhash;...@@ -73,6 +82,7 @@ const Hash = std.hash.Wyhash;
7382
74const InternPool = @This();83const InternPool = @This();
75const Module = @import("Module.zig");84const Module = @import("Module.zig");
85const Zir = @import("Zir.zig");
76const Sema = @import("Sema.zig");86const Sema = @import("Sema.zig");
7787
78const KeyAdapter = struct {88const KeyAdapter = struct {
...@@ -129,12 +139,24 @@ pub const NullTerminatedString = enum(u32) {...@@ -129,12 +139,24 @@ pub const NullTerminatedString = enum(u32) {
129 empty = 0,139 empty = 0,
130 _,140 _,
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
132 pub fn toString(self: NullTerminatedString) String {154 pub fn toString(self: NullTerminatedString) String {
133 return @as(String, @enumFromInt(@intFromEnum(self)));155 return @enumFromInt(@intFromEnum(self));
134 }156 }
135157
136 pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString {158 pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString {
137 return @as(OptionalNullTerminatedString, @enumFromInt(@intFromEnum(self)));159 return @enumFromInt(@intFromEnum(self));
138 }160 }
139161
140 const Adapter = struct {162 const Adapter = struct {
...@@ -224,7 +246,8 @@ pub const Key = union(enum) {...@@ -224,7 +246,8 @@ pub const Key = union(enum) {
224 enum_type: EnumType,246 enum_type: EnumType,
225 func_type: FuncType,247 func_type: FuncType,
226 error_set_type: ErrorSetType,248 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
229 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented252 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
230 /// via `simple_value` and has a named `Index` tag for it.253 /// via `simple_value` and has a named `Index` tag for it.
...@@ -273,16 +296,16 @@ pub const Key = union(enum) {...@@ -273,16 +296,16 @@ pub const Key = union(enum) {
273296
274 pub const ErrorSetType = struct {297 pub const ErrorSetType = struct {
275 /// Set of error names, sorted by null terminated string index.298 /// Set of error names, sorted by null terminated string index.
276 names: []const NullTerminatedString,299 names: NullTerminatedString.Slice,
277 /// This is ignored by `get` but will always be provided by `indexToKey`.300 /// This is ignored by `get` but will always be provided by `indexToKey`.
278 names_map: OptionalMapIndex = .none,301 names_map: OptionalMapIndex = .none,
279302
280 /// Look up field index based on field name.303 /// Look up field index based on field name.
281 pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 {304 pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
282 const map = &ip.maps.items[@intFromEnum(self.names_map.unwrap().?)];305 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) };
284 const field_index = map.getIndexAdapted(name, adapter) orelse return null;307 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
285 return @as(u32, @intCast(field_index));308 return @intCast(field_index);
286 }309 }
287 };310 };
288311
...@@ -487,7 +510,7 @@ pub const Key = union(enum) {...@@ -487,7 +510,7 @@ pub const Key = union(enum) {
487 };510 };
488511
489 pub const FuncType = struct {512 pub const FuncType = struct {
490 param_types: []Index,513 param_types: Index.Slice,
491 return_type: Index,514 return_type: Index,
492 /// Tells whether a parameter is comptime. See `paramIsComptime` helper515 /// Tells whether a parameter is comptime. See `paramIsComptime` helper
493 /// method for accessing this.516 /// method for accessing this.
...@@ -518,6 +541,32 @@ pub const Key = union(enum) {...@@ -518,6 +541,32 @@ pub const Key = union(enum) {
518 assert(i < self.param_types.len);541 assert(i < self.param_types.len);
519 return @as(u1, @truncate(self.noalias_bits >> i)) != 0;542 return @as(u1, @truncate(self.noalias_bits >> i)) != 0;
520 }543 }
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 }
521 };570 };
522571
523 pub const Variable = struct {572 pub const Variable = struct {
...@@ -541,10 +590,73 @@ pub const Key = union(enum) {...@@ -541,10 +590,73 @@ pub const Key = union(enum) {
541 lib_name: OptionalNullTerminatedString,590 lib_name: OptionalNullTerminatedString,
542 };591 };
543592
544 /// Extern so it can be hashed by reinterpreting memory.593 pub const Func = struct {
545 pub const Func = extern 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.
546 ty: Index,596 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 }
548 };660 };
549661
550 pub const Int = struct {662 pub const Int = struct {
...@@ -679,13 +791,13 @@ pub const Key = union(enum) {...@@ -679,13 +791,13 @@ pub const Key = union(enum) {
679 };791 };
680792
681 pub const MemoizedCall = struct {793 pub const MemoizedCall = struct {
682 func: Module.Fn.Index,794 func: Index,
683 arg_values: []const Index,795 arg_values: []const Index,
684 result: Index,796 result: Index,
685 };797 };
686798
687 pub fn hash32(key: Key, ip: *const InternPool) u32 {799 pub fn hash32(key: Key, ip: *const InternPool) u32 {
688 return @as(u32, @truncate(key.hash64(ip)));800 return @truncate(key.hash64(ip));
689 }801 }
690802
691 pub fn hash64(key: Key, ip: *const InternPool) u64 {803 pub fn hash64(key: Key, ip: *const InternPool) u64 {
...@@ -695,7 +807,6 @@ pub const Key = union(enum) {...@@ -695,7 +807,6 @@ pub const Key = union(enum) {
695 return switch (key) {807 return switch (key) {
696 // TODO: assert no padding in these types808 // TODO: assert no padding in these types
697 inline .ptr_type,809 inline .ptr_type,
698 .func,
699 .array_type,810 .array_type,
700 .vector_type,811 .vector_type,
701 .opt_type,812 .opt_type,
...@@ -723,20 +834,11 @@ pub const Key = union(enum) {...@@ -723,20 +834,11 @@ pub const Key = union(enum) {
723 },834 },
724835
725 .runtime_value => |x| Hash.hash(seed, asBytes(&x.val)),836 .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| {838 inline .opaque_type,
735 var hasher = Hash.init(seed);839 .enum_type,
736 std.hash.autoHash(&hasher, variable.decl);840 .variable,
737 return hasher.final();841 => |x| Hash.hash(seed, asBytes(&x.decl)),
738 },
739 .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)),
740842
741 .int => |int| {843 .int => |int| {
742 var hasher = Hash.init(seed);844 var hasher = Hash.init(seed);
...@@ -859,11 +961,7 @@ pub const Key = union(enum) {...@@ -859,11 +961,7 @@ pub const Key = union(enum) {
859 return hasher.final();961 return hasher.final();
860 },962 },
861963
862 .error_set_type => |error_set_type| {964 .error_set_type => |x| Hash.hash(seed, std.mem.sliceAsBytes(x.names.get(ip))),
863 var hasher = Hash.init(seed);
864 for (error_set_type.names) |elem| std.hash.autoHash(&hasher, elem);
865 return hasher.final();
866 },
867965
868 .anon_struct_type => |anon_struct_type| {966 .anon_struct_type => |anon_struct_type| {
869 var hasher = Hash.init(seed);967 var hasher = Hash.init(seed);
...@@ -875,15 +973,7 @@ pub const Key = union(enum) {...@@ -875,15 +973,7 @@ pub const Key = union(enum) {
875973
876 .func_type => |func_type| {974 .func_type => |func_type| {
877 var hasher = Hash.init(seed);975 var hasher = Hash.init(seed);
878 for (func_type.param_types) |param_type| std.hash.autoHash(&hasher, param_type);976 func_type.hash(&hasher, ip);
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);
887 return hasher.final();977 return hasher.final();
888 },978 },
889979
...@@ -893,6 +983,30 @@ pub const Key = union(enum) {...@@ -893,6 +983,30 @@ pub const Key = union(enum) {
893 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg);983 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg);
894 return hasher.final();984 return hasher.final();
895 },985 },
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)),
896 };1010 };
897 }1011 }
8981012
...@@ -993,7 +1107,41 @@ pub const Key = union(enum) {...@@ -993,7 +1107,41 @@ pub const Key = union(enum) {
993 },1107 },
994 .func => |a_info| {1108 .func => |a_info| {
995 const b_info = b.func;1109 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);
997 },1145 },
9981146
999 .ptr => |a_info| {1147 .ptr => |a_info| {
...@@ -1145,7 +1293,7 @@ pub const Key = union(enum) {...@@ -1145,7 +1293,7 @@ pub const Key = union(enum) {
1145 },1293 },
1146 .error_set_type => |a_info| {1294 .error_set_type => |a_info| {
1147 const b_info = b.error_set_type;1295 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));
1149 },1297 },
1150 .inferred_error_set_type => |a_info| {1298 .inferred_error_set_type => |a_info| {
1151 const b_info = b.inferred_error_set_type;1299 const b_info = b.inferred_error_set_type;
...@@ -1154,16 +1302,7 @@ pub const Key = union(enum) {...@@ -1154,16 +1302,7 @@ pub const Key = union(enum) {
11541302
1155 .func_type => |a_info| {1303 .func_type => |a_info| {
1156 const b_info = b.func_type;1304 const b_info = b.func_type;
11571305 return Key.FuncType.eql(a_info, b_info, ip);
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;
1167 },1306 },
11681307
1169 .memoized_call => |a_info| {1308 .memoized_call => |a_info| {
...@@ -1311,6 +1450,8 @@ pub const Index = enum(u32) {...@@ -1311,6 +1450,8 @@ pub const Index = enum(u32) {
1311 slice_const_u8_sentinel_0_type,1450 slice_const_u8_sentinel_0_type,
1312 optional_noreturn_type,1451 optional_noreturn_type,
1313 anyerror_void_error_union_type,1452 anyerror_void_error_union_type,
1453 /// Used for the inferred error set of inline/comptime function calls.
1454 adhoc_inferred_error_set_type,
1314 generic_poison_type,1455 generic_poison_type,
1315 /// `@TypeOf(.{})`1456 /// `@TypeOf(.{})`
1316 empty_struct_type,1457 empty_struct_type,
...@@ -1360,6 +1501,18 @@ pub const Index = enum(u32) {...@@ -1360,6 +1501,18 @@ pub const Index = enum(u32) {
13601501
1361 _,1502 _,
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
1363 pub fn toType(i: Index) @import("type.zig").Type {1516 pub fn toType(i: Index) @import("type.zig").Type {
1364 assert(i != .none);1517 assert(i != .none);
1365 return .{ .ip_index = i };1518 return .{ .ip_index = i };
...@@ -1390,6 +1543,7 @@ pub const Index = enum(u32) {...@@ -1390,6 +1543,7 @@ pub const Index = enum(u32) {
13901543
1391 /// This function is used in the debugger pretty formatters in tools/ to fetch the1544 /// This function is used in the debugger pretty formatters in tools/ to fetch the
1392 /// Tag to encoding mapping to facilitate fancy debug printing for this type.1545 /// Tag to encoding mapping to facilitate fancy debug printing for this type.
1546 /// TODO merge this with `Tag.Payload`.
1393 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {1547 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {
1394 const DataIsIndex = struct { data: Index };1548 const DataIsIndex = struct { data: Index };
1395 const DataIsExtraIndexOfEnumExplicit = struct {1549 const DataIsExtraIndexOfEnumExplicit = struct {
...@@ -1425,13 +1579,14 @@ pub const Index = enum(u32) {...@@ -1425,13 +1579,14 @@ pub const Index = enum(u32) {
1425 type_optional: DataIsIndex,1579 type_optional: DataIsIndex,
1426 type_anyframe: DataIsIndex,1580 type_anyframe: DataIsIndex,
1427 type_error_union: struct { data: *Key.ErrorUnionType },1581 type_error_union: struct { data: *Key.ErrorUnionType },
1582 type_anyerror_union: DataIsIndex,
1428 type_error_set: struct {1583 type_error_set: struct {
1429 const @"data.names_len" = opaque {};1584 const @"data.names_len" = opaque {};
1430 data: *ErrorSet,1585 data: *Tag.ErrorSet,
1431 @"trailing.names.len": *@"data.names_len",1586 @"trailing.names.len": *@"data.names_len",
1432 trailing: struct { names: []NullTerminatedString },1587 trailing: struct { names: []NullTerminatedString },
1433 },1588 },
1434 type_inferred_error_set: struct { data: Module.Fn.InferredErrorSet.Index },1589 type_inferred_error_set: DataIsIndex,
1435 type_enum_auto: struct {1590 type_enum_auto: struct {
1436 const @"data.fields_len" = opaque {};1591 const @"data.fields_len" = opaque {};
1437 data: *EnumAuto,1592 data: *EnumAuto,
...@@ -1450,10 +1605,14 @@ pub const Index = enum(u32) {...@@ -1450,10 +1605,14 @@ pub const Index = enum(u32) {
1450 type_union_untagged: struct { data: Module.Union.Index },1605 type_union_untagged: struct { data: Module.Union.Index },
1451 type_union_safety: struct { data: Module.Union.Index },1606 type_union_safety: struct { data: Module.Union.Index },
1452 type_function: struct {1607 type_function: struct {
1608 const @"data.flags.has_comptime_bits" = opaque {};
1609 const @"data.flags.has_noalias_bits" = opaque {};
1453 const @"data.params_len" = opaque {};1610 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",
1455 @"trailing.param_types.len": *@"data.params_len",1614 @"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 },
1457 },1616 },
14581617
1459 undef: DataIsIndex,1618 undef: DataIsIndex,
...@@ -1497,7 +1656,23 @@ pub const Index = enum(u32) {...@@ -1497,7 +1656,23 @@ pub const Index = enum(u32) {
1497 float_comptime_float: struct { data: *Float128 },1656 float_comptime_float: struct { data: *Float128 },
1498 variable: struct { data: *Tag.Variable },1657 variable: struct { data: *Tag.Variable },
1499 extern_func: struct { data: *Key.ExternFunc },1658 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 },
1501 only_possible_value: DataIsIndex,1676 only_possible_value: DataIsIndex,
1502 union_value: struct { data: *Key.Union },1677 union_value: struct { data: *Key.Union },
1503 bytes: struct { data: *Bytes },1678 bytes: struct { data: *Bytes },
...@@ -1716,6 +1891,8 @@ pub const static_keys = [_]Key{...@@ -1716,6 +1891,8 @@ pub const static_keys = [_]Key{
1716 .payload_type = .void_type,1891 .payload_type = .void_type,
1717 } },1892 } },
17181893
1894 // adhoc_inferred_error_set_type
1895 .{ .simple_type = .adhoc_inferred_error_set },
1719 // generic_poison_type1896 // generic_poison_type
1720 .{ .simple_type = .generic_poison },1897 .{ .simple_type = .generic_poison },
17211898
...@@ -1822,11 +1999,14 @@ pub const Tag = enum(u8) {...@@ -1822,11 +1999,14 @@ pub const Tag = enum(u8) {
1822 /// An error union type.1999 /// An error union type.
1823 /// data is payload to `Key.ErrorUnionType`.2000 /// data is payload to `Key.ErrorUnionType`.
1824 type_error_union,2001 type_error_union,
2002 /// An error union type of the form `anyerror!T`.
2003 /// data is `Index` of payload type.
2004 type_anyerror_union,
1825 /// An error set type.2005 /// An error set type.
1826 /// data is payload to `ErrorSet`.2006 /// data is payload to `ErrorSet`.
1827 type_error_set,2007 type_error_set,
1828 /// The inferred error set type of a function.2008 /// 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`.
1830 type_inferred_error_set,2010 type_inferred_error_set,
1831 /// An enum type with auto-numbered tag values.2011 /// An enum type with auto-numbered tag values.
1832 /// The enum is exhaustive.2012 /// The enum is exhaustive.
...@@ -2005,11 +2185,19 @@ pub const Tag = enum(u8) {...@@ -2005,11 +2185,19 @@ pub const Tag = enum(u8) {
2005 /// data is extra index to Variable.2185 /// data is extra index to Variable.
2006 variable,2186 variable,
2007 /// An extern function.2187 /// An extern function.
2008 /// data is extra index to Key.ExternFunc.2188 /// data is extra index to ExternFunc.
2009 extern_func,2189 extern_func,
2010 /// A regular function.2190 /// A non-extern function corresponding directly to the AST node from whence it originated.
2011 /// data is extra index to Func.2191 /// data is extra index to `FuncDecl`.
2012 func,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,
2013 /// This represents the only possible value for *some* types which have2201 /// This represents the only possible value for *some* types which have
2014 /// only one possible value. Not all only-possible-values are encoded this way;2202 /// only one possible value. Not all only-possible-values are encoded this way;
2015 /// for example structs which have all comptime fields are not encoded this way.2203 /// for example structs which have all comptime fields are not encoded this way.
...@@ -2041,7 +2229,6 @@ pub const Tag = enum(u8) {...@@ -2041,7 +2229,6 @@ pub const Tag = enum(u8) {
2041 const Error = Key.Error;2229 const Error = Key.Error;
2042 const EnumTag = Key.EnumTag;2230 const EnumTag = Key.EnumTag;
2043 const ExternFunc = Key.ExternFunc;2231 const ExternFunc = Key.ExternFunc;
2044 const Func = Key.Func;
2045 const Union = Key.Union;2232 const Union = Key.Union;
2046 const TypePointer = Key.PtrType;2233 const TypePointer = Key.PtrType;
20472234
...@@ -2057,6 +2244,7 @@ pub const Tag = enum(u8) {...@@ -2057,6 +2244,7 @@ pub const Tag = enum(u8) {
2057 .type_optional => unreachable,2244 .type_optional => unreachable,
2058 .type_anyframe => unreachable,2245 .type_anyframe => unreachable,
2059 .type_error_union => ErrorUnionType,2246 .type_error_union => ErrorUnionType,
2247 .type_anyerror_union => unreachable,
2060 .type_error_set => ErrorSet,2248 .type_error_set => ErrorSet,
2061 .type_inferred_error_set => unreachable,2249 .type_inferred_error_set => unreachable,
2062 .type_enum_auto => EnumAuto,2250 .type_enum_auto => EnumAuto,
...@@ -2114,7 +2302,9 @@ pub const Tag = enum(u8) {...@@ -2114,7 +2302,9 @@ pub const Tag = enum(u8) {
2114 .float_comptime_float => unreachable,2302 .float_comptime_float => unreachable,
2115 .variable => Variable,2303 .variable => Variable,
2116 .extern_func => ExternFunc,2304 .extern_func => ExternFunc,
2117 .func => Func,2305 .func_decl => FuncDecl,
2306 .func_instance => FuncInstance,
2307 .func_coerced => FuncCoerced,
2118 .only_possible_value => unreachable,2308 .only_possible_value => unreachable,
2119 .union_value => Union,2309 .union_value => Union,
2120 .bytes => Bytes,2310 .bytes => Bytes,
...@@ -2150,36 +2340,107 @@ pub const Tag = enum(u8) {...@@ -2150,36 +2340,107 @@ pub const Tag = enum(u8) {
2150 /// The type of the aggregate.2340 /// The type of the aggregate.
2151 ty: Index,2341 ty: Index,
2152 };2342 };
2153};
21542343
2155/// Trailing:2344 /// Trailing:
2156/// 0. name: NullTerminatedString for each names_len2345 /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which
2157pub const ErrorSet = struct {2346 /// is a regular error set corresponding to the finished inferred error set.
2158 names_len: u32,2347 /// A `none` value marks that the inferred error set is not resolved yet.
2159 /// Maps error names to declaration index.2348 pub const FuncDecl = struct {
2160 names_map: MapIndex,2349 analysis: FuncAnalysis,
2161};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:2359 /// Trailing:
2164/// 0. param_type: Index for each params_len2360 /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which
2165pub const TypeFunction = struct {2361 /// is a regular error set corresponding to the finished inferred error set.
2166 params_len: u32,2362 /// A `none` value marks that the inferred error set is not resolved yet.
2167 return_type: Index,2363 /// 1. For each parameter of generic_owner: `Index` if comptime, otherwise `none`
2168 comptime_bits: u32,2364 pub const FuncInstance = struct {
2169 noalias_bits: u32,2365 analysis: FuncAnalysis,
2170 flags: Flags,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) {2374 pub const FuncCoerced = struct {
2173 alignment: Alignment,2375 ty: Index,
2174 cc: std.builtin.CallingConvention,2376 func: Index,
2175 is_var_args: bool,2377 };
2176 is_generic: bool,2378
2177 is_noinline: bool,2379 /// Trailing:
2178 align_is_generic: bool,2380 /// 0. name: NullTerminatedString for each names_len
2179 cc_is_generic: bool,2381 pub const ErrorSet = struct {
2180 section_is_generic: bool,2382 names_len: u32,
2181 addrspace_is_generic: bool,2383 /// Maps error names to declaration index.
2182 _: u11 = 0,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,
2183 };2444 };
2184};2445};
21852446
...@@ -2251,6 +2512,7 @@ pub const SimpleType = enum(u32) {...@@ -2251,6 +2512,7 @@ pub const SimpleType = enum(u32) {
2251 extern_options,2512 extern_options,
2252 type_info,2513 type_info,
22532514
2515 adhoc_inferred_error_set,
2254 generic_poison,2516 generic_poison,
2255};2517};
22562518
...@@ -2499,7 +2761,7 @@ pub const Float128 = struct {...@@ -2499,7 +2761,7 @@ pub const Float128 = struct {
2499/// Trailing:2761/// Trailing:
2500/// 0. arg value: Index for each args_len2762/// 0. arg value: Index for each args_len
2501pub const MemoizedCall = struct {2763pub const MemoizedCall = struct {
2502 func: Module.Fn.Index,2764 func: Index,
2503 args_len: u32,2765 args_len: u32,
2504 result: Index,2766 result: Index,
2505};2767};
...@@ -2553,11 +2815,11 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -2553,11 +2815,11 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
2553 ip.unions_free_list.deinit(gpa);2815 ip.unions_free_list.deinit(gpa);
2554 ip.allocated_unions.deinit(gpa);2816 ip.allocated_unions.deinit(gpa);
25552817
2556 ip.funcs_free_list.deinit(gpa);2818 ip.decls_free_list.deinit(gpa);
2557 ip.allocated_funcs.deinit(gpa);2819 ip.allocated_decls.deinit(gpa);
25582820
2559 ip.inferred_error_sets_free_list.deinit(gpa);2821 ip.namespaces_free_list.deinit(gpa);
2560 ip.allocated_inferred_error_sets.deinit(gpa);2822 ip.allocated_namespaces.deinit(gpa);
25612823
2562 for (ip.maps.items) |*map| map.deinit(gpa);2824 for (ip.maps.items) |*map| map.deinit(gpa);
2563 ip.maps.deinit(gpa);2825 ip.maps.deinit(gpa);
...@@ -2620,26 +2882,22 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2620,26 +2882,22 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2620 return .{ .ptr_type = ptr_info };2882 return .{ .ptr_type = ptr_info };
2621 },2883 },
26222884
2623 .type_optional => .{ .opt_type = @as(Index, @enumFromInt(data)) },2885 .type_optional => .{ .opt_type = @enumFromInt(data) },
2624 .type_anyframe => .{ .anyframe_type = @as(Index, @enumFromInt(data)) },2886 .type_anyframe => .{ .anyframe_type = @enumFromInt(data) },
26252887
2626 .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) },2888 .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) },
2627 .type_error_set => {2889 .type_anyerror_union => .{ .error_union_type = .{
2628 const error_set = ip.extraDataTrail(ErrorSet, data);2890 .error_set_type = .anyerror_type,
2629 const names_len = error_set.data.names_len;2891 .payload_type = @enumFromInt(data),
2630 const names = ip.extra.items[error_set.end..][0..names_len];2892 } },
2631 return .{ .error_set_type = .{2893 .type_error_set => .{ .error_set_type = ip.extraErrorSet(data) },
2632 .names = @as([]const NullTerminatedString, @ptrCast(names)),
2633 .names_map = error_set.data.names_map.toOptional(),
2634 } };
2635 },
2636 .type_inferred_error_set => .{2894 .type_inferred_error_set => .{
2637 .inferred_error_set_type = @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(data)),2895 .inferred_error_set_type = @enumFromInt(data),
2638 },2896 },
26392897
2640 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },2898 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
2641 .type_struct => {2899 .type_struct => {
2642 const struct_index = @as(Module.Struct.OptionalIndex, @enumFromInt(data));2900 const struct_index: Module.Struct.OptionalIndex = @enumFromInt(data);
2643 const namespace = if (struct_index.unwrap()) |i|2901 const namespace = if (struct_index.unwrap()) |i|
2644 ip.structPtrConst(i).namespace.toOptional()2902 ip.structPtrConst(i).namespace.toOptional()
2645 else2903 else
...@@ -2661,9 +2919,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2661,9 +2919,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2661 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];2919 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
2662 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];2920 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];
2663 return .{ .anon_struct_type = .{2921 return .{ .anon_struct_type = .{
2664 .types = @as([]const Index, @ptrCast(types)),2922 .types = @ptrCast(types),
2665 .values = @as([]const Index, @ptrCast(values)),2923 .values = @ptrCast(values),
2666 .names = @as([]const NullTerminatedString, @ptrCast(names)),2924 .names = @ptrCast(names),
2667 } };2925 } };
2668 },2926 },
2669 .type_tuple_anon => {2927 .type_tuple_anon => {
...@@ -2672,8 +2930,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2672,8 +2930,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2672 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];2930 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
2673 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];2931 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
2674 return .{ .anon_struct_type = .{2932 return .{ .anon_struct_type = .{
2675 .types = @as([]const Index, @ptrCast(types)),2933 .types = @ptrCast(types),
2676 .values = @as([]const Index, @ptrCast(values)),2934 .values = @ptrCast(values),
2677 .names = &.{},2935 .names = &.{},
2678 } };2936 } };
2679 },2937 },
...@@ -2710,7 +2968,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2710,7 +2968,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2710 },2968 },
2711 .type_enum_explicit => ip.indexToKeyEnum(data, .explicit),2969 .type_enum_explicit => ip.indexToKeyEnum(data, .explicit),
2712 .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive),2970 .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive),
2713 .type_function => .{ .func_type = ip.indexToKeyFuncType(data) },2971 .type_function => .{ .func_type = ip.extraFuncType(data) },
27142972
2715 .undef => .{ .undef = @as(Index, @enumFromInt(data)) },2973 .undef => .{ .undef = @as(Index, @enumFromInt(data)) },
2716 .runtime_value => .{ .runtime_value = ip.extraData(Tag.TypeValue, data) },2974 .runtime_value => .{ .runtime_value = ip.extraData(Tag.TypeValue, data) },
...@@ -2957,7 +3215,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2957,7 +3215,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2957 } };3215 } };
2958 },3216 },
2959 .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) },3217 .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) },
2961 .only_possible_value => {3221 .only_possible_value => {
2962 const ty = @as(Index, @enumFromInt(data));3222 const ty = @as(Index, @enumFromInt(data));
2963 const ty_item = ip.items.get(@intFromEnum(ty));3223 const ty_item = ip.items.get(@intFromEnum(ty));
...@@ -3062,27 +3322,104 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -3062,27 +3322,104 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
3062 };3322 };
3063}3323}
30643324
3065fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType {3325fn extraErrorSet(ip: *const InternPool, extra_index: u32) Key.ErrorSetType {
3066 const type_function = ip.extraDataTrail(TypeFunction, data);3326 const error_set = ip.extraDataTrail(Tag.ErrorSet, extra_index);
3067 const param_types = @as(3327 return .{
3068 []Index,3328 .names = .{
3069 @ptrCast(ip.extra.items[type_function.end..][0..type_function.data.params_len]),3329 .start = @intCast(error_set.end),
3070 );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 };
3071 return .{3349 return .{
3072 .param_types = param_types,3350 .param_types = .{
3351 .start = @intCast(index),
3352 .len = type_function.data.params_len,
3353 },
3073 .return_type = type_function.data.return_type,3354 .return_type = type_function.data.return_type,
3074 .comptime_bits = type_function.data.comptime_bits,3355 .comptime_bits = comptime_bits,
3075 .noalias_bits = type_function.data.noalias_bits,3356 .noalias_bits = noalias_bits,
3076 .alignment = type_function.data.flags.alignment,3357 .alignment = type_function.data.flags.alignment,
3077 .cc = type_function.data.flags.cc,3358 .cc = type_function.data.flags.cc,
3078 .is_var_args = type_function.data.flags.is_var_args,3359 .is_var_args = type_function.data.flags.is_var_args,
3079 .is_generic = type_function.data.flags.is_generic,
3080 .is_noinline = type_function.data.flags.is_noinline,3360 .is_noinline = type_function.data.flags.is_noinline,
3081 .align_is_generic = type_function.data.flags.align_is_generic,3361 .align_is_generic = type_function.data.flags.align_is_generic,
3082 .cc_is_generic = type_function.data.flags.cc_is_generic,3362 .cc_is_generic = type_function.data.flags.cc_is_generic,
3083 .section_is_generic = type_function.data.flags.section_is_generic,3363 .section_is_generic = type_function.data.flags.section_is_generic,
3084 .addrspace_is_generic = type_function.data.flags.addrspace_is_generic,3364 .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,
3085 };3420 };
3421 func.ty = func_coerced.ty;
3422 return func;
3086}3423}
30873424
3088fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {3425fn 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...@@ -3122,7 +3459,7 @@ fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key
3122pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {3459pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3123 const adapter: KeyAdapter = .{ .intern_pool = ip };3460 const adapter: KeyAdapter = .{ .intern_pool = ip };
3124 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);3461 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);
3126 try ip.items.ensureUnusedCapacity(gpa, 1);3463 try ip.items.ensureUnusedCapacity(gpa, 1);
3127 switch (key) {3464 switch (key) {
3128 .int_type => |int_type| {3465 .int_type => |int_type| {
...@@ -3213,26 +3550,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3213,26 +3550,29 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3213 });3550 });
3214 },3551 },
3215 .error_union_type => |error_union_type| {3552 .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 .{
3217 .tag = .type_error_union,3557 .tag = .type_error_union,
3218 .data = try ip.addExtra(gpa, error_union_type),3558 .data = try ip.addExtra(gpa, error_union_type),
3219 });3559 });
3220 },3560 },
3221 .error_set_type => |error_set_type| {3561 .error_set_type => |error_set_type| {
3222 assert(error_set_type.names_map == .none);3562 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));
3224 const names_map = try ip.addMap(gpa);3564 const names_map = try ip.addMap(gpa);
3225 try addStringsToMap(ip, gpa, names_map, error_set_type.names);3565 try addStringsToMap(ip, gpa, names_map, error_set_type.names.get(ip));
3226 const names_len = @as(u32, @intCast(error_set_type.names.len));3566 const names_len = error_set_type.names.len;
3227 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(ErrorSet).Struct.fields.len + names_len);3567 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.ErrorSet).Struct.fields.len + names_len);
3228 ip.items.appendAssumeCapacity(.{3568 ip.items.appendAssumeCapacity(.{
3229 .tag = .type_error_set,3569 .tag = .type_error_set,
3230 .data = ip.addExtraAssumeCapacity(ErrorSet{3570 .data = ip.addExtraAssumeCapacity(Tag.ErrorSet{
3231 .names_len = names_len,3571 .names_len = names_len,
3232 .names_map = names_map,3572 .names_map = names_map,
3233 }),3573 }),
3234 });3574 });
3235 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(error_set_type.names)));3575 ip.extra.appendSliceAssumeCapacity(@ptrCast(error_set_type.names.get(ip)));
3236 },3576 },
3237 .inferred_error_set_type => |ies_index| {3577 .inferred_error_set_type => |ies_index| {
3238 ip.items.appendAssumeCapacity(.{3578 ip.items.appendAssumeCapacity(.{
...@@ -3369,36 +3709,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3369,36 +3709,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3369 }3709 }
3370 },3710 },
33713711
3372 .func_type => |func_type| {3712 .func_type => unreachable, // use getFuncType() instead
3373 assert(func_type.return_type != .none);3713 .extern_func => unreachable, // use getExternFunc() instead
3374 for (func_type.param_types) |param_type| assert(param_type != .none);3714 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead
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 },
34023715
3403 .variable => |variable| {3716 .variable => |variable| {
3404 const has_init = variable.init != .none;3717 const has_init = variable.init != .none;
...@@ -3420,16 +3733,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3420,16 +3733,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3420 });3733 });
3421 },3734 },
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
3433 .ptr => |ptr| {3736 .ptr => |ptr| {
3434 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;3737 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
3435 switch (ptr.len) {3738 switch (ptr.len) {
...@@ -4065,108 +4368,705 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4065,108 +4368,705 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4065 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values)));4368 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(memoized_call.arg_values)));
4066 },4369 },
4067 }4370 }
4068 return @as(Index, @enumFromInt(ip.items.len - 1));4371 return @enumFromInt(ip.items.len - 1);
4069}4372}
40704373
4071/// Provides API for completing an enum type after calling `getIncompleteEnum`.4374/// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`.
4072pub const IncompleteEnumType = struct {4375pub const GetFuncTypeKey = struct {
4073 index: Index,4376 param_types: []Index,
4074 tag_ty_index: u32,4377 return_type: Index,
4075 names_map: MapIndex,4378 comptime_bits: u32,
4076 names_start: u32,4379 noalias_bits: u32,
4077 values_map: OptionalMapIndex,4380 /// `null` means generic.
4078 values_start: u32,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 {4391pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocator.Error!Index {
4081 assert(tag_ty == .noreturn_type or ip.isIntegerType(tag_ty));4392 // Validate input parameters.
4082 ip.extra.items[self.tag_ty_index] = @intFromEnum(tag_ty);4393 assert(key.return_type != .none);
4083 }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.4408 const func_type_extra_index = ip.addExtraAssumeCapacity(Tag.TypeFunction{
4086 pub fn addFieldName(4409 .params_len = params_len,
4087 self: @This(),4410 .return_type = key.return_type,
4088 ip: *InternPool,4411 .flags = .{
4089 gpa: Allocator,4412 .alignment = key.alignment orelse .none,
4090 name: NullTerminatedString,4413 .cc = key.cc orelse .Unspecified,
4091 ) Allocator.Error!?u32 {4414 .is_var_args = key.is_var_args,
4092 const map = &ip.maps.items[@intFromEnum(self.names_map)];4415 .has_comptime_bits = key.comptime_bits != 0,
4093 const field_index = map.count();4416 .has_noalias_bits = key.noalias_bits != 0,
4094 const strings = ip.extra.items[self.names_start..][0..field_index];4417 .is_generic = key.is_generic,
4095 const adapter: NullTerminatedString.Adapter = .{4418 .is_noinline = key.is_noinline,
4096 .strings = @as([]const NullTerminatedString, @ptrCast(strings)),4419 .align_is_generic = key.alignment == null,
4097 };4420 .cc_is_generic = key.cc == null,
4098 const gop = try map.getOrPutAdapted(gpa, name, adapter);4421 .section_is_generic = key.section_is_generic,
4099 if (gop.found_existing) return @as(u32, @intCast(gop.index));4422 .addrspace_is_generic = key.addrspace_is_generic,
4100 ip.extra.items[self.names_start + field_index] = @intFromEnum(name);4423 },
4101 return null;4424 });
4102 }
41034425
4104 /// Returns the already-existing field with the same value, if any.4426 if (key.comptime_bits != 0) ip.extra.appendAssumeCapacity(key.comptime_bits);
4105 /// Make sure the type of the value has the integer tag type of the enum.4427 if (key.noalias_bits != 0) ip.extra.appendAssumeCapacity(key.noalias_bits);
4106 pub fn addFieldValue(4428 ip.extra.appendSliceAssumeCapacity(@ptrCast(key.param_types));
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};
41254429
4126/// This is used to create an enum type in the `InternPool`, with the ability4430 const adapter: KeyAdapter = .{ .intern_pool = ip };
4127/// to update the tag type, field names, and field values later.4431 const gop = try ip.map.getOrPutAdapted(gpa, Key{
4128pub fn getIncompleteEnum(4432 .func_type = extraFuncType(ip, func_type_extra_index),
4129 ip: *InternPool,4433 }, adapter);
4130 gpa: Allocator,4434 if (gop.found_existing) {
4131 enum_type: Key.IncompleteEnumType,4435 ip.extra.items.len = prev_extra_len;
4132) Allocator.Error!IncompleteEnumType {4436 return @enumFromInt(gop.index);
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),
4137 }4437 }
4138}
41394438
4140fn getIncompleteEnumAuto(4439 ip.items.appendAssumeCapacity(.{
4141 ip: *InternPool,4440 .tag = .type_function,
4142 gpa: Allocator,4441 .data = func_type_extra_index,
4143 enum_type: Key.IncompleteEnumType,4442 });
4144) Allocator.Error!IncompleteEnumType {4443 return @enumFromInt(ip.items.len - 1);
4145 const int_tag_type = if (enum_type.tag_ty != .none)4444}
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 } });
41524445
4153 // We must keep the map in sync with `items`. The hash and equality functions4446pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: Key.ExternFunc) Allocator.Error!Index {
4154 // for enum types only look at the decl field, which is present even in
4155 // an `IncompleteEnumType`.
4156 const adapter: KeyAdapter = .{ .intern_pool = ip };4447 const adapter: KeyAdapter = .{ .intern_pool = ip };
4157 const gop = try ip.map.getOrPutAdapted(gpa, enum_type.toKey(), adapter);4448 const gop = try ip.map.getOrPutAdapted(gpa, Key{ .extern_func = key }, adapter);
4158 assert(!gop.found_existing);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;4474pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index {
4163 try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.fields_len);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);
4164 try ip.items.ensureUnusedCapacity(gpa, 1);4481 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{4502 const adapter: KeyAdapter = .{ .intern_pool = ip };
4167 .decl = enum_type.decl,4503 const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{
4168 .namespace = enum_type.namespace,4504 .func = extraFuncDecl(ip, func_decl_extra_index),
4169 .int_tag_type = int_tag_type,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,
4170 .names_map = names_map,5070 .names_map = names_map,
4171 .fields_len = enum_type.fields_len,5071 .fields_len = enum_type.fields_len,
4172 });5072 });
...@@ -4265,15 +5165,15 @@ pub fn finishGetEnum(...@@ -4265,15 +5165,15 @@ pub fn finishGetEnum(
4265 .values_map = values_map,5165 .values_map = values_map,
4266 }),5166 }),
4267 });5167 });
4268 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.names)));5168 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.names));
4269 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(enum_type.values)));5169 ip.extra.appendSliceAssumeCapacity(@ptrCast(enum_type.values));
4270 return @as(Index, @enumFromInt(ip.items.len - 1));5170 return @enumFromInt(ip.items.len - 1);
4271}5171}
42725172
4273pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {5173pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {
4274 const adapter: KeyAdapter = .{ .intern_pool = ip };5174 const adapter: KeyAdapter = .{ .intern_pool = ip };
4275 const index = ip.map.getIndexAdapted(key, adapter) orelse return null;5175 const index = ip.map.getIndexAdapted(key, adapter) orelse return null;
4276 return @as(Index, @enumFromInt(index));5176 return @enumFromInt(index);
4277}5177}
42785178
4279pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {5179pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {
...@@ -4311,7 +5211,7 @@ fn addIndexesToMap(...@@ -4311,7 +5211,7 @@ fn addIndexesToMap(
4311fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex {5211fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex {
4312 const ptr = try ip.maps.addOne(gpa);5212 const ptr = try ip.maps.addOne(gpa);
4313 ptr.* = .{};5213 ptr.* = .{};
4314 return @as(MapIndex, @enumFromInt(ip.maps.items.len - 1));5214 return @enumFromInt(ip.maps.items.len - 1);
4315}5215}
43165216
4317/// This operation only happens under compile error conditions.5217/// This operation only happens under compile error conditions.
...@@ -4342,24 +5242,28 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -4342,24 +5242,28 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
4342 const result = @as(u32, @intCast(ip.extra.items.len));5242 const result = @as(u32, @intCast(ip.extra.items.len));
4343 inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| {5243 inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| {
4344 ip.extra.appendAssumeCapacity(switch (field.type) {5244 ip.extra.appendAssumeCapacity(switch (field.type) {
4345 u32 => @field(extra, field.name),5245 Index,
4346 Index => @intFromEnum(@field(extra, field.name)),5246 Module.Decl.Index,
4347 Module.Decl.Index => @intFromEnum(@field(extra, field.name)),5247 Module.Namespace.Index,
4348 Module.Namespace.Index => @intFromEnum(@field(extra, field.name)),5248 Module.Namespace.OptionalIndex,
4349 Module.Namespace.OptionalIndex => @intFromEnum(@field(extra, field.name)),5249 MapIndex,
4350 Module.Fn.Index => @intFromEnum(@field(extra, field.name)),5250 OptionalMapIndex,
4351 MapIndex => @intFromEnum(@field(extra, field.name)),5251 RuntimeIndex,
4352 OptionalMapIndex => @intFromEnum(@field(extra, field.name)),5252 String,
4353 RuntimeIndex => @intFromEnum(@field(extra, field.name)),5253 NullTerminatedString,
4354 String => @intFromEnum(@field(extra, field.name)),5254 OptionalNullTerminatedString,
4355 NullTerminatedString => @intFromEnum(@field(extra, field.name)),5255 Tag.TypePointer.VectorIndex,
4356 OptionalNullTerminatedString => @intFromEnum(@field(extra, field.name)),5256 => @intFromEnum(@field(extra, field.name)),
4357 i32 => @as(u32, @bitCast(@field(extra, field.name))),5257
4358 Tag.TypePointer.Flags => @as(u32, @bitCast(@field(extra, field.name))),5258 u32,
4359 TypeFunction.Flags => @as(u32, @bitCast(@field(extra, field.name))),5259 i32,
4360 Tag.TypePointer.PackedOffset => @as(u32, @bitCast(@field(extra, field.name))),5260 FuncAnalysis,
4361 Tag.TypePointer.VectorIndex => @intFromEnum(@field(extra, field.name)),5261 Tag.TypePointer.Flags,
4362 Tag.Variable.Flags => @as(u32, @bitCast(@field(extra, field.name))),5262 Tag.TypeFunction.Flags,
5263 Tag.TypePointer.PackedOffset,
5264 Tag.Variable.Flags,
5265 => @bitCast(@field(extra, field.name)),
5266
4363 else => @compileError("bad field type: " ++ @typeName(field.type)),5267 else => @compileError("bad field type: " ++ @typeName(field.type)),
4364 });5268 });
4365 }5269 }
...@@ -4404,36 +5308,40 @@ fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void {...@@ -4404,36 +5308,40 @@ fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void {
4404 }5308 }
4405}5309}
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 } {
4408 var result: T = undefined;5312 var result: T = undefined;
4409 const fields = @typeInfo(T).Struct.fields;5313 const fields = @typeInfo(T).Struct.fields;
4410 inline for (fields, 0..) |field, i| {5314 inline for (fields, 0..) |field, i| {
4411 const int32 = ip.extra.items[i + index];5315 const int32 = ip.extra.items[i + index];
4412 @field(result, field.name) = switch (field.type) {5316 @field(result, field.name) = switch (field.type) {
4413 u32 => int32,5317 Index,
4414 Index => @as(Index, @enumFromInt(int32)),5318 Module.Decl.Index,
4415 Module.Decl.Index => @as(Module.Decl.Index, @enumFromInt(int32)),5319 Module.Namespace.Index,
4416 Module.Namespace.Index => @as(Module.Namespace.Index, @enumFromInt(int32)),5320 Module.Namespace.OptionalIndex,
4417 Module.Namespace.OptionalIndex => @as(Module.Namespace.OptionalIndex, @enumFromInt(int32)),5321 MapIndex,
4418 Module.Fn.Index => @as(Module.Fn.Index, @enumFromInt(int32)),5322 OptionalMapIndex,
4419 MapIndex => @as(MapIndex, @enumFromInt(int32)),5323 RuntimeIndex,
4420 OptionalMapIndex => @as(OptionalMapIndex, @enumFromInt(int32)),5324 String,
4421 RuntimeIndex => @as(RuntimeIndex, @enumFromInt(int32)),5325 NullTerminatedString,
4422 String => @as(String, @enumFromInt(int32)),5326 OptionalNullTerminatedString,
4423 NullTerminatedString => @as(NullTerminatedString, @enumFromInt(int32)),5327 Tag.TypePointer.VectorIndex,
4424 OptionalNullTerminatedString => @as(OptionalNullTerminatedString, @enumFromInt(int32)),5328 => @enumFromInt(int32),
4425 i32 => @as(i32, @bitCast(int32)),5329
4426 Tag.TypePointer.Flags => @as(Tag.TypePointer.Flags, @bitCast(int32)),5330 u32,
4427 TypeFunction.Flags => @as(TypeFunction.Flags, @bitCast(int32)),5331 i32,
4428 Tag.TypePointer.PackedOffset => @as(Tag.TypePointer.PackedOffset, @bitCast(int32)),5332 Tag.TypePointer.Flags,
4429 Tag.TypePointer.VectorIndex => @as(Tag.TypePointer.VectorIndex, @enumFromInt(int32)),5333 Tag.TypeFunction.Flags,
4430 Tag.Variable.Flags => @as(Tag.Variable.Flags, @bitCast(int32)),5334 Tag.TypePointer.PackedOffset,
5335 Tag.Variable.Flags,
5336 FuncAnalysis,
5337 => @bitCast(int32),
5338
4431 else => @compileError("bad field type: " ++ @typeName(field.type)),5339 else => @compileError("bad field type: " ++ @typeName(field.type)),
4432 };5340 };
4433 }5341 }
4434 return .{5342 return .{
4435 .data = result,5343 .data = result,
4436 .end = index + fields.len,5344 .end = @intCast(index + fields.len),
4437 };5345 };
4438}5346}
44395347
...@@ -4603,206 +5511,226 @@ pub fn sliceLen(ip: *const InternPool, i: Index) Index {...@@ -4603,206 +5511,226 @@ pub fn sliceLen(ip: *const InternPool, i: Index) Index {
4603pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {5511pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
4604 const old_ty = ip.typeOf(val);5512 const old_ty = ip.typeOf(val);
4605 if (old_ty == new_ty) return val;5513 if (old_ty == new_ty) return val;
5514
5515 const tags = ip.items.items(.tag);
5516
4606 switch (val) {5517 switch (val) {
4607 .undef => return ip.get(gpa, .{ .undef = new_ty }),5518 .undef => return ip.get(gpa, .{ .undef = new_ty }),
4608 .null_value => if (ip.isOptionalType(new_ty))5519 .null_value => {
4609 return ip.get(gpa, .{ .opt = .{5520 if (ip.isOptionalType(new_ty)) return ip.get(gpa, .{ .opt = .{
4610 .ty = new_ty,5521 .ty = new_ty,
4611 .val = .none,5522 .val = .none,
4612 } })5523 } });
4613 else if (ip.isPointerType(new_ty))5524
4614 return ip.get(gpa, .{ .ptr = .{5525 if (ip.isPointerType(new_ty)) return ip.get(gpa, .{ .ptr = .{
4615 .ty = new_ty,5526 .ty = new_ty,
4616 .addr = .{ .int = .zero_usize },5527 .addr = .{ .int = .zero_usize },
4617 .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) {5528 .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) {
4618 .One, .Many, .C => .none,5529 .One, .Many, .C => .none,
4619 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),5530 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
4620 },5531 },
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,
4621 } }),5559 } }),
4622 else => switch (ip.indexToKey(val)) {5560
4623 .undef => return ip.get(gpa, .{ .undef = new_ty }),5561 .func => unreachable,
4624 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))5562
4625 return ip.get(gpa, .{ .extern_func = .{5563 .int => |int| switch (ip.indexToKey(new_ty)) {
4626 .ty = new_ty,5564 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
4627 .decl = extern_func.decl,5565 .ty = new_ty,
4628 .lib_name = extern_func.lib_name,5566 .int = try ip.getCoerced(gpa, val, enum_type.tag_ty),
4629 } }),5567 } }),
4630 .func => |func| if (ip.isFunctionType(new_ty))5568 .ptr_type => return ip.get(gpa, .{ .ptr = .{
4631 return ip.get(gpa, .{ .func = .{5569 .ty = new_ty,
4632 .ty = new_ty,5570 .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) },
4633 .index = func.index,5571 } }),
4634 } }),5572 else => if (ip.isIntegerType(new_ty))
4635 .int => |int| switch (ip.indexToKey(new_ty)) {5573 return getCoercedInts(ip, gpa, int, new_ty),
4636 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{5574 },
4637 .ty = new_ty,5575 .float => |float| switch (ip.indexToKey(new_ty)) {
4638 .int = try ip.getCoerced(gpa, val, enum_type.tag_ty),5576 .simple_type => |simple| switch (simple) {
4639 } }),5577 .f16,
4640 .ptr_type => return ip.get(gpa, .{ .ptr = .{5578 .f32,
5579 .f64,
5580 .f80,
5581 .f128,
5582 .c_longdouble,
5583 .comptime_float,
5584 => return ip.get(gpa, .{ .float = .{
4641 .ty = new_ty,5585 .ty = new_ty,
4642 .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) },5586 .storage = float.storage,
4643 } }),5587 } }),
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 },
4662 else => {},5588 else => {},
4663 },5589 },
4664 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))5590 else => {},
4665 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),5591 },
4666 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {5592 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
4667 .enum_type => |enum_type| {5593 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
4668 const index = enum_type.nameIndex(ip, enum_literal).?;5594 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
4669 return ip.get(gpa, .{ .enum_tag = .{5595 .enum_type => |enum_type| {
4670 .ty = new_ty,5596 const index = enum_type.nameIndex(ip, enum_literal).?;
4671 .int = if (enum_type.values.len != 0)5597 return ip.get(gpa, .{ .enum_tag = .{
4672 enum_type.values[index]5598 .ty = new_ty,
4673 else5599 .int = if (enum_type.values.len != 0)
4674 try ip.get(gpa, .{ .int = .{5600 enum_type.values[index]
4675 .ty = enum_type.tag_ty,5601 else
4676 .storage = .{ .u64 = index },5602 try ip.get(gpa, .{ .int = .{
4677 } }),5603 .ty = enum_type.tag_ty,
4678 } });5604 .storage = .{ .u64 = index },
4679 },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),
4680 else => {},5619 else => {},
4681 },5620 },
4682 .ptr => |ptr| if (ip.isPointerType(new_ty))5621 .opt => |opt| switch (ip.indexToKey(new_ty)) {
4683 return ip.get(gpa, .{ .ptr = .{5622 .ptr_type => |ptr_type| return switch (opt.val) {
5623 .none => try ip.get(gpa, .{ .ptr = .{
4684 .ty = new_ty,5624 .ty = new_ty,
4685 .addr = ptr.addr,5625 .addr = .{ .int = .zero_usize },
4686 .len = ptr.len,5626 .len = switch (ptr_type.flags.size) {
4687 } })5627 .One, .Many, .C => .none,
4688 else if (ip.isIntegerType(new_ty))5628 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
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),
4710 },5629 },
4711 } }),5630 } }),
4712 else => {},5631 else => |payload| try ip.getCoerced(gpa, payload, new_ty),
4713 },5632 },
4714 .err => |err| if (ip.isErrorSetType(new_ty))5633 .opt_type => |child_type| return try ip.get(gpa, .{ .opt = .{
4715 return ip.get(gpa, .{ .err = .{5634 .ty = new_ty,
4716 .ty = new_ty,5635 .val = switch (opt.val) {
4717 .name = err.name,5636 .none => .none,
4718 } })5637 else => try ip.getCoerced(gpa, opt.val, child_type),
4719 else if (ip.isErrorUnionType(new_ty))5638 },
4720 return ip.get(gpa, .{ .error_union = .{5639 } }),
4721 .ty = new_ty,5640 else => {},
4722 .val = .{ .err_name = err.name },5641 },
4723 } }),5642 .err => |err| if (ip.isErrorSetType(new_ty))
4724 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))5643 return ip.get(gpa, .{ .err = .{
4725 return ip.get(gpa, .{ .error_union = .{5644 .ty = new_ty,
4726 .ty = new_ty,5645 .name = err.name,
4727 .val = error_union.val,5646 } })
4728 } }),5647 else if (ip.isErrorUnionType(new_ty))
4729 .aggregate => |aggregate| {5648 return ip.get(gpa, .{ .error_union = .{
4730 const new_len = @as(usize, @intCast(ip.aggregateTypeLen(new_ty)));5649 .ty = new_ty,
4731 direct: {5650 .val = .{ .err_name = err.name },
4732 const old_ty_child = switch (ip.indexToKey(old_ty)) {5651 } }),
4733 inline .array_type, .vector_type => |seq_type| seq_type.child,5652 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
4734 .anon_struct_type, .struct_type => break :direct,5653 return ip.get(gpa, .{ .error_union = .{
4735 else => unreachable,5654 .ty = new_ty,
4736 };5655 .val = error_union.val,
4737 const new_ty_child = switch (ip.indexToKey(new_ty)) {5656 } }),
4738 inline .array_type, .vector_type => |seq_type| seq_type.child,5657 .aggregate => |aggregate| {
4739 .anon_struct_type, .struct_type => break :direct,5658 const new_len = @as(usize, @intCast(ip.aggregateTypeLen(new_ty)));
4740 else => unreachable,5659 direct: {
4741 };5660 const old_ty_child = switch (ip.indexToKey(old_ty)) {
4742 if (old_ty_child != new_ty_child) break :direct;5661 inline .array_type, .vector_type => |seq_type| seq_type.child,
4743 // TODO: write something like getCoercedInts to avoid needing to dupe here5662 .anon_struct_type, .struct_type => break :direct,
4744 switch (aggregate.storage) {5663 else => unreachable,
4745 .bytes => |bytes| {5664 };
4746 const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]);5665 const new_ty_child = switch (ip.indexToKey(new_ty)) {
4747 defer gpa.free(bytes_copy);5666 inline .array_type, .vector_type => |seq_type| seq_type.child,
4748 return ip.get(gpa, .{ .aggregate = .{5667 .anon_struct_type, .struct_type => break :direct,
4749 .ty = new_ty,5668 else => unreachable,
4750 .storage = .{ .bytes = bytes_copy },5669 };
4751 } });5670 if (old_ty_child != new_ty_child) break :direct;
4752 },5671 // TODO: write something like getCoercedInts to avoid needing to dupe here
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.
4775 switch (aggregate.storage) {5672 switch (aggregate.storage) {
4776 .bytes => {5673 .bytes => |bytes| {
4777 // We have to intern each value here, so unfortunately we can't easily avoid5674 const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]);
4778 // the repeated indexToKey calls.5675 defer gpa.free(bytes_copy);
4779 for (agg_elems, 0..) |*elem, i| {5676 return ip.get(gpa, .{ .aggregate = .{
4780 const x = ip.indexToKey(val).aggregate.storage.bytes[i];5677 .ty = new_ty,
4781 elem.* = try ip.get(gpa, .{ .int = .{5678 .storage = .{ .bytes = bytes_copy },
4782 .ty = .u8_type,5679 } });
4783 .storage = .{ .u64 = x },5680 },
4784 } });5681 .elems => |elems| {
4785 }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 } });
4786 },5694 },
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);
4800 }5695 }
4801 return ip.get(gpa, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } });5696 }
4802 },5697 // Direct approach failed - we must recursively coerce elems
4803 else => {},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 } } });
4804 },5730 },
5731 else => {},
4805 }5732 }
5733
4806 switch (ip.indexToKey(new_ty)) {5734 switch (ip.indexToKey(new_ty)) {
4807 .opt_type => |child_type| switch (val) {5735 .opt_type => |child_type| switch (val) {
4808 .null_value => return ip.get(gpa, .{ .opt = .{5736 .null_value => return ip.get(gpa, .{ .opt = .{
...@@ -4830,6 +5758,54 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -4830,6 +5758,54 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
4830 unreachable;5758 unreachable;
4831}5759}
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
4833/// Asserts `val` has an integer type.5809/// Asserts `val` has an integer type.
4834/// Assumes `new_ty` is an integer type.5810/// Assumes `new_ty` is an integer type.
4835pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Index) Allocator.Error!Index {5811pub 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 {...@@ -4881,27 +5857,11 @@ pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType {
4881 const tags = ip.items.items(.tag);5857 const tags = ip.items.items(.tag);
4882 const datas = ip.items.items(.data);5858 const datas = ip.items.items(.data);
4883 switch (tags[@intFromEnum(val)]) {5859 switch (tags[@intFromEnum(val)]) {
4884 .type_function => return indexToKeyFuncType(ip, datas[@intFromEnum(val)]),5860 .type_function => return extraFuncType(ip, datas[@intFromEnum(val)]),
4885 else => return null,5861 else => return null,
4886 }5862 }
4887}5863}
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
4905/// includes .comptime_int_type5865/// includes .comptime_int_type
4906pub fn isIntegerType(ip: *const InternPool, ty: Index) bool {5866pub fn isIntegerType(ip: *const InternPool, ty: Index) bool {
4907 return switch (ty) {5867 return switch (ty) {
...@@ -4952,14 +5912,17 @@ pub fn isOptionalType(ip: *const InternPool, ty: Index) bool {...@@ -4952,14 +5912,17 @@ pub fn isOptionalType(ip: *const InternPool, ty: Index) bool {
49525912
4953/// includes .inferred_error_set_type5913/// includes .inferred_error_set_type
4954pub fn isErrorSetType(ip: *const InternPool, ty: Index) bool {5914pub fn isErrorSetType(ip: *const InternPool, ty: Index) bool {
4955 return ty == .anyerror_type or switch (ip.indexToKey(ty)) {5915 return switch (ty) {
4956 .error_set_type, .inferred_error_set_type => true,5916 .anyerror_type, .adhoc_inferred_error_set_type => true,
4957 else => false,5917 else => switch (ip.indexToKey(ty)) {
5918 .error_set_type, .inferred_error_set_type => true,
5919 else => false,
5920 },
4958 };5921 };
4959}5922}
49605923
4961pub fn isInferredErrorSetType(ip: *const InternPool, ty: Index) bool {5924pub 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;
4963}5926}
49645927
4965pub fn isErrorUnionType(ip: *const InternPool, ty: Index) bool {5928pub fn isErrorUnionType(ip: *const InternPool, ty: Index) bool {
...@@ -4973,6 +5936,14 @@ pub fn isAggregateType(ip: *const InternPool, ty: Index) bool {...@@ -4973,6 +5936,14 @@ pub fn isAggregateType(ip: *const InternPool, ty: Index) bool {
4973 };5936 };
4974}5937}
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
4976/// The is only legal because the initializer is not part of the hash.5947/// The is only legal because the initializer is not part of the hash.
4977pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void {5948pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void {
4978 const item = ip.items.get(@intFromEnum(index));5949 const item = ip.items.get(@intFromEnum(index));
...@@ -4994,12 +5965,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -4994,12 +5965,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
4994 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));5965 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
4995 const unions_size = ip.allocated_unions.len *5966 const unions_size = ip.allocated_unions.len *
4996 (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));5967 (@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
5000 // TODO: map overhead size is not taken into account5969 // TODO: map overhead size is not taken into account
5001 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +5970 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +
5002 structs_size + unions_size + funcs_size;5971 structs_size + unions_size;
50035972
5004 std.debug.print(5973 std.debug.print(
5005 \\InternPool size: {d} bytes5974 \\InternPool size: {d} bytes
...@@ -5008,7 +5977,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5008,7 +5977,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5008 \\ {d} limbs: {d} bytes5977 \\ {d} limbs: {d} bytes
5009 \\ {d} structs: {d} bytes5978 \\ {d} structs: {d} bytes
5010 \\ {d} unions: {d} bytes5979 \\ {d} unions: {d} bytes
5011 \\ {d} funcs: {d} bytes
5012 \\5980 \\
5013 , .{5981 , .{
5014 total_size,5982 total_size,
...@@ -5022,8 +5990,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5022,8 +5990,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5022 structs_size,5990 structs_size,
5023 ip.allocated_unions.len,5991 ip.allocated_unions.len,
5024 unions_size,5992 unions_size,
5025 ip.allocated_funcs.len,
5026 funcs_size,
5027 });5993 });
50285994
5029 const tags = ip.items.items(.tag);5995 const tags = ip.items.items(.tag);
...@@ -5048,11 +6014,12 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5048,11 +6014,12 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5048 .type_optional => 0,6014 .type_optional => 0,
5049 .type_anyframe => 0,6015 .type_anyframe => 0,
5050 .type_error_union => @sizeOf(Key.ErrorUnionType),6016 .type_error_union => @sizeOf(Key.ErrorUnionType),
6017 .type_anyerror_union => 0,
5051 .type_error_set => b: {6018 .type_error_set => b: {
5052 const info = ip.extraData(ErrorSet, data);6019 const info = ip.extraData(Tag.ErrorSet, data);
5053 break :b @sizeOf(ErrorSet) + (@sizeOf(u32) * info.names_len);6020 break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len);
5054 },6021 },
5055 .type_inferred_error_set => @sizeOf(Module.Fn.InferredErrorSet),6022 .type_inferred_error_set => 0,
5056 .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),6023 .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),
5057 .type_enum_auto => @sizeOf(EnumAuto),6024 .type_enum_auto => @sizeOf(EnumAuto),
5058 .type_opaque => @sizeOf(Key.OpaqueType),6025 .type_opaque => @sizeOf(Key.OpaqueType),
...@@ -5080,8 +6047,11 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5080,8 +6047,11 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5080 => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),6047 => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),
50816048
5082 .type_function => b: {6049 .type_function => b: {
5083 const info = ip.extraData(TypeFunction, data);6050 const info = ip.extraData(Tag.TypeFunction, data);
5084 break :b @sizeOf(TypeFunction) + (@sizeOf(Index) * info.params_len);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));
5085 },6055 },
50866056
5087 .undef => 0,6057 .undef => 0,
...@@ -5130,7 +6100,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5130,7 +6100,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5130 },6100 },
5131 .aggregate => b: {6101 .aggregate => b: {
5132 const info = ip.extraData(Tag.Aggregate, data);6102 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));
5134 break :b @sizeOf(Tag.Aggregate) + (@sizeOf(Index) * fields_len);6104 break :b @sizeOf(Tag.Aggregate) + (@sizeOf(Index) * fields_len);
5135 },6105 },
5136 .repeated => @sizeOf(Repeated),6106 .repeated => @sizeOf(Repeated),
...@@ -5145,7 +6115,15 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5145,7 +6115,15 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5145 .float_comptime_float => @sizeOf(Float128),6115 .float_comptime_float => @sizeOf(Float128),
5146 .variable => @sizeOf(Tag.Variable) + @sizeOf(Module.Decl),6116 .variable => @sizeOf(Tag.Variable) + @sizeOf(Module.Decl),
5147 .extern_func => @sizeOf(Tag.ExternFunc) + @sizeOf(Module.Decl),6117 .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),
5149 .only_possible_value => 0,6127 .only_possible_value => 0,
5150 .union_value => @sizeOf(Key.Union),6128 .union_value => @sizeOf(Key.Union),
51516129
...@@ -5193,6 +6171,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -5193,6 +6171,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
5193 .type_optional,6171 .type_optional,
5194 .type_anyframe,6172 .type_anyframe,
5195 .type_error_union,6173 .type_error_union,
6174 .type_anyerror_union,
5196 .type_error_set,6175 .type_error_set,
5197 .type_inferred_error_set,6176 .type_inferred_error_set,
5198 .type_enum_explicit,6177 .type_enum_explicit,
...@@ -5249,7 +6228,9 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -5249,7 +6228,9 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
5249 .float_comptime_float,6228 .float_comptime_float,
5250 .variable,6229 .variable,
5251 .extern_func,6230 .extern_func,
5252 .func,6231 .func_decl,
6232 .func_instance,
6233 .func_coerced,
5253 .union_value,6234 .union_value,
5254 .memoized_call,6235 .memoized_call,
5255 => try w.print("{d}", .{data}),6236 => try w.print("{d}", .{data}),
...@@ -5284,20 +6265,12 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo...@@ -5284,20 +6265,12 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo
5284 return ip.allocated_unions.at(@intFromEnum(index));6265 return ip.allocated_unions.at(@intFromEnum(index));
5285}6266}
52866267
5287pub fn funcPtr(ip: *InternPool, index: Module.Fn.Index) *Module.Fn {6268pub fn declPtr(ip: *InternPool, index: Module.Decl.Index) *Module.Decl {
5288 return ip.allocated_funcs.at(@intFromEnum(index));6269 return ip.allocated_decls.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));
5293}6270}
52946271
5295pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet {6272pub fn namespacePtr(ip: *InternPool, index: Module.Namespace.Index) *Module.Namespace {
5296 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));6273 return ip.allocated_namespaces.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));
5301}6274}
53026275
5303pub fn createStruct(6276pub fn createStruct(
...@@ -5344,47 +6317,47 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)...@@ -5344,47 +6317,47 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)
5344 };6317 };
5345}6318}
53466319
5347pub fn createFunc(6320pub fn createDecl(
5348 ip: *InternPool,6321 ip: *InternPool,
5349 gpa: Allocator,6322 gpa: Allocator,
5350 initialization: Module.Fn,6323 initialization: Module.Decl,
5351) Allocator.Error!Module.Fn.Index {6324) Allocator.Error!Module.Decl.Index {
5352 if (ip.funcs_free_list.popOrNull()) |index| {6325 if (ip.decls_free_list.popOrNull()) |index| {
5353 ip.allocated_funcs.at(@intFromEnum(index)).* = initialization;6326 ip.allocated_decls.at(@intFromEnum(index)).* = initialization;
5354 return index;6327 return index;
5355 }6328 }
5356 const ptr = try ip.allocated_funcs.addOne(gpa);6329 const ptr = try ip.allocated_decls.addOne(gpa);
5357 ptr.* = initialization;6330 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));
5359}6332}
53606333
5361pub fn destroyFunc(ip: *InternPool, gpa: Allocator, index: Module.Fn.Index) void {6334pub fn destroyDecl(ip: *InternPool, gpa: Allocator, index: Module.Decl.Index) void {
5362 ip.funcPtr(index).* = undefined;6335 ip.declPtr(index).* = undefined;
5363 ip.funcs_free_list.append(gpa, index) catch {6336 ip.decls_free_list.append(gpa, index) catch {
5364 // In order to keep `destroyFunc` a non-fallible function, we ignore memory6337 // In order to keep `destroyDecl` a non-fallible function, we ignore memory
5365 // allocation failures here, instead leaking the Fn until garbage collection.6338 // allocation failures here, instead leaking the Decl until garbage collection.
5366 };6339 };
5367}6340}
53686341
5369pub fn createInferredErrorSet(6342pub fn createNamespace(
5370 ip: *InternPool,6343 ip: *InternPool,
5371 gpa: Allocator,6344 gpa: Allocator,
5372 initialization: Module.Fn.InferredErrorSet,6345 initialization: Module.Namespace,
5373) Allocator.Error!Module.Fn.InferredErrorSet.Index {6346) Allocator.Error!Module.Namespace.Index {
5374 if (ip.inferred_error_sets_free_list.popOrNull()) |index| {6347 if (ip.namespaces_free_list.popOrNull()) |index| {
5375 ip.allocated_inferred_error_sets.at(@intFromEnum(index)).* = initialization;6348 ip.allocated_namespaces.at(@intFromEnum(index)).* = initialization;
5376 return index;6349 return index;
5377 }6350 }
5378 const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);6351 const ptr = try ip.allocated_namespaces.addOne(gpa);
5379 ptr.* = initialization;6352 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));
5381}6354}
53826355
5383pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.Fn.InferredErrorSet.Index) void {6356pub fn destroyNamespace(ip: *InternPool, gpa: Allocator, index: Module.Namespace.Index) void {
5384 ip.inferredErrorSetPtr(index).* = undefined;6357 ip.namespacePtr(index).* = undefined;
5385 ip.inferred_error_sets_free_list.append(gpa, index) catch {6358 ip.namespaces_free_list.append(gpa, index) catch {
5386 // In order to keep `destroyInferredErrorSet` a non-fallible function, we ignore memory6359 // In order to keep `destroyNamespace` a non-fallible function, we ignore memory
5387 // allocation failures here, instead leaking the InferredErrorSet until garbage collection.6360 // allocation failures here, instead leaking the Namespace until garbage collection.
5388 };6361 };
5389}6362}
53906363
...@@ -5547,6 +6520,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -5547,6 +6520,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
5547 .slice_const_u8_sentinel_0_type,6520 .slice_const_u8_sentinel_0_type,
5548 .optional_noreturn_type,6521 .optional_noreturn_type,
5549 .anyerror_void_error_union_type,6522 .anyerror_void_error_union_type,
6523 .adhoc_inferred_error_set_type,
5550 .generic_poison_type,6524 .generic_poison_type,
5551 .empty_struct_type,6525 .empty_struct_type,
5552 => .type_type,6526 => .type_type,
...@@ -5576,6 +6550,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -5576,6 +6550,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
5576 .type_optional,6550 .type_optional,
5577 .type_anyframe,6551 .type_anyframe,
5578 .type_error_union,6552 .type_error_union,
6553 .type_anyerror_union,
5579 .type_error_set,6554 .type_error_set,
5580 .type_inferred_error_set,6555 .type_inferred_error_set,
5581 .type_enum_auto,6556 .type_enum_auto,
...@@ -5596,7 +6571,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -5596,7 +6571,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
5596 .undef,6571 .undef,
5597 .opt_null,6572 .opt_null,
5598 .only_possible_value,6573 .only_possible_value,
5599 => @as(Index, @enumFromInt(ip.items.items(.data)[@intFromEnum(index)])),6574 => @enumFromInt(ip.items.items(.data)[@intFromEnum(index)]),
56006575
5601 .simple_value => unreachable, // handled via Index above6576 .simple_value => unreachable, // handled via Index above
56026577
...@@ -5620,7 +6595,9 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -5620,7 +6595,9 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
5620 .enum_tag,6595 .enum_tag,
5621 .variable,6596 .variable,
5622 .extern_func,6597 .extern_func,
5623 .func,6598 .func_decl,
6599 .func_instance,
6600 .func_coerced,
5624 .union_value,6601 .union_value,
5625 .bytes,6602 .bytes,
5626 .aggregate,6603 .aggregate,
...@@ -5628,7 +6605,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -5628,7 +6605,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
5628 => |t| {6605 => |t| {
5629 const extra_index = ip.items.items(.data)[@intFromEnum(index)];6606 const extra_index = ip.items.items(.data)[@intFromEnum(index)];
5630 const field_index = std.meta.fieldIndex(t.Payload(), "ty").?;6607 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]);
5632 },6609 },
56336610
5634 .int_u8 => .u8_type,6611 .int_u8 => .u8_type,
...@@ -5693,7 +6670,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {...@@ -5693,7 +6670,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {
5693 };6670 };
5694}6671}
56956672
5696pub fn funcReturnType(ip: *const InternPool, ty: Index) Index {6673pub fn funcTypeReturnType(ip: *const InternPool, ty: Index) Index {
5697 const item = ip.items.get(@intFromEnum(ty));6674 const item = ip.items.get(@intFromEnum(ty));
5698 const child_item = switch (item.tag) {6675 const child_item = switch (item.tag) {
5699 .type_pointer => ip.items.get(ip.extra.items[6676 .type_pointer => ip.items.get(ip.extra.items[
...@@ -5704,7 +6681,7 @@ pub fn funcReturnType(ip: *const InternPool, ty: Index) Index {...@@ -5704,7 +6681,7 @@ pub fn funcReturnType(ip: *const InternPool, ty: Index) Index {
5704 };6681 };
5705 assert(child_item.tag == .type_function);6682 assert(child_item.tag == .type_function);
5706 return @as(Index, @enumFromInt(ip.extra.items[6683 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").?
5708 ]));6685 ]));
5709}6686}
57106687
...@@ -5712,7 +6689,7 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {...@@ -5712,7 +6689,7 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
5712 return switch (ty) {6689 return switch (ty) {
5713 .noreturn_type => true,6690 .noreturn_type => true,
5714 else => switch (ip.items.items(.tag)[@intFromEnum(ty)]) {6691 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,
5716 else => false,6693 else => false,
5717 },6694 },
5718 };6695 };
...@@ -5821,7 +6798,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -5821,7 +6798,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
5821 .bool_type => .Bool,6798 .bool_type => .Bool,
5822 .void_type => .Void,6799 .void_type => .Void,
5823 .type_type => .Type,6800 .type_type => .Type,
5824 .anyerror_type => .ErrorSet,6801 .anyerror_type, .adhoc_inferred_error_set_type => .ErrorSet,
5825 .comptime_int_type => .ComptimeInt,6802 .comptime_int_type => .ComptimeInt,
5826 .comptime_float_type => .ComptimeFloat,6803 .comptime_float_type => .ComptimeFloat,
5827 .noreturn_type => .NoReturn,6804 .noreturn_type => .NoReturn,
...@@ -5899,7 +6876,10 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -5899,7 +6876,10 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
58996876
5900 .type_optional => .Optional,6877 .type_optional => .Optional,
5901 .type_anyframe => .AnyFrame,6878 .type_anyframe => .AnyFrame,
5902 .type_error_union => .ErrorUnion,6879
6880 .type_error_union,
6881 .type_anyerror_union,
6882 => .ErrorUnion,
59036883
5904 .type_error_set,6884 .type_error_set,
5905 .type_inferred_error_set,6885 .type_inferred_error_set,
...@@ -5969,7 +6949,9 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -5969,7 +6949,9 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
5969 .float_comptime_float,6949 .float_comptime_float,
5970 .variable,6950 .variable,
5971 .extern_func,6951 .extern_func,
5972 .func,6952 .func_decl,
6953 .func_instance,
6954 .func_coerced,
5973 .only_possible_value,6955 .only_possible_value,
5974 .union_value,6956 .union_value,
5975 .bytes,6957 .bytes,
...@@ -5982,3 +6964,126 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -5982,3 +6964,126 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
5982 .none => unreachable, // special tag6964 .none => unreachable, // special tag
5983 };6965 };
5984}6966}
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) = .{},...@@ -87,7 +87,9 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{},
87/// Keys are fully resolved file paths. This table owns the keys and values.87/// Keys are fully resolved file paths. This table owns the keys and values.
88embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},88embed_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.
91intern_pool: InternPool = .{},93intern_pool: InternPool = .{},
9294
93/// To be eliminated in a future commit by moving more data into InternPool.95/// To be eliminated in a future commit by moving more data into InternPool.
...@@ -101,16 +103,6 @@ tmp_hack_arena: std.heap.ArenaAllocator,...@@ -101,16 +103,6 @@ tmp_hack_arena: std.heap.ArenaAllocator,
101/// This is currently only used for string literals.103/// This is currently only used for string literals.
102memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},104memoized_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
114/// We optimize memory usage for a compilation with no compile errors by storing the106/// We optimize memory usage for a compilation with no compile errors by storing the
115/// error messages and mapping outside of `Decl`.107/// error messages and mapping outside of `Decl`.
116/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.108/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
...@@ -162,25 +154,6 @@ emit_h: ?*GlobalEmitH,...@@ -162,25 +154,6 @@ emit_h: ?*GlobalEmitH,
162154
163test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},155test_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
184global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},157global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},
185158
186reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {159reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
...@@ -189,7 +162,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {...@@ -189,7 +162,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
189}) = .{},162}) = .{},
190163
191panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len,164panic_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,
193null_stack_trace: InternPool.Index = .none,167null_stack_trace: InternPool.Index = .none,
194168
195pub const PanicId = enum {169pub const PanicId = enum {
...@@ -239,50 +213,6 @@ pub const CImportError = struct {...@@ -239,50 +213,6 @@ pub const CImportError = struct {
239 }213 }
240};214};
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
286/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.216/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
287pub const GlobalEmitH = struct {217pub const GlobalEmitH = struct {
288 /// Where to put the output.218 /// Where to put the output.
...@@ -366,6 +296,9 @@ pub const CaptureScope = struct {...@@ -366,6 +296,9 @@ pub const CaptureScope = struct {
366 }296 }
367297
368 pub fn incRef(self: *CaptureScope) void {298 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.
369 self.refs += 1;302 self.refs += 1;
370 }303 }
371304
...@@ -625,13 +558,6 @@ pub const Decl = struct {...@@ -625,13 +558,6 @@ pub const Decl = struct {
625 function_body,558 function_body,
626 };559 };
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
635 /// This name is relative to the containing namespace of the decl.561 /// This name is relative to the containing namespace of the decl.
636 /// The memory is owned by the containing File ZIR.562 /// The memory is owned by the containing File ZIR.
637 pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {563 pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {
...@@ -816,14 +742,18 @@ pub const Decl = struct {...@@ -816,14 +742,18 @@ pub const Decl = struct {
816 return mod.typeToUnion(decl.val.toType());742 return mod.typeToUnion(decl.val.toType());
817 }743 }
818744
819 /// If the Decl owns its value and it is a function, return it,745 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?InternPool.Key.Func {
820 /// otherwise null.746 const i = decl.getOwnedFunctionIndex();
821 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?*Fn {747 if (i == .none) return null;
822 return mod.funcPtrUnwrap(decl.getOwnedFunctionIndex(mod));748 return switch (mod.intern_pool.indexToKey(i)) {
749 .func => |func| func,
750 else => null,
751 };
823 }752 }
824753
825 pub fn getOwnedFunctionIndex(decl: Decl, mod: *Module) Fn.OptionalIndex {754 /// This returns an InternPool.Index even when the value is not a function.
826 return if (decl.owns_tv) decl.val.getFunctionIndex(mod) else .none;755 pub fn getOwnedFunctionIndex(decl: Decl) InternPool.Index {
756 return if (decl.owns_tv) decl.val.toIntern() else .none;
827 }757 }
828758
829 /// If the Decl owns its value and it is an extern function, returns it,759 /// If the Decl owns its value and it is an extern function, returns it,
...@@ -1368,252 +1298,6 @@ pub const Union = struct {...@@ -1368,252 +1298,6 @@ pub const Union = struct {
1368 }1298 }
1369};1299};
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
1617pub const DeclAdapter = struct {1301pub const DeclAdapter = struct {
1618 mod: *Module,1302 mod: *Module,
16191303
...@@ -1638,12 +1322,10 @@ pub const Namespace = struct {...@@ -1638,12 +1322,10 @@ pub const Namespace = struct {
1638 /// Direct children of the namespace. Used during an update to detect1322 /// Direct children of the namespace. Used during an update to detect
1639 /// which decls have been added/removed from source.1323 /// which decls have been added/removed from source.
1640 /// Declaration order is preserved via entry order.1324 /// Declaration order is preserved via entry order.
1641 /// Key memory is owned by `decl.name`.1325 /// These are only declarations named directly by the AST; anonymous
1642 /// Anonymous decls are not stored here; they are kept in `anon_decls` instead.1326 /// declarations are not stored here.
1643 decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{},1327 decls: std.ArrayHashMapUnmanaged(Decl.Index, void, DeclContext, true) = .{},
16441328
1645 anon_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
1646
1647 /// Key is usingnamespace Decl itself. To find the namespace being included,1329 /// Key is usingnamespace Decl itself. To find the namespace being included,
1648 /// the Decl Value has to be resolved as a Type which has a Namespace.1330 /// the Decl Value has to be resolved as a Type which has a Namespace.
1649 /// Value is whether the usingnamespace decl is marked `pub`.1331 /// Value is whether the usingnamespace decl is marked `pub`.
...@@ -1698,18 +1380,11 @@ pub const Namespace = struct {...@@ -1698,18 +1380,11 @@ pub const Namespace = struct {
1698 var decls = ns.decls;1380 var decls = ns.decls;
1699 ns.decls = .{};1381 ns.decls = .{};
17001382
1701 var anon_decls = ns.anon_decls;
1702 ns.anon_decls = .{};
1703
1704 for (decls.keys()) |decl_index| {1383 for (decls.keys()) |decl_index| {
1705 mod.destroyDecl(decl_index);1384 mod.destroyDecl(decl_index);
1706 }1385 }
1707 decls.deinit(gpa);1386 decls.deinit(gpa);
17081387
1709 for (anon_decls.keys()) |key| {
1710 mod.destroyDecl(key);
1711 }
1712 anon_decls.deinit(gpa);
1713 ns.usingnamespace_set.deinit(gpa);1388 ns.usingnamespace_set.deinit(gpa);
1714 }1389 }
17151390
...@@ -1723,9 +1398,6 @@ pub const Namespace = struct {...@@ -1723,9 +1398,6 @@ pub const Namespace = struct {
1723 var decls = ns.decls;1398 var decls = ns.decls;
1724 ns.decls = .{};1399 ns.decls = .{};
17251400
1726 var anon_decls = ns.anon_decls;
1727 ns.anon_decls = .{};
1728
1729 // TODO rework this code to not panic on OOM.1401 // TODO rework this code to not panic on OOM.
1730 // (might want to coordinate with the clearDecl function)1402 // (might want to coordinate with the clearDecl function)
17311403
...@@ -1735,12 +1407,6 @@ pub const Namespace = struct {...@@ -1735,12 +1407,6 @@ pub const Namespace = struct {
1735 }1407 }
1736 decls.deinit(gpa);1408 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
1744 ns.usingnamespace_set.deinit(gpa);1410 ns.usingnamespace_set.deinit(gpa);
1745 }1411 }
17461412
...@@ -2155,8 +1821,8 @@ pub const SrcLoc = struct {...@@ -2155,8 +1821,8 @@ pub const SrcLoc = struct {
2155 return tree.firstToken(src_loc.parent_decl_node);1821 return tree.firstToken(src_loc.parent_decl_node);
2156 }1822 }
21571823
2158 pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.TokenIndex {1824 pub fn declRelativeToNodeIndex(src_loc: SrcLoc, offset: i32) Ast.Node.Index {
2159 return @as(Ast.Node.Index, @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node))));1825 return @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node)));
2160 }1826 }
21611827
2162 pub const Span = struct {1828 pub const Span = struct {
...@@ -2468,6 +2134,37 @@ pub const SrcLoc = struct {...@@ -2468,6 +2134,37 @@ pub const SrcLoc = struct {
2468 }2134 }
2469 } else unreachable;2135 } else unreachable;
2470 },2136 },
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 },
2471 .node_offset_bin_lhs => |node_off| {2168 .node_offset_bin_lhs => |node_off| {
2472 const tree = try src_loc.file_scope.getTree(gpa);2169 const tree = try src_loc.file_scope.getTree(gpa);
2473 const node = src_loc.declRelativeToNodeIndex(node_off);2170 const node = src_loc.declRelativeToNodeIndex(node_off);
...@@ -2820,6 +2517,10 @@ pub const SrcLoc = struct {...@@ -2820,6 +2517,10 @@ pub const SrcLoc = struct {
2820 );2517 );
2821 }2518 }
28222519
2520 fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span {
2521 return tokensToSpan(tree, token, token, token);
2522 }
2523
2823 fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {2524 fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span {
2824 const token_starts = tree.tokens.items(.start);2525 const token_starts = tree.tokens.items(.start);
2825 var start_tok = start;2526 var start_tok = start;
...@@ -3146,6 +2847,21 @@ pub const LazySrcLoc = union(enum) {...@@ -3146,6 +2847,21 @@ pub const LazySrcLoc = union(enum) {
3146 /// Next, navigate to the corresponding capture.2847 /// Next, navigate to the corresponding capture.
3147 /// The Decl is determined contextually.2848 /// The Decl is determined contextually.
3148 for_capture_from_input: i32,2849 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
3150 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;2866 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
31512867
...@@ -3240,6 +2956,13 @@ pub const LazySrcLoc = union(enum) {...@@ -3240,6 +2956,13 @@ pub const LazySrcLoc = union(enum) {
3240 .parent_decl_node = decl.src_node,2956 .parent_decl_node = decl.src_node,
3241 .lazy = lazy,2957 .lazy = lazy,
3242 },2958 },
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 },
3243 };2966 };
3244 }2967 }
3245};2968};
...@@ -3373,17 +3096,10 @@ pub fn deinit(mod: *Module) void {...@@ -3373,17 +3096,10 @@ pub fn deinit(mod: *Module) void {
3373 mod.global_error_set.deinit(gpa);3096 mod.global_error_set.deinit(gpa);
33743097
3375 mod.test_functions.deinit(gpa);3098 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);
3381 mod.global_assembly.deinit(gpa);3100 mod.global_assembly.deinit(gpa);
3382 mod.reference_table.deinit(gpa);3101 mod.reference_table.deinit(gpa);
33833102
3384 mod.namespaces_free_list.deinit(gpa);
3385 mod.allocated_namespaces.deinit(gpa);
3386
3387 mod.memoized_decls.deinit(gpa);3103 mod.memoized_decls.deinit(gpa);
3388 mod.intern_pool.deinit(gpa);3104 mod.intern_pool.deinit(gpa);
3389 mod.tmp_hack_arena.deinit();3105 mod.tmp_hack_arena.deinit();
...@@ -3391,6 +3107,8 @@ pub fn deinit(mod: *Module) void {...@@ -3391,6 +3107,8 @@ pub fn deinit(mod: *Module) void {
33913107
3392pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {3108pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3393 const gpa = mod.gpa;3109 const gpa = mod.gpa;
3110 const ip = &mod.intern_pool;
3111
3394 {3112 {
3395 const decl = mod.declPtr(decl_index);3113 const decl = mod.declPtr(decl_index);
3396 _ = mod.test_functions.swapRemove(decl_index);3114 _ = mod.test_functions.swapRemove(decl_index);
...@@ -3407,15 +3125,12 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -3407,15 +3125,12 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3407 }3125 }
3408 }3126 }
3409 if (decl.src_scope) |scope| scope.decRef(gpa);3127 if (decl.src_scope) |scope| scope.decRef(gpa);
3410 decl.clearValues(mod);
3411 decl.dependants.deinit(gpa);3128 decl.dependants.deinit(gpa);
3412 decl.dependencies.deinit(gpa);3129 decl.dependencies.deinit(gpa);
3413 decl.* = undefined;
3414 }3130 }
3415 mod.decls_free_list.append(gpa, decl_index) catch {3131
3416 // In order to keep `destroyDecl` a non-fallible function, we ignore memory3132 ip.destroyDecl(gpa, decl_index);
3417 // allocation failures here, instead leaking the Decl until garbage collection.3133
3418 };
3419 if (mod.emit_h) |mod_emit_h| {3134 if (mod.emit_h) |mod_emit_h| {
3420 const decl_emit_h = mod_emit_h.declPtr(decl_index);3135 const decl_emit_h = mod_emit_h.declPtr(decl_index);
3421 decl_emit_h.fwd_decl.deinit(gpa);3136 decl_emit_h.fwd_decl.deinit(gpa);
...@@ -3424,11 +3139,11 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -3424,11 +3139,11 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3424}3139}
34253140
3426pub fn declPtr(mod: *Module, index: Decl.Index) *Decl {3141pub fn declPtr(mod: *Module, index: Decl.Index) *Decl {
3427 return mod.allocated_decls.at(@intFromEnum(index));3142 return mod.intern_pool.declPtr(index);
3428}3143}
34293144
3430pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace {3145pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace {
3431 return mod.allocated_namespaces.at(@intFromEnum(index));3146 return mod.intern_pool.namespacePtr(index);
3432}3147}
34333148
3434pub fn unionPtr(mod: *Module, index: Union.Index) *Union {3149pub fn unionPtr(mod: *Module, index: Union.Index) *Union {
...@@ -3439,14 +3154,6 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {...@@ -3439,14 +3154,6 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
3439 return mod.intern_pool.structPtr(index);3154 return mod.intern_pool.structPtr(index);
3440}3155}
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
3450pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namespace {3157pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namespace {
3451 return mod.namespacePtr(index.unwrap() orelse return null);3158 return mod.namespacePtr(index.unwrap() orelse return null);
3452}3159}
...@@ -3457,10 +3164,6 @@ pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {...@@ -3457,10 +3164,6 @@ pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {
3457 return mod.structPtr(index.unwrap() orelse return null);3164 return mod.structPtr(index.unwrap() orelse return null);
3458}3165}
34593166
3460pub fn funcPtrUnwrap(mod: *Module, index: Fn.OptionalIndex) ?*Fn {
3461 return mod.funcPtr(index.unwrap() orelse return null);
3462}
3463
3464/// Returns true if and only if the Decl is the top level struct associated with a File.3167/// Returns true if and only if the Decl is the top level struct associated with a File.
3465pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {3168pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
3466 const decl = mod.declPtr(decl_index);3169 const decl = mod.declPtr(decl_index);
...@@ -3881,6 +3584,8 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {...@@ -3881,6 +3584,8 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3881 // to re-generate ZIR for the File.3584 // to re-generate ZIR for the File.
3882 try file.outdated_decls.append(gpa, root_decl);3585 try file.outdated_decls.append(gpa, root_decl);
38833586
3587 const ip = &mod.intern_pool;
3588
3884 while (decl_stack.popOrNull()) |decl_index| {3589 while (decl_stack.popOrNull()) |decl_index| {
3885 const decl = mod.declPtr(decl_index);3590 const decl = mod.declPtr(decl_index);
3886 // Anonymous decls and the root decl have this set to 0. We still need3591 // 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 {...@@ -3918,7 +3623,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3918 }3623 }
39193624
3920 if (decl.getOwnedFunction(mod)) |func| {3625 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 {
3922 try file.deleted_decls.append(gpa, decl_index);3627 try file.deleted_decls.append(gpa, decl_index);
3923 continue;3628 continue;
3924 };3629 };
...@@ -3928,9 +3633,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {...@@ -3928,9 +3633,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3928 for (namespace.decls.keys()) |sub_decl| {3633 for (namespace.decls.keys()) |sub_decl| {
3929 try decl_stack.append(gpa, sub_decl);3634 try decl_stack.append(gpa, sub_decl);
3930 }3635 }
3931 for (namespace.anon_decls.keys()) |sub_decl| {
3932 try decl_stack.append(gpa, sub_decl);
3933 }
3934 }3636 }
3935 }3637 }
3936}3638}
...@@ -4101,11 +3803,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4101,11 +3803,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4101 // prior to re-analysis.3803 // prior to re-analysis.
4102 try mod.deleteDeclExports(decl_index);3804 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
4109 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.3806 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
4110 for (decl.dependencies.keys()) |dep_index| {3807 for (decl.dependencies.keys()) |dep_index| {
4111 const dep = mod.declPtr(dep_index);3808 const dep = mod.declPtr(dep_index);
...@@ -4189,11 +3886,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4189,11 +3886,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4189 }3886 }
4190}3887}
41913888
4192pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void {3889pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaError!void {
4193 const tracy = trace(@src());3890 const tracy = trace(@src());
4194 defer tracy.end();3891 defer tracy.end();
41953892
4196 const func = mod.funcPtr(func_index);3893 const ip = &mod.intern_pool;
3894 const func = mod.funcInfo(func_index);
4197 const decl_index = func.owner_decl;3895 const decl_index = func.owner_decl;
4198 const decl = mod.declPtr(decl_index);3896 const decl = mod.declPtr(decl_index);
41993897
...@@ -4211,7 +3909,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4211,7 +3909,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
4211 => return error.AnalysisFail,3909 => return error.AnalysisFail,
42123910
4213 .complete, .codegen_failure_retryable => {3911 .complete, .codegen_failure_retryable => {
4214 switch (func.state) {3912 switch (func.analysis(ip).state) {
4215 .sema_failure, .dependency_failure => return error.AnalysisFail,3913 .sema_failure, .dependency_failure => return error.AnalysisFail,
4216 .none, .queued => {},3914 .none, .queued => {},
4217 .in_progress => unreachable,3915 .in_progress => unreachable,
...@@ -4227,11 +3925,11 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4227,11 +3925,11 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42273925
4228 var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {3926 var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
4229 error.AnalysisFail => {3927 error.AnalysisFail => {
4230 if (func.state == .in_progress) {3928 if (func.analysis(ip).state == .in_progress) {
4231 // If this decl caused the compile error, the analysis field would3929 // If this decl caused the compile error, the analysis field would
4232 // be changed to indicate it was this Decl's fault. Because this3930 // be changed to indicate it was this Decl's fault. Because this
4233 // did not happen, we infer here that it was a dependency failure.3931 // did not happen, we infer here that it was a dependency failure.
4234 func.state = .dependency_failure;3932 func.analysis(ip).state = .dependency_failure;
4235 }3933 }
4236 return error.AnalysisFail;3934 return error.AnalysisFail;
4237 },3935 },
...@@ -4251,14 +3949,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4251,14 +3949,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42513949
4252 if (no_bin_file and !dump_air and !dump_llvm_ir) return;3950 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);
4255 defer liveness.deinit(gpa);3953 defer liveness.deinit(gpa);
42563954
4257 if (dump_air) {3955 if (dump_air) {
4258 const fqn = try decl.getFullyQualifiedName(mod);3956 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)});
4260 @import("print_air.zig").dump(mod, air, liveness);3958 @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)});
4262 }3960 }
42633961
4264 if (std.debug.runtime_safety) {3962 if (std.debug.runtime_safety) {
...@@ -4266,7 +3964,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4266,7 +3964,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
4266 .gpa = gpa,3964 .gpa = gpa,
4267 .air = air,3965 .air = air,
4268 .liveness = liveness,3966 .liveness = liveness,
4269 .intern_pool = &mod.intern_pool,3967 .intern_pool = ip,
4270 };3968 };
4271 defer verify.deinit();3969 defer verify.deinit();
42723970
...@@ -4321,8 +4019,9 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4321,8 +4019,9 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
4321/// analyzed, and for ensuring it can exist at runtime (see4019/// analyzed, and for ensuring it can exist at runtime (see
4322/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body4020/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
4323/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.4021/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
4324pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {4022pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) !void {
4325 const func = mod.funcPtr(func_index);4023 const ip = &mod.intern_pool;
4024 const func = mod.funcInfo(func_index);
4326 const decl_index = func.owner_decl;4025 const decl_index = func.owner_decl;
4327 const decl = mod.declPtr(decl_index);4026 const decl = mod.declPtr(decl_index);
43284027
...@@ -4348,7 +4047,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {...@@ -4348,7 +4047,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
43484047
4349 assert(decl.has_tv);4048 assert(decl.has_tv);
43504049
4351 switch (func.state) {4050 switch (func.analysis(ip).state) {
4352 .none => {},4051 .none => {},
4353 .queued => return,4052 .queued => return,
4354 // As above, we don't need to forward errors here.4053 // As above, we don't need to forward errors here.
...@@ -4366,7 +4065,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {...@@ -4366,7 +4065,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
4366 // since the last update4065 // since the last update
4367 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });4066 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
4368 }4067 }
4369 func.state = .queued;4068 func.analysis(ip).state = .queued;
4370}4069}
43714070
4372pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {4071pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {
...@@ -4490,10 +4189,9 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4490,10 +4189,9 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4490 .code = file.zir,4189 .code = file.zir,
4491 .owner_decl = new_decl,4190 .owner_decl = new_decl,
4492 .owner_decl_index = new_decl_index,4191 .owner_decl_index = new_decl_index,
4493 .func = null,
4494 .func_index = .none,4192 .func_index = .none,
4495 .fn_ret_ty = Type.void,4193 .fn_ret_ty = Type.void,
4496 .owner_func = null,4194 .fn_ret_ty_ies = null,
4497 .owner_func_index = .none,4195 .owner_func_index = .none,
4498 .comptime_mutable_decls = &comptime_mutable_decls,4196 .comptime_mutable_decls = &comptime_mutable_decls,
4499 };4197 };
...@@ -4573,10 +4271,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4573,10 +4271,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4573 .code = zir,4271 .code = zir,
4574 .owner_decl = decl,4272 .owner_decl = decl,
4575 .owner_decl_index = decl_index,4273 .owner_decl_index = decl_index,
4576 .func = null,
4577 .func_index = .none,4274 .func_index = .none,
4578 .fn_ret_ty = Type.void,4275 .fn_ret_ty = Type.void,
4579 .owner_func = null,4276 .fn_ret_ty_ies = null,
4580 .owner_func_index = .none,4277 .owner_func_index = .none,
4581 .comptime_mutable_decls = &comptime_mutable_decls,4278 .comptime_mutable_decls = &comptime_mutable_decls,
4582 };4279 };
...@@ -4608,10 +4305,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4608,10 +4305,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4608 .inlining = null,4305 .inlining = null,
4609 .is_comptime = true,4306 .is_comptime = true,
4610 };4307 };
4611 defer {4308 defer block_scope.instructions.deinit(gpa);
4612 block_scope.instructions.deinit(gpa);
4613 block_scope.params.deinit(gpa);
4614 }
46154309
4616 const zir_block_index = decl.zirBlockIndex(mod);4310 const zir_block_index = decl.zirBlockIndex(mod);
4617 const inst_data = zir_datas[zir_block_index].pl_node;4311 const inst_data = zir_datas[zir_block_index].pl_node;
...@@ -4658,48 +4352,49 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4658,48 +4352,49 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4658 return true;4352 return true;
4659 }4353 }
46604354
4661 if (mod.intern_pool.indexToFunc(decl_tv.val.toIntern()).unwrap()) |func_index| {4355 const ip = &mod.intern_pool;
4662 const func = mod.funcPtr(func_index);4356 switch (ip.indexToKey(decl_tv.val.toIntern())) {
4663 const owns_tv = func.owner_decl == decl_index;4357 .func => |func| {
4664 if (owns_tv) {4358 const owns_tv = func.owner_decl == decl_index;
4665 var prev_type_has_bits = false;4359 if (owns_tv) {
4666 var prev_is_inline = false;4360 var prev_type_has_bits = false;
4667 var type_changed = true;4361 var prev_is_inline = false;
46684362 var type_changed = true;
4669 if (decl.has_tv) {4363
4670 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);4364 if (decl.has_tv) {
4671 type_changed = !decl.ty.eql(decl_tv.ty, mod);4365 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
4672 if (decl.getOwnedFunction(mod)) |prev_func| {4366 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4673 prev_is_inline = prev_func.state == .inline_only;4367 if (decl.getOwnedFunction(mod)) |prev_func| {
4368 prev_is_inline = prev_func.analysis(ip).state == .inline_only;
4369 }
4674 }4370 }
4675 }4371
4676 decl.clearValues(mod);4372 decl.ty = decl_tv.ty;
46774373 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
4678 decl.ty = decl_tv.ty;4374 // linksection, align, and addrspace were already set by Sema
4679 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();4375 decl.has_tv = true;
4680 // linksection, align, and addrspace were already set by Sema4376 decl.owns_tv = owns_tv;
4681 decl.has_tv = true;4377 decl.analysis = .complete;
4682 decl.owns_tv = owns_tv;4378 decl.generation = mod.generation;
4683 decl.analysis = .complete;4379
4684 decl.generation = mod.generation;4380 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
46854381 if (decl.is_exported) {
4686 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;4382 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
4687 if (decl.is_exported) {4383 if (is_inline) {
4688 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };4384 return sema.fail(&block_scope, export_src, "export of inline function", .{});
4689 if (is_inline) {4385 }
4690 return sema.fail(&block_scope, export_src, "export of inline function", .{});4386 // The scope needs to have the decl in it.
4387 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
4691 }4388 }
4692 // The scope needs to have the decl in it.4389 return type_changed or is_inline != prev_is_inline;
4693 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
4694 }4390 }
4695 return type_changed or is_inline != prev_is_inline;4391 },
4696 }4392 else => {},
4697 }4393 }
4698 var type_changed = true;4394 var type_changed = true;
4699 if (decl.has_tv) {4395 if (decl.has_tv) {
4700 type_changed = !decl.ty.eql(decl_tv.ty, mod);4396 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4701 }4397 }
4702 decl.clearValues(mod);
47034398
4704 decl.owns_tv = false;4399 decl.owns_tv = false;
4705 var queue_linker_work = false;4400 var queue_linker_work = false;
...@@ -4707,7 +4402,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4707,7 +4402,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4707 switch (decl_tv.val.toIntern()) {4402 switch (decl_tv.val.toIntern()) {
4708 .generic_poison => unreachable,4403 .generic_poison => unreachable,
4709 .unreachable_value => unreachable,4404 .unreachable_value => unreachable,
4710 else => switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {4405 else => switch (ip.indexToKey(decl_tv.val.toIntern())) {
4711 .variable => |variable| if (variable.decl == decl_index) {4406 .variable => |variable| if (variable.decl == decl_index) {
4712 decl.owns_tv = true;4407 decl.owns_tv = true;
4713 queue_linker_work = true;4408 queue_linker_work = true;
...@@ -4743,11 +4438,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4743,11 +4438,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4743 } else if (bytes.len == 0) {4438 } else if (bytes.len == 0) {
4744 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});4439 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
4745 }4440 }
4746 const section = try mod.intern_pool.getOrPutString(gpa, bytes);4441 const section = try ip.getOrPutString(gpa, bytes);
4747 break :blk section.toOptional();4442 break :blk section.toOptional();
4748 };4443 };
4749 decl.@"addrspace" = blk: {4444 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())) {
4751 .variable => .variable,4446 .variable => .variable,
4752 .extern_func, .func => .function,4447 .extern_func, .func => .function,
4753 else => .constant,4448 else => .constant,
...@@ -5309,7 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5309,7 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5309 decl.has_align = has_align;5004 decl.has_align = has_align;
5310 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;5005 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
5311 decl.zir_decl_index = @as(u32, @intCast(decl_sub_index));5006 decl.zir_decl_index = @as(u32, @intCast(decl_sub_index));
5312 if (decl.getOwnedFunctionIndex(mod) != .none) {5007 if (decl.getOwnedFunction(mod) != null) {
5313 switch (comp.bin_file.tag) {5008 switch (comp.bin_file.tag) {
5314 .coff, .elf, .macho, .plan9 => {5009 .coff, .elf, .macho, .plan9 => {
5315 // TODO Look into detecting when this would be unnecessary by storing enough state5010 // TODO Look into detecting when this would be unnecessary by storing enough state
...@@ -5386,7 +5081,6 @@ pub fn clearDecl(...@@ -5386,7 +5081,6 @@ pub fn clearDecl(
5386 try namespace.deleteAllDecls(mod, outdated_decls);5081 try namespace.deleteAllDecls(mod, outdated_decls);
5387 }5082 }
5388 }5083 }
5389 decl.clearValues(mod);
53905084
5391 if (decl.deletion_flag) {5085 if (decl.deletion_flag) {
5392 decl.deletion_flag = false;5086 decl.deletion_flag = false;
...@@ -5397,21 +5091,19 @@ pub fn clearDecl(...@@ -5397,21 +5091,19 @@ pub fn clearDecl(
5397}5091}
53985092
5399/// This function is exclusively called for anonymous decls.5093/// 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.
5400pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {5096pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {
5401 const decl = mod.declPtr(decl_index);5097 const gpa = mod.gpa;
54025098 const ip = &mod.intern_pool;
5403 assert(!mod.declIsRoot(decl_index));
5404 assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index));
54055099
5406 const dependants = decl.dependants.keys();5100 ip.destroyDecl(gpa, decl_index);
5407 for (dependants) |dep| {
5408 mod.declPtr(dep).removeDependency(decl_index);
5409 }
54105101
5411 for (decl.dependencies.keys()) |dep| {5102 if (mod.emit_h) |mod_emit_h| {
5412 mod.declPtr(dep).removeDependant(decl_index);5103 const decl_emit_h = mod_emit_h.declPtr(decl_index);
5104 decl_emit_h.fwd_decl.deinit(gpa);
5105 decl_emit_h.* = undefined;
5413 }5106 }
5414 mod.destroyDecl(decl_index);
5415}5107}
54165108
5417/// We don't perform a deletion here, because this Decl or another one5109/// 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 {...@@ -5428,7 +5120,6 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
5428 const decl = mod.declPtr(decl_index);5120 const decl = mod.declPtr(decl_index);
54295121
5430 assert(!mod.declIsRoot(decl_index));5122 assert(!mod.declIsRoot(decl_index));
5431 assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index));
54325123
5433 // An aborted decl must not have dependants -- they must have5124 // An aborted decl must not have dependants -- they must have
5434 // been aborted first and removed from this list.5125 // been aborted first and removed from this list.
...@@ -5497,19 +5188,26 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void...@@ -5497,19 +5188,26 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
5497 export_owners.deinit(mod.gpa);5188 export_owners.deinit(mod.gpa);
5498}5189}
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 {
5501 const tracy = trace(@src());5192 const tracy = trace(@src());
5502 defer tracy.end();5193 defer tracy.end();
55035194
5504 const gpa = mod.gpa;5195 const gpa = mod.gpa;
5505 const func = mod.funcPtr(func_index);5196 const ip = &mod.intern_pool;
5197 const func = mod.funcInfo(func_index);
5506 const decl_index = func.owner_decl;5198 const decl_index = func.owner_decl;
5507 const decl = mod.declPtr(decl_index);5199 const decl = mod.declPtr(decl_index);
55085200
5509 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);5201 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
5510 defer comptime_mutable_decls.deinit();5202 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.
5512 const fn_ty = decl.ty;5209 const fn_ty = decl.ty;
5210 const fn_ty_info = mod.typeToFunc(fn_ty).?;
55135211
5514 var sema: Sema = .{5212 var sema: Sema = .{
5515 .mod = mod,5213 .mod = mod,
...@@ -5518,18 +5216,23 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5518,18 +5216,23 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5518 .code = decl.getFileScope(mod).zir,5216 .code = decl.getFileScope(mod).zir,
5519 .owner_decl = decl,5217 .owner_decl = decl,
5520 .owner_decl_index = decl_index,5218 .owner_decl_index = decl_index,
5521 .func = func,5219 .func_index = func_index,
5522 .func_index = func_index.toOptional(),5220 .fn_ret_ty = fn_ty_info.return_type.toType(),
5523 .fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(),5221 .fn_ret_ty_ies = null,
5524 .owner_func = func,5222 .owner_func_index = func_index,
5525 .owner_func_index = func_index.toOptional(),5223 .branch_quota = @max(func.branchQuota(ip).*, Sema.default_branch_quota),
5526 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
5527 .comptime_mutable_decls = &comptime_mutable_decls,5224 .comptime_mutable_decls = &comptime_mutable_decls,
5528 };5225 };
5529 defer sema.deinit();5226 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
5531 // reset in case calls to errorable functions are removed.5234 // 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
5534 // First few indexes of extra are reserved and set at the end.5237 // First few indexes of extra are reserved and set at the end.
5535 const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len;5238 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...@@ -5551,8 +5254,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5551 };5254 };
5552 defer inner_block.instructions.deinit(gpa);5255 defer inner_block.instructions.deinit(gpa);
55535256
5554 const fn_info = sema.code.getFnInfo(func.zir_body_inst);5257 const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*);
5555 const zir_tags = sema.code.instructions.items(.tag);
55565258
5557 // Here we are performing "runtime semantic analysis" for a function body, which means5259 // Here we are performing "runtime semantic analysis" for a function body, which means
5558 // we must map the parameter ZIR instructions to `arg` AIR instructions.5260 // 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...@@ -5560,35 +5262,36 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5560 // This could be a generic function instantiation, however, in which case we need to5262 // This could be a generic function instantiation, however, in which case we need to
5561 // map the comptime parameters to constant values and only emit arg AIR instructions5263 // map the comptime parameters to constant values and only emit arg AIR instructions
5562 // for the runtime ones.5264 // 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;
5564 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);5266 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);
5566 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);5268 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
55675269
5568 var runtime_param_index: usize = 0;5270 // In the case of a generic function instance, pre-populate all the comptime args.
5569 var total_param_index: usize = 0;5271 if (func.comptime_args.len != 0) {
5570 for (fn_info.param_body) |inst| {5272 for (
5571 switch (zir_tags[inst]) {5273 fn_info.param_body[0..func.comptime_args.len],
5572 .param, .param_comptime, .param_anytype, .param_anytype_comptime => {},5274 func.comptime_args.get(ip),
5573 else => continue,5275 ) |inst, comptime_arg| {
5276 if (comptime_arg == .none) continue;
5277 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.internedToRef(comptime_arg));
5574 }5278 }
5575 const param_ty = if (func.comptime_args) |comptime_args| t: {5279 }
5576 const arg_tv = comptime_args[total_param_index];5280
55775281 const src_params_len = if (func.comptime_args.len != 0)
5578 const arg_val = if (!arg_tv.val.isGenericPoison())5282 func.comptime_args.len
5579 arg_tv.val5283 else
5580 else if (try arg_tv.ty.onePossibleValue(mod)) |opv|5284 runtime_params_len;
5581 opv5285
5582 else5286 var runtime_param_index: usize = 0;
5583 break :t arg_tv.ty;5287 for (fn_info.param_body[0..src_params_len], 0..) |inst, src_param_index| {
55845288 const gop = sema.inst_map.getOrPutAssumeCapacity(inst);
5585 const arg = try sema.addConstant(arg_val);5289 if (gop.found_existing) continue; // provided above by comptime arg
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();
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) {
5592 error.NeededSourceLocation => unreachable,5295 error.NeededSourceLocation => unreachable,
5593 error.GenericPoison => unreachable,5296 error.GenericPoison => unreachable,
5594 error.ComptimeReturn => unreachable,5297 error.ComptimeReturn => unreachable,
...@@ -5596,28 +5299,22 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5596,28 +5299,22 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5596 else => |e| return e,5299 else => |e| return e,
5597 };5300 };
5598 if (opt_opv) |opv| {5301 if (opt_opv) |opv| {
5599 const arg = try sema.addConstant(opv);5302 gop.value_ptr.* = Air.internedToRef(opv.toIntern());
5600 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5601 total_param_index += 1;
5602 runtime_param_index += 1;
5603 continue;5303 continue;
5604 }5304 }
5605 const air_ty = try sema.addType(param_ty);5305 const arg_index: u32 = @intCast(sema.air_instructions.len);
5606 const arg_index = @as(u32, @intCast(sema.air_instructions.len));5306 gop.value_ptr.* = Air.indexToRef(arg_index);
5607 inner_block.instructions.appendAssumeCapacity(arg_index);5307 inner_block.instructions.appendAssumeCapacity(arg_index);
5608 sema.air_instructions.appendAssumeCapacity(.{5308 sema.air_instructions.appendAssumeCapacity(.{
5609 .tag = .arg,5309 .tag = .arg,
5610 .data = .{ .arg = .{5310 .data = .{ .arg = .{
5611 .ty = air_ty,5311 .ty = Air.internedToRef(param_ty),
5612 .src_index = @as(u32, @intCast(total_param_index)),5312 .src_index = @intCast(src_param_index),
5613 } },5313 } },
5614 });5314 });
5615 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
5616 total_param_index += 1;
5617 runtime_param_index += 1;
5618 }5315 }
56195316
5620 func.state = .in_progress;5317 func.analysis(ip).state = .in_progress;
56215318
5622 const last_arg_index = inner_block.instructions.items.len;5319 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...@@ -5648,7 +5345,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5648 }5345 }
56495346
5650 // If we don't get an error return trace from a caller, create our own.5347 // If we don't get an error return trace from a caller, create our own.
5651 if (func.calls_or_awaits_errorable_fn and5348 if (func.analysis(ip).calls_or_awaits_errorable_fn and
5652 mod.comp.bin_file.options.error_return_tracing and5349 mod.comp.bin_file.options.error_return_tracing and
5653 !sema.fn_ret_ty.isError(mod))5350 !sema.fn_ret_ty.isError(mod))
5654 {5351 {
...@@ -5672,12 +5369,33 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5672,12 +5369,33 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5672 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +5369 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
5673 inner_block.instructions.items.len);5370 inner_block.instructions.items.len);
5674 const main_block_index = sema.addExtraAssumeCapacity(Air.Block{5371 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),
5676 });5373 });
5677 sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);5374 sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
5678 sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;5375 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
5682 // Finally we must resolve the return type and parameter types so that backends5400 // Finally we must resolve the return type and parameter types so that backends
5683 // have full access to type information.5401 // have full access to type information.
...@@ -5716,7 +5434,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5716,7 +5434,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5716 };5434 };
5717 }5435 }
57185436
5719 return Air{5437 return .{
5720 .instructions = sema.air_instructions.toOwnedSlice(),5438 .instructions = sema.air_instructions.toOwnedSlice(),
5721 .extra = try sema.air_extra.toOwnedSlice(gpa),5439 .extra = try sema.air_extra.toOwnedSlice(gpa),
5722 };5440 };
...@@ -5731,9 +5449,6 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -5731,9 +5449,6 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5731 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {5449 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
5732 for (kv.value) |err| err.deinit(mod.gpa);5450 for (kv.value) |err| err.deinit(mod.gpa);
5733 }5451 }
5734 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
5735 _ = mod.align_stack_fns.remove(func);
5736 }
5737 if (mod.emit_h) |emit_h| {5452 if (mod.emit_h) |emit_h| {
5738 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {5453 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
5739 kv.value.destroy(mod.gpa);5454 kv.value.destroy(mod.gpa);
...@@ -5744,21 +5459,11 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -5744,21 +5459,11 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5744}5459}
57455460
5746pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index {5461pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index {
5747 if (mod.namespaces_free_list.popOrNull()) |index| {5462 return mod.intern_pool.createNamespace(mod.gpa, initialization);
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));
5754}5463}
57555464
5756pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void {5465pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void {
5757 mod.namespacePtr(index).* = undefined;5466 return mod.intern_pool.destroyNamespace(mod.gpa, index);
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 };
5762}5467}
57635468
5764pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index {5469pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index {
...@@ -5777,43 +5482,15 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {...@@ -5777,43 +5482,15 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {
5777 return mod.intern_pool.destroyUnion(mod.gpa, index);5482 return mod.intern_pool.destroyUnion(mod.gpa, index);
5778}5483}
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
5788pub fn allocateNewDecl(5485pub fn allocateNewDecl(
5789 mod: *Module,5486 mod: *Module,
5790 namespace: Namespace.Index,5487 namespace: Namespace.Index,
5791 src_node: Ast.Node.Index,5488 src_node: Ast.Node.Index,
5792 src_scope: ?*CaptureScope,5489 src_scope: ?*CaptureScope,
5793) !Decl.Index {5490) !Decl.Index {
5794 const decl_and_index: struct {5491 const ip = &mod.intern_pool;
5795 new_decl: *Decl,5492 const gpa = mod.gpa;
5796 decl_index: Decl.Index,5493 const decl_index = try ip.createDecl(gpa, .{
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.* = .{
5817 .name = undefined,5494 .name = undefined,
5818 .src_namespace = namespace,5495 .src_namespace = namespace,
5819 .src_node = src_node,5496 .src_node = src_node,
...@@ -5836,9 +5513,18 @@ pub fn allocateNewDecl(...@@ -5836,9 +5513,18 @@ pub fn allocateNewDecl(
5836 .has_align = false,5513 .has_align = false,
5837 .alive = false,5514 .alive = false,
5838 .kind = .anon,5515 .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;
5842}5528}
58435529
5844pub fn getErrorValue(5530pub fn getErrorValue(
...@@ -5874,7 +5560,7 @@ pub fn createAnonymousDeclFromDecl(...@@ -5874,7 +5560,7 @@ pub fn createAnonymousDeclFromDecl(
5874 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{5560 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{
5875 src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index),5561 src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index),
5876 });5562 });
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);
5878 return new_decl_index;5564 return new_decl_index;
5879}5565}
58805566
...@@ -5882,7 +5568,6 @@ pub fn initNewAnonDecl(...@@ -5882,7 +5568,6 @@ pub fn initNewAnonDecl(
5882 mod: *Module,5568 mod: *Module,
5883 new_decl_index: Decl.Index,5569 new_decl_index: Decl.Index,
5884 src_line: u32,5570 src_line: u32,
5885 namespace: Namespace.Index,
5886 typed_value: TypedValue,5571 typed_value: TypedValue,
5887 name: InternPool.NullTerminatedString,5572 name: InternPool.NullTerminatedString,
5888) Allocator.Error!void {5573) Allocator.Error!void {
...@@ -5899,8 +5584,6 @@ pub fn initNewAnonDecl(...@@ -5899,8 +5584,6 @@ pub fn initNewAnonDecl(
5899 new_decl.has_tv = true;5584 new_decl.has_tv = true;
5900 new_decl.analysis = .complete;5585 new_decl.analysis = .complete;
5901 new_decl.generation = mod.generation;5586 new_decl.generation = mod.generation;
5902
5903 try mod.namespacePtr(namespace).anon_decls.putNoClobber(mod.gpa, new_decl_index, {});
5904}5587}
59055588
5906pub fn errNoteNonLazy(5589pub fn errNoteNonLazy(
...@@ -6578,7 +6261,6 @@ pub fn populateTestFunctions(...@@ -6578,7 +6261,6 @@ pub fn populateTestFunctions(
65786261
6579 // Since we are replacing the Decl's value we must perform cleanup on the6262 // Since we are replacing the Decl's value we must perform cleanup on the
6580 // previous value.6263 // previous value.
6581 decl.clearValues(mod);
6582 decl.ty = new_ty;6264 decl.ty = new_ty;
6583 decl.val = new_val;6265 decl.val = new_val;
6584 decl.has_tv = true;6266 decl.has_tv = true;
...@@ -6657,7 +6339,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {...@@ -6657,7 +6339,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
6657 switch (mod.intern_pool.indexToKey(val.toIntern())) {6339 switch (mod.intern_pool.indexToKey(val.toIntern())) {
6658 .variable => |variable| try mod.markDeclIndexAlive(variable.decl),6340 .variable => |variable| try mod.markDeclIndexAlive(variable.decl),
6659 .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),6341 .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),
6661 .error_union => |error_union| switch (error_union.val) {6343 .error_union => |error_union| switch (error_union.val) {
6662 .err_name => {},6344 .err_name => {},
6663 .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),6345 .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),
...@@ -6851,8 +6533,8 @@ pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator...@@ -6851,8 +6533,8 @@ pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator
6851 return mod.ptrType(info);6533 return mod.ptrType(info);
6852}6534}
68536535
6854pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Type {6536pub fn funcType(mod: *Module, key: InternPool.GetFuncTypeKey) Allocator.Error!Type {
6855 return (try intern(mod, .{ .func_type = info })).toType();6537 return (try mod.intern_pool.getFuncType(mod.gpa, key)).toType();
6856}6538}
68576539
6858/// Use this for `anyframe->T` only.6540/// Use this for `anyframe->T` only.
...@@ -6870,7 +6552,8 @@ pub fn errorUnionType(mod: *Module, error_set_ty: Type, payload_ty: Type) Alloca...@@ -6870,7 +6552,8 @@ pub fn errorUnionType(mod: *Module, error_set_ty: Type, payload_ty: Type) Alloca
68706552
6871pub fn singleErrorSetType(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type {6553pub fn singleErrorSetType(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type {
6872 const names: *const [1]InternPool.NullTerminatedString = &name;6554 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();
6874}6557}
68756558
6876/// Sorts `names` in place.6559/// Sorts `names` in place.
...@@ -6884,7 +6567,7 @@ pub fn errorSetFromUnsortedNames(...@@ -6884,7 +6567,7 @@ pub fn errorSetFromUnsortedNames(
6884 {},6567 {},
6885 InternPool.NullTerminatedString.indexLessThan,6568 InternPool.NullTerminatedString.indexLessThan,
6886 );6569 );
6887 const new_ty = try mod.intern(.{ .error_set_type = .{ .names = names } });6570 const new_ty = try mod.intern_pool.getErrorSetType(mod.gpa, names);
6888 return new_ty.toType();6571 return new_ty.toType();
6889}6572}
68906573
...@@ -7231,14 +6914,20 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {...@@ -7231,14 +6914,20 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {
7231 return mod.intern_pool.indexToFuncType(ty.toIntern());6914 return mod.intern_pool.indexToFuncType(ty.toIntern());
7232}6915}
72336916
7234pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*Fn.InferredErrorSet {6917pub fn funcOwnerDeclPtr(mod: *Module, func_index: InternPool.Index) *Decl {
7235 const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;6918 return mod.declPtr(mod.funcOwnerDeclIndex(func_index));
7236 return mod.inferredErrorSetPtr(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);
7237}6927}
72386928
7239pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) Fn.InferredErrorSet.OptionalIndex {6929pub fn funcInfo(mod: *Module, func_index: InternPool.Index) InternPool.Key.Func {
7240 if (ty.ip_index == .none) return .none;6930 return mod.intern_pool.indexToKey(func_index).func;
7241 return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern());
7242}6931}
72436932
7244pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {6933pub 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...@@ -7265,3 +6954,41 @@ pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQu
7265pub fn toEnum(mod: *Module, comptime E: type, val: Value) E {6954pub fn toEnum(mod: *Module, comptime E: type, val: Value) E {
7266 return mod.intern_pool.toEnum(E, val.toIntern());6955 return mod.intern_pool.toEnum(E, val.toIntern());
7267}6956}
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,...@@ -23,13 +23,13 @@ owner_decl: *Decl,
23owner_decl_index: Decl.Index,23owner_decl_index: Decl.Index,
24/// For an inline or comptime function call, this will be the root parent function24/// For an inline or comptime function call, this will be the root parent function
25/// which contains the callsite. Corresponds to `owner_decl`.25/// which contains the callsite. Corresponds to `owner_decl`.
26owner_func: ?*Module.Fn,26/// This could be `none`, a `func_decl`, or a `func_instance`.
27owner_func_index: Module.Fn.OptionalIndex,27owner_func_index: InternPool.Index,
28/// The function this ZIR code is the body of, according to the source code.28/// 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 of29/// This starts out the same as `owner_func_index` and then diverges in the case of
30/// an inline or comptime function call.30/// an inline or comptime function call.
31func: ?*Module.Fn,31/// This could be `none`, a `func_decl`, or a `func_instance`.
32func_index: Module.Fn.OptionalIndex,32func_index: InternPool.Index,
33/// Used to restore the error return trace when returning a non-error from a function.33/// Used to restore the error return trace when returning a non-error from a function.
34error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,34error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
35/// When semantic analysis needs to know the return type of the function whose body35/// 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,...@@ -38,6 +38,10 @@ error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
38/// generic function which uses a type expression for the return type.38/// generic function which uses a type expression for the return type.
39/// The type will be `void` in the case that `func` is `null`.39/// The type will be `void` in the case that `func` is `null`.
40fn_ret_ty: Type,40fn_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,
41branch_quota: u32 = default_branch_quota,45branch_quota: u32 = default_branch_quota,
42branch_count: u32 = 0,46branch_count: u32 = 0,
43/// Populated when returning `error.ComptimeBreak`. Used to communicate the47/// Populated when returning `error.ComptimeBreak`. Used to communicate the
...@@ -49,21 +53,23 @@ comptime_break_inst: Zir.Inst.Index = undefined,...@@ -49,21 +53,23 @@ comptime_break_inst: Zir.Inst.Index = undefined,
49/// contain a mapped source location.53/// contain a mapped source location.
50src: LazySrcLoc = .{ .token_offset = 0 },54src: LazySrcLoc = .{ .token_offset = 0 },
51decl_val_table: std.AutoHashMapUnmanaged(Decl.Index, Air.Inst.Ref) = .{},55decl_val_table: std.AutoHashMapUnmanaged(Decl.Index, Air.Inst.Ref) = .{},
52/// When doing a generic function instantiation, this array collects a56/// When doing a generic function instantiation, this array collects a value
53/// `Value` object for each parameter that is comptime-known and thus elided57/// for each parameter of the generic owner. `none` for non-comptime parameters.
54/// from the generated function. This memory is allocated by a parent `Sema` and58/// This is a separate array from `block.params` so that it can be passed
55/// owned by the values arena of the Sema owner_decl.59/// directly to `comptime_args` when calling `InternPool.getFuncInstance`.
56comptime_args: []TypedValue = &.{},60/// This memory is allocated by a parent `Sema` in the temporary arena, and is
57/// Marks the function instruction that `comptime_args` applies to so that we61/// used only to add a `func_instance` into the `InternPool`.
58/// don't accidentally apply it to a function prototype which is used in the62comptime_args: []InternPool.Index = &.{},
59/// type expression of a generic function parameter.63/// Used to communicate from a generic function instantiation to the logic that
60comptime_args_fn_inst: Zir.Inst.Index = 0,64/// creates a generic function instantiation value in `funcCommon`.
61/// When `comptime_args` is provided, this field is also provided. It was used as65generic_owner: InternPool.Index = .none,
62/// the key in the `monomorphed_funcs` set. The `func` instruction is supposed66/// When `generic_owner` is not none, this contains the generic function
63/// to use this instead of allocating a fresh one. This avoids an unnecessary67/// instantiation callsite so that compile errors on the parameter types of the
64/// extra hash table lookup in the `monomorphed_funcs` set.68/// instantiation can point back to the instantiation site in addition to the
65/// Sema will set this to null when it takes ownership.69/// declaration site.
66preallocated_new_func: Module.Fn.OptionalIndex = .none,70generic_call_src: LazySrcLoc = .unneeded,
71/// Corresponds to `generic_call_src`.
72generic_call_decl: Decl.OptionalIndex = .none,
67/// The key is types that must be fully resolved prior to machine code73/// The key is types that must be fully resolved prior to machine code
68/// generation pass. Types are added to this set when resolving them74/// generation pass. Types are added to this set when resolving them
69/// immediately could cause a dependency loop, but they do need to be resolved75/// 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) = .{},...@@ -79,8 +85,6 @@ types_to_resolve: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{},
79post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},85post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
80/// Populated with the last compile error created.86/// Populated with the last compile error created.
81err: ?*Module.ErrorMsg = null,87err: ?*Module.ErrorMsg = null,
82/// True when analyzing a generic instantiation. Used to suppress some errors.
83is_generic_instantiation: bool = false,
84/// Set to true when analyzing a func type instruction so that nested generic88/// Set to true when analyzing a func type instruction so that nested generic
85/// function types will emit generic poison instead of a partial type.89/// function types will emit generic poison instead of a partial type.
86no_partial_func_ty: bool = false,90no_partial_func_ty: bool = false,
...@@ -97,6 +101,10 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAll...@@ -97,6 +101,10 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAll
97/// involve transitioning comptime-mutable memory away from using Decls at all.101/// involve transitioning comptime-mutable memory away from using Decls at all.
98comptime_mutable_decls: *std.ArrayList(Decl.Index),102comptime_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
100const std = @import("std");108const std = @import("std");
101const math = std.math;109const math = std.math;
102const mem = std.mem;110const mem = std.mem;
...@@ -131,6 +139,49 @@ const Alignment = InternPool.Alignment;...@@ -131,6 +139,49 @@ const Alignment = InternPool.Alignment;
131pub const default_branch_quota = 1000;139pub const default_branch_quota = 1000;
132pub const default_reference_trace_len = 2;140pub 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
134/// Stores the mapping from `Zir.Inst.Index -> Air.Inst.Ref`, which is used by sema to resolve185/// Stores the mapping from `Zir.Inst.Index -> Air.Inst.Ref`, which is used by sema to resolve
135/// instructions during analysis.186/// instructions during analysis.
136/// Instead of a hash table approach, InstMap is simply a slice that is indexed into using the187/// 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 {...@@ -243,7 +294,13 @@ pub const Block = struct {
243 /// The AIR instructions generated for this block.294 /// The AIR instructions generated for this block.
244 instructions: std.ArrayListUnmanaged(Air.Inst.Index),295 instructions: std.ArrayListUnmanaged(Air.Inst.Index),
245 // `param` instructions are collected here to be used by the `func` instruction.296 // `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
248 wip_capture_scope: *CaptureScope,305 wip_capture_scope: *CaptureScope,
249306
...@@ -323,10 +380,10 @@ pub const Block = struct {...@@ -323,10 +380,10 @@ pub const Block = struct {
323 };380 };
324381
325 const Param = struct {382 const Param = struct {
326 /// `noreturn` means `anytype`.383 /// `none` means `anytype`.
327 ty: Type,384 ty: InternPool.Index,
328 is_comptime: bool,385 is_comptime: bool,
329 name: []const u8,386 name: Zir.NullTerminatedString,
330 };387 };
331388
332 /// This `Block` maps a block ZIR instruction to the corresponding389 /// This `Block` maps a block ZIR instruction to the corresponding
...@@ -342,7 +399,8 @@ pub const Block = struct {...@@ -342,7 +399,8 @@ pub const Block = struct {
342 /// It is shared among all the blocks in an inline or comptime called399 /// It is shared among all the blocks in an inline or comptime called
343 /// function.400 /// function.
344 pub const Inlining = struct {401 pub const Inlining = struct {
345 func: ?*Module.Fn,402 /// Might be `none`.
403 func: InternPool.Index,
346 comptime_result: Air.Inst.Ref,404 comptime_result: Air.Inst.Ref,
347 merges: Merges,405 merges: Merges,
348 };406 };
...@@ -906,7 +964,7 @@ fn analyzeBodyInner(...@@ -906,7 +964,7 @@ fn analyzeBodyInner(
906 // We use a while (true) loop here to avoid a redundant way of breaking out of964 // We use a while (true) loop here to avoid a redundant way of breaking out of
907 // the loop. The only way to break out of the loop is with a `noreturn`965 // the loop. The only way to break out of the loop is with a `noreturn`
908 // instruction.966 // instruction.
909 var i: usize = 0;967 var i: u32 = 0;
910 const result = while (true) {968 const result = while (true) {
911 crash_info.setBodyIndex(i);969 crash_info.setBodyIndex(i);
912 const inst = body[i];970 const inst = body[i];
...@@ -1116,7 +1174,7 @@ fn analyzeBodyInner(...@@ -1116,7 +1174,7 @@ fn analyzeBodyInner(
1116 .shl_sat => try sema.zirShl(block, inst, .shl_sat),1174 .shl_sat => try sema.zirShl(block, inst, .shl_sat),
11171175
1118 .ret_ptr => try sema.zirRetPtr(block),1176 .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
1121 // Instructions that we know to *always* be noreturn based solely on their tag.1179 // Instructions that we know to *always* be noreturn based solely on their tag.
1122 // These functions match the return type of analyzeBody so that we can1180 // These functions match the return type of analyzeBody so that we can
...@@ -1338,22 +1396,22 @@ fn analyzeBodyInner(...@@ -1338,22 +1396,22 @@ fn analyzeBodyInner(
1338 continue;1396 continue;
1339 },1397 },
1340 .param => {1398 .param => {
1341 try sema.zirParam(block, inst, false);1399 try sema.zirParam(block, inst, i, false);
1342 i += 1;1400 i += 1;
1343 continue;1401 continue;
1344 },1402 },
1345 .param_comptime => {1403 .param_comptime => {
1346 try sema.zirParam(block, inst, true);1404 try sema.zirParam(block, inst, i, true);
1347 i += 1;1405 i += 1;
1348 continue;1406 continue;
1349 },1407 },
1350 .param_anytype => {1408 .param_anytype => {
1351 try sema.zirParamAnytype(block, inst, false);1409 try sema.zirParamAnytype(block, inst, i, false);
1352 i += 1;1410 i += 1;
1353 continue;1411 continue;
1354 },1412 },
1355 .param_anytype_comptime => {1413 .param_anytype_comptime => {
1356 try sema.zirParamAnytype(block, inst, true);1414 try sema.zirParamAnytype(block, inst, i, true);
1357 i += 1;1415 i += 1;
1358 continue;1416 continue;
1359 },1417 },
...@@ -1493,10 +1551,7 @@ fn analyzeBodyInner(...@@ -1493,10 +1551,7 @@ fn analyzeBodyInner(
1493 // Note: this probably needs to be resolved in a more general manner.1551 // Note: this probably needs to be resolved in a more general manner.
1494 const prev_params = block.params;1552 const prev_params = block.params;
1495 block.params = .{};1553 block.params = .{};
1496 defer {1554 defer block.params = prev_params;
1497 block.params.deinit(sema.gpa);
1498 block.params = prev_params;
1499 }
1500 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1555 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1501 break always_noreturn;1556 break always_noreturn;
1502 if (inst == break_data.block_inst) {1557 if (inst == break_data.block_inst) {
...@@ -1532,7 +1587,6 @@ fn analyzeBodyInner(...@@ -1532,7 +1587,6 @@ fn analyzeBodyInner(
1532 .merges = undefined,1587 .merges = undefined,
1533 };1588 };
1534 child_block.label = &label;1589 child_block.label = &label;
1535 defer child_block.params.deinit(gpa);
15361590
1537 // Write these instructions directly into the parent block1591 // Write these instructions directly into the parent block
1538 child_block.instructions = block.instructions;1592 child_block.instructions = block.instructions;
...@@ -2008,10 +2062,7 @@ fn resolveDefinedValue(...@@ -2008,10 +2062,7 @@ fn resolveDefinedValue(
2008/// Value Tag `variable` causes this function to return `null`.2062/// Value Tag `variable` causes this function to return `null`.
2009/// Value Tag `undef` causes this function to return the Value.2063/// Value Tag `undef` causes this function to return the Value.
2010/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.2064/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
2011fn resolveMaybeUndefVal(2065fn resolveMaybeUndefVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2012 sema: *Sema,
2013 inst: Air.Inst.Ref,
2014) CompileError!?Value {
2015 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;2066 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
2016 if (val.isGenericPoison()) return error.GenericPoison;2067 if (val.isGenericPoison()) return error.GenericPoison;
2017 if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null;2068 if (val.ip_index != .none and sema.mod.intern_pool.isVariable(val.toIntern())) return null;
...@@ -2022,10 +2073,7 @@ fn resolveMaybeUndefVal(...@@ -2022,10 +2073,7 @@ fn resolveMaybeUndefVal(
2022/// Value Tag `undef` causes this function to return the Value.2073/// Value Tag `undef` causes this function to return the Value.
2023/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.2074/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
2024/// Lazy values are recursively resolved.2075/// Lazy values are recursively resolved.
2025fn resolveMaybeUndefLazyVal(2076fn resolveMaybeUndefLazyVal(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2026 sema: *Sema,
2027 inst: Air.Inst.Ref,
2028) CompileError!?Value {
2029 return try sema.resolveLazyValue((try sema.resolveMaybeUndefVal(inst)) orelse return null);2077 return try sema.resolveLazyValue((try sema.resolveMaybeUndefVal(inst)) orelse return null);
2030}2078}
20312079
...@@ -2034,10 +2082,7 @@ fn resolveMaybeUndefLazyVal(...@@ -2034,10 +2082,7 @@ fn resolveMaybeUndefLazyVal(
2034/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.2082/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
2035/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`.2083/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`.
2036/// Lazy values are recursively resolved.2084/// Lazy values are recursively resolved.
2037fn resolveMaybeUndefValIntable(2085fn resolveMaybeUndefValIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2038 sema: *Sema,
2039 inst: Air.Inst.Ref,
2040) CompileError!?Value {
2041 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;2086 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
2042 if (val.isGenericPoison()) return error.GenericPoison;2087 if (val.isGenericPoison()) return error.GenericPoison;
2043 if (val.ip_index == .none) return val;2088 if (val.ip_index == .none) return val;
...@@ -2363,7 +2408,10 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {...@@ -2363,7 +2408,10 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2363 break :blk default_reference_trace_len;2408 break :blk default_reference_trace_len;
2364 };2409 };
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;
2367 var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa);2415 var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa);
2368 defer reference_stack.deinit();2416 defer reference_stack.deinit();
23692417
...@@ -2399,14 +2447,15 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {...@@ -2399,14 +2447,15 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2399 }2447 }
2400 err_msg.reference_trace = try reference_stack.toOwnedSlice();2448 err_msg.reference_trace = try reference_stack.toOwnedSlice();
2401 }2449 }
2402 if (sema.owner_func) |func| {2450 const ip = &mod.intern_pool;
2403 func.state = .sema_failure;2451 if (sema.owner_func_index != .none) {
2452 ip.funcAnalysis(sema.owner_func_index).state = .sema_failure;
2404 } else {2453 } else {
2405 sema.owner_decl.analysis = .sema_failure;2454 sema.owner_decl.analysis = .sema_failure;
2406 sema.owner_decl.generation = mod.generation;2455 sema.owner_decl.generation = mod.generation;
2407 }2456 }
2408 if (sema.func) |func| {2457 if (sema.func_index != .none) {
2409 func.state = .sema_failure;2458 ip.funcAnalysis(sema.func_index).state = .sema_failure;
2410 }2459 }
2411 const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index);2460 const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index);
2412 if (gop.found_existing) {2461 if (gop.found_existing) {
...@@ -2866,6 +2915,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2866,6 +2915,7 @@ fn createAnonymousDeclTypeNamed(
2866 inst: ?Zir.Inst.Index,2915 inst: ?Zir.Inst.Index,
2867) !Decl.Index {2916) !Decl.Index {
2868 const mod = sema.mod;2917 const mod = sema.mod;
2918 const ip = &mod.intern_pool;
2869 const gpa = sema.gpa;2919 const gpa = sema.gpa;
2870 const namespace = block.namespace;2920 const namespace = block.namespace;
2871 const src_scope = block.wip_capture_scope;2921 const src_scope = block.wip_capture_scope;
...@@ -2886,16 +2936,16 @@ fn createAnonymousDeclTypeNamed(...@@ -2886,16 +2936,16 @@ fn createAnonymousDeclTypeNamed(
2886 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{2936 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
2887 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index),2937 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index),
2888 }) catch unreachable;2938 }) 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);
2890 return new_decl_index;2940 return new_decl_index;
2891 },2941 },
2892 .parent => {2942 .parent => {
2893 const name = mod.declPtr(block.src_decl).name;2943 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);
2895 return new_decl_index;2945 return new_decl_index;
2896 },2946 },
2897 .func => {2947 .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));
2899 const zir_tags = sema.code.instructions.items(.tag);2949 const zir_tags = sema.code.instructions.items(.tag);
29002950
2901 var buf = std.ArrayList(u8).init(gpa);2951 var buf = std.ArrayList(u8).init(gpa);
...@@ -2927,7 +2977,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2927,7 +2977,7 @@ fn createAnonymousDeclTypeNamed(
29272977
2928 try writer.writeByte(')');2978 try writer.writeByte(')');
2929 const name = try mod.intern_pool.getOrPutString(gpa, buf.items);2979 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);
2931 return new_decl_index;2981 return new_decl_index;
2932 },2982 },
2933 .dbg_var => {2983 .dbg_var => {
...@@ -2943,7 +2993,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2943,7 +2993,7 @@ fn createAnonymousDeclTypeNamed(
2943 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),2993 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),
2944 });2994 });
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);
2947 return new_decl_index;2997 return new_decl_index;
2948 },2998 },
2949 else => {},2999 else => {},
...@@ -3070,18 +3120,12 @@ fn zirEnumDecl(...@@ -3070,18 +3120,12 @@ fn zirEnumDecl(
3070 sema.owner_decl_index = prev_owner_decl_index;3120 sema.owner_decl_index = prev_owner_decl_index;
3071 }3121 }
30723122
3073 const prev_owner_func = sema.owner_func;
3074 const prev_owner_func_index = sema.owner_func_index;3123 const prev_owner_func_index = sema.owner_func_index;
3075 sema.owner_func = null;
3076 sema.owner_func_index = .none;3124 sema.owner_func_index = .none;
3077 defer sema.owner_func = prev_owner_func;
3078 defer sema.owner_func_index = prev_owner_func_index;3125 defer sema.owner_func_index = prev_owner_func_index;
30793126
3080 const prev_func = sema.func;
3081 const prev_func_index = sema.func_index;3127 const prev_func_index = sema.func_index;
3082 sema.func = null;
3083 sema.func_index = .none;3128 sema.func_index = .none;
3084 defer sema.func = prev_func;
3085 defer sema.func_index = prev_func_index;3129 defer sema.func_index = prev_func_index;
30863130
3087 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);3131 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);
...@@ -3393,7 +3437,7 @@ fn zirErrorSetDecl(...@@ -3393,7 +3437,7 @@ fn zirErrorSetDecl(
3393 const src = inst_data.src();3437 const src = inst_data.src();
3394 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);3438 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 = .{};
3397 try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len);3441 try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len);
33983442
3399 var extra_index = @as(u32, @intCast(extra.end));3443 var extra_index = @as(u32, @intCast(extra.end));
...@@ -5236,12 +5280,10 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v...@@ -5236,12 +5280,10 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
5236 // %b = store(%a, %c)5280 // %b = store(%a, %c)
5237 // Where %c is an error union or error set. In such case we need to add5281 // Where %c is an error union or error set. In such case we need to add
5238 // to the current function's inferred error set, if any.5282 // to the current function's inferred error set, if any.
5239 if (is_ret and (sema.typeOf(operand).zigTypeTag(mod) == .ErrorUnion or5283 if (is_ret and sema.fn_ret_ty_ies != null) switch (sema.typeOf(operand).zigTypeTag(mod)) {
5240 sema.typeOf(operand).zigTypeTag(mod) == .ErrorSet) and5284 .ErrorUnion, .ErrorSet => try sema.addToInferredErrorSet(operand),
5241 sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion)5285 else => {},
5242 {5286 };
5243 try sema.addToInferredErrorSet(operand);
5244 }
52455287
5246 const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node };5288 const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node };
5247 const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node };5289 const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node };
...@@ -5379,7 +5421,10 @@ fn zirCompileLog(...@@ -5379,7 +5421,10 @@ fn zirCompileLog(
5379 }5421 }
5380 try writer.print("\n", .{});5422 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;
5383 const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index);5428 const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index);
5384 if (!gop.found_existing) {5429 if (!gop.found_existing) {
5385 gop.value_ptr.* = src_node;5430 gop.value_ptr.* = src_node;
...@@ -5967,11 +6012,11 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -5967,11 +6012,11 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5967 alignment.toByteUnitsOptional().?,6012 alignment.toByteUnitsOptional().?,
5968 });6013 });
5969 }6014 }
5970 const func_index = sema.func_index.unwrap() orelse6015 if (sema.func_index == .none) {
5971 return sema.fail(block, src, "@setAlignStack outside function body", .{});6016 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);
5975 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {6020 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
5976 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),6021 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
5977 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),6022 .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...@@ -5980,25 +6025,34 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5980 },6025 },
5981 }6026 }
59826027
5983 const gop = try mod.align_stack_fns.getOrPut(sema.gpa, func_index);6028 if (sema.prev_stack_alignment_src) |prev_src| {
5984 if (gop.found_existing) {
5985 const msg = msg: {6029 const msg = msg: {
5986 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});6030 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});
5987 errdefer msg.destroy(sema.gpa);6031 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", .{});
5989 break :msg msg;6033 break :msg msg;
5990 };6034 };
5991 return sema.failWithOwnedErrorMsg(msg);6035 return sema.failWithOwnedErrorMsg(msg);
5992 }6036 }
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 }
5994}6046}
59956047
5996fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {6048fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
6049 const mod = sema.mod;
6050 const ip = &mod.intern_pool;
5997 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;6051 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
5998 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };6052 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
5999 const is_cold = try sema.resolveConstBool(block, operand_src, extra.operand, "operand to @setCold must be comptime-known");6053 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 function6054 if (sema.func_index == .none) return; // does nothing outside a function
6001 func.is_cold = is_cold;6055 ip.funcAnalysis(sema.func_index).is_cold = is_cold;
6002}6056}
60036057
6004fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {6058fn 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 {...@@ -6308,7 +6362,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
6308 if (func_val.isUndef(mod)) return null;6362 if (func_val.isUndef(mod)) return null;
6309 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {6363 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
6310 .extern_func => |extern_func| extern_func.decl,6364 .extern_func => |extern_func| extern_func.decl,
6311 .func => |func| mod.funcPtr(func.index).owner_decl,6365 .func => |func| func.owner_decl,
6312 .ptr => |ptr| switch (ptr.addr) {6366 .ptr => |ptr| switch (ptr.addr) {
6313 .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl,6367 .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl,
6314 else => return null,6368 else => return null,
...@@ -6445,6 +6499,7 @@ fn zirCall(...@@ -6445,6 +6499,7 @@ fn zirCall(
6445 defer tracy.end();6499 defer tracy.end();
64466500
6447 const mod = sema.mod;6501 const mod = sema.mod;
6502 const ip = &mod.intern_pool;
6448 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6503 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6449 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };6504 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
6450 const call_src = inst_data.src();6505 const call_src = inst_data.src();
...@@ -6493,9 +6548,10 @@ fn zirCall(...@@ -6493,9 +6548,10 @@ fn zirCall(
6493 const args_body = sema.code.extra[extra.end..];6548 const args_body = sema.code.extra[extra.end..];
64946549
6495 var input_is_error = false;6550 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;
6499 const parent_comptime = block.is_comptime;6555 const parent_comptime = block.is_comptime;
6500 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.6556 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
6501 var extra_index: usize = 0;6557 var extra_index: usize = 0;
...@@ -6504,13 +6560,12 @@ fn zirCall(...@@ -6504,13 +6560,12 @@ fn zirCall(
6504 extra_index += 1;6560 extra_index += 1;
6505 arg_index += 1;6561 arg_index += 1;
6506 }) {6562 }) {
6507 const func_ty_info = mod.typeToFunc(func_ty).?;
6508 const arg_end = sema.code.extra[extra.end + extra_index];6563 const arg_end = sema.code.extra[extra.end + extra_index];
6509 defer arg_start = arg_end;6564 defer arg_start = arg_end;
65106565
6511 // Generate args to comptime params in comptime block.6566 // Generate args to comptime params in comptime block.
6512 defer block.is_comptime = parent_comptime;6567 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))) {
6514 block.is_comptime = true;6569 block.is_comptime = true;
6515 // TODO set comptime_reason6570 // TODO set comptime_reason
6516 }6571 }
...@@ -6519,10 +6574,10 @@ fn zirCall(...@@ -6519,10 +6574,10 @@ fn zirCall(
6519 if (arg_index >= fn_params_len)6574 if (arg_index >= fn_params_len)
6520 break :inst Air.Inst.Ref.var_args_param_type;6575 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)
6523 break :inst Air.Inst.Ref.generic_poison_type;6578 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());
6526 });6581 });
65276582
6528 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);6583 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
...@@ -6535,7 +6590,9 @@ fn zirCall(...@@ -6535,7 +6590,9 @@ fn zirCall(
6535 }6590 }
6536 resolved_args[arg_index] = resolved;6591 resolved_args[arg_index] = resolved;
6537 }6592 }
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 {
6539 input_is_error = false; // input was an error type, but no errorable fn's were actually called6596 input_is_error = false; // input was an error type, but no errorable fn's were actually called
6540 }6597 }
65416598
...@@ -6702,6 +6759,7 @@ fn analyzeCall(...@@ -6702,6 +6759,7 @@ fn analyzeCall(
6702 call_dbg_node: ?Zir.Inst.Index,6759 call_dbg_node: ?Zir.Inst.Index,
6703) CompileError!Air.Inst.Ref {6760) CompileError!Air.Inst.Ref {
6704 const mod = sema.mod;6761 const mod = sema.mod;
6762 const ip = &mod.intern_pool;
67056763
6706 const callee_ty = sema.typeOf(func);6764 const callee_ty = sema.typeOf(func);
6707 const func_ty_info = mod.typeToFunc(func_ty).?;6765 const func_ty_info = mod.typeToFunc(func_ty).?;
...@@ -6749,20 +6807,17 @@ fn analyzeCall(...@@ -6749,20 +6807,17 @@ fn analyzeCall(
67496807
6750 var is_generic_call = func_ty_info.is_generic;6808 var is_generic_call = func_ty_info.is_generic;
6751 var is_comptime_call = block.is_comptime or modifier == .compile_time;6809 var is_comptime_call = block.is_comptime or modifier == .compile_time;
6752 var comptime_reason_buf: Block.ComptimeReason = undefined;
6753 var comptime_reason: ?*const Block.ComptimeReason = null;6810 var comptime_reason: ?*const Block.ComptimeReason = null;
6754 if (!is_comptime_call) {6811 if (!is_comptime_call) {
6755 if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| {6812 if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| {
6756 is_comptime_call = ct;6813 is_comptime_call = ct;
6757 if (ct) {6814 if (ct) {
6758 // stage1 can't handle doing this directly6815 comptime_reason = &.{ .comptime_ret_ty = .{
6759 comptime_reason_buf = .{ .comptime_ret_ty = .{
6760 .block = block,6816 .block = block,
6761 .func = func,6817 .func = func,
6762 .func_src = func_src,6818 .func_src = func_src,
6763 .return_ty = func_ty_info.return_type.toType(),6819 .return_ty = func_ty_info.return_type.toType(),
6764 } };6820 } };
6765 comptime_reason = &comptime_reason_buf;
6766 }6821 }
6767 } else |err| switch (err) {6822 } else |err| switch (err) {
6768 error.GenericPoison => is_generic_call = true,6823 error.GenericPoison => is_generic_call = true,
...@@ -6778,7 +6833,6 @@ fn analyzeCall(...@@ -6778,7 +6833,6 @@ fn analyzeCall(
6778 func,6833 func,
6779 func_src,6834 func_src,
6780 call_src,6835 call_src,
6781 func_ty,
6782 ensure_result_used,6836 ensure_result_used,
6783 uncasted_args,6837 uncasted_args,
6784 call_tag,6838 call_tag,
...@@ -6793,14 +6847,12 @@ fn analyzeCall(...@@ -6793,14 +6847,12 @@ fn analyzeCall(
6793 error.ComptimeReturn => {6847 error.ComptimeReturn => {
6794 is_inline_call = true;6848 is_inline_call = true;
6795 is_comptime_call = true;6849 is_comptime_call = true;
6796 // stage1 can't handle doing this directly6850 comptime_reason = &.{ .comptime_ret_ty = .{
6797 comptime_reason_buf = .{ .comptime_ret_ty = .{
6798 .block = block,6851 .block = block,
6799 .func = func,6852 .func = func,
6800 .func_src = func_src,6853 .func_src = func_src,
6801 .return_ty = func_ty_info.return_type.toType(),6854 .return_ty = func_ty_info.return_type.toType(),
6802 } };6855 } };
6803 comptime_reason = &comptime_reason_buf;
6804 },6856 },
6805 else => |e| return e,6857 else => |e| return e,
6806 }6858 }
...@@ -6819,9 +6871,9 @@ fn analyzeCall(...@@ -6819,9 +6871,9 @@ fn analyzeCall(
6819 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{6871 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
6820 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),6872 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
6821 }),6873 }),
6822 .func => |function| function.index,6874 .func => func_val.toIntern(),
6823 .ptr => |ptr| switch (ptr.addr) {6875 .ptr => |ptr| switch (ptr.addr) {
6824 .decl => |decl| mod.declPtr(decl).val.getFunctionIndex(mod).unwrap().?,6876 .decl => |decl| mod.declPtr(decl).val.toIntern(),
6825 else => {6877 else => {
6826 assert(callee_ty.isPtrAtRuntime(mod));6878 assert(callee_ty.isPtrAtRuntime(mod));
6827 return sema.fail(block, call_src, "{s} call of function pointer", .{6879 return sema.fail(block, call_src, "{s} call of function pointer", .{
...@@ -6850,7 +6902,7 @@ fn analyzeCall(...@@ -6850,7 +6902,7 @@ fn analyzeCall(
6850 // This one is shared among sub-blocks within the same callee, but not6902 // This one is shared among sub-blocks within the same callee, but not
6851 // shared among the entire inline/comptime call stack.6903 // shared among the entire inline/comptime call stack.
6852 var inlining: Block.Inlining = .{6904 var inlining: Block.Inlining = .{
6853 .func = null,6905 .func = .none,
6854 .comptime_result = undefined,6906 .comptime_result = undefined,
6855 .merges = .{6907 .merges = .{
6856 .src_locs = .{},6908 .src_locs = .{},
...@@ -6862,7 +6914,7 @@ fn analyzeCall(...@@ -6862,7 +6914,7 @@ fn analyzeCall(
6862 // In order to save a bit of stack space, directly modify Sema rather6914 // In order to save a bit of stack space, directly modify Sema rather
6863 // than create a child one.6915 // than create a child one.
6864 const parent_zir = sema.code;6916 const parent_zir = sema.code;
6865 const module_fn = mod.funcPtr(module_fn_index);6917 const module_fn = mod.funcInfo(module_fn_index);
6866 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);6918 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
6867 sema.code = fn_owner_decl.getFileScope(mod).zir;6919 sema.code = fn_owner_decl.getFileScope(mod).zir;
6868 defer sema.code = parent_zir;6920 defer sema.code = parent_zir;
...@@ -6877,11 +6929,8 @@ fn analyzeCall(...@@ -6877,11 +6929,8 @@ fn analyzeCall(
6877 sema.inst_map = parent_inst_map;6929 sema.inst_map = parent_inst_map;
6878 }6930 }
68796931
6880 const parent_func = sema.func;
6881 const parent_func_index = sema.func_index;6932 const parent_func_index = sema.func_index;
6882 sema.func = module_fn;6933 sema.func_index = module_fn_index;
6883 sema.func_index = module_fn_index.toOptional();
6884 defer sema.func = parent_func;
6885 defer sema.func_index = parent_func_index;6934 defer sema.func_index = parent_func_index;
68866935
6887 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;6936 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
...@@ -6913,16 +6962,28 @@ fn analyzeCall(...@@ -6913,16 +6962,28 @@ fn analyzeCall(
69136962
6914 try sema.emitBackwardBranch(block, call_src);6963 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.
6917 var should_memoize = true;6967 var should_memoize = true;
69186968
6919 // If it's a comptime function call, we need to memoize it as long as no external6969 // If it's a comptime function call, we need to memoize it as long as no external
6920 // comptime memory is mutated.6970 // comptime memory is mutated.
6921 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);6971 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).?;6973 const owner_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);6974 var new_fn_info: InternPool.GetFuncTypeKey = .{
6925 new_fn_info.comptime_bits = 0;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
6927 // This will have return instructions analyzed as break instructions to6988 // This will have return instructions analyzed as break instructions to
6928 // the block_inst above. Here we are performing "comptime/inline semantic analysis"6989 // the block_inst above. Here we are performing "comptime/inline semantic analysis"
...@@ -6934,59 +6995,46 @@ fn analyzeCall(...@@ -6934,59 +6995,46 @@ fn analyzeCall(
6934 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body);6995 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body);
69356996
6936 var has_comptime_args = false;6997 var has_comptime_args = false;
6937 var arg_i: usize = 0;6998 var arg_i: u32 = 0;
6938 for (fn_info.param_body) |inst| {6999 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(
6940 block,7009 block,
6941 &child_block,7010 &child_block,
6942 .unneeded,7011 arg_src,
6943 inst,7012 inst,
6944 &new_fn_info,7013 new_fn_info.param_types,
6945 &arg_i,7014 &arg_i,
6946 uncasted_args,7015 uncasted_args,
6947 is_comptime_call,7016 is_comptime_call,
6948 &should_memoize,7017 &should_memoize,
6949 memoized_arg_values,7018 memoized_arg_values,
6950 mod.typeToFunc(func_ty).?.param_types,7019 func_ty_info.param_types,
6951 func,7020 func,
6952 &has_comptime_args,7021 &has_comptime_args,
6953 ) catch |err| switch (err) {7022 );
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 };
6976 }7023 }
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
6980 const recursive_msg = "inline call is recursive";7028 const recursive_msg = "inline call is recursive";
6981 var head = if (!has_comptime_args) block else null;7029 var head = if (!has_comptime_args) block else null;
6982 while (head) |some| {7030 while (head) |some| {
6983 const parent_inlining = some.inlining orelse break;7031 const parent_inlining = some.inlining orelse break;
6984 if (parent_inlining.func == module_fn) {7032 if (parent_inlining.func == module_fn_index) {
6985 return sema.fail(block, call_src, recursive_msg, .{});7033 return sema.fail(block, call_src, recursive_msg, .{});
6986 }7034 }
6987 head = some.parent;7035 head = some.parent;
6988 }7036 }
6989 if (!has_comptime_args) inlining.func = module_fn;7037 if (!has_comptime_args) inlining.func = module_fn_index;
69907038
6991 // In case it is a generic function with an expression for the return type that depends7039 // In case it is a generic function with an expression for the return type that depends
6992 // on parameters, we must now do the same for the return type as we just did with7040 // on parameters, we must now do the same for the return type as we just did with
...@@ -6998,21 +7046,32 @@ fn analyzeCall(...@@ -6998,21 +7046,32 @@ fn analyzeCall(
6998 try sema.resolveInst(fn_info.ret_ty_ref);7046 try sema.resolveInst(fn_info.ret_ty_ref);
6999 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };7047 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
7000 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);7048 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();
7013 const parent_fn_ret_ty = sema.fn_ret_ty;7049 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;
7015 defer sema.fn_ret_ty = parent_fn_ret_ty;7059 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
7017 // This `res2` is here instead of directly breaking from `res` due to a stage17076 // This `res2` is here instead of directly breaking from `res` due to a stage1
7018 // bug generating invalid LLVM IR.7077 // bug generating invalid LLVM IR.
...@@ -7030,9 +7089,10 @@ fn analyzeCall(...@@ -7030,9 +7089,10 @@ fn analyzeCall(
7030 }7089 }
7031 }7090 }
70327091
7092 new_fn_info.return_type = sema.fn_ret_ty.toIntern();
7033 const new_func_resolved_ty = try mod.funcType(new_fn_info);7093 const new_func_resolved_ty = try mod.funcType(new_fn_info);
7034 if (!is_comptime_call and !block.is_typeof) {7094 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
7037 const zir_tags = sema.code.instructions.items(.tag);7097 const zir_tags = sema.code.instructions.items(.tag);
7038 for (fn_info.param_body) |param| switch (zir_tags[param]) {7098 for (fn_info.param_body) |param| switch (zir_tags[param]) {
...@@ -7056,7 +7116,7 @@ fn analyzeCall(...@@ -7056,7 +7116,7 @@ fn analyzeCall(
7056 }7116 }
70577117
7058 if (is_comptime_call and ensure_result_used) {7118 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);
7060 }7120 }
70617121
7062 const result = result: {7122 const result = result: {
...@@ -7074,26 +7134,47 @@ fn analyzeCall(...@@ -7074,26 +7134,47 @@ fn analyzeCall(
7074 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);7134 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);
7075 };7135 };
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 {
7078 try sema.emitDbgInline(7140 try sema.emitDbgInline(
7079 block,7141 block,
7080 module_fn_index,7142 module_fn_index,
7081 parent_func_index.unwrap().?,7143 parent_func_index,
7082 mod.declPtr(parent_func.?.owner_decl).ty,7144 mod.funcOwnerDeclPtr(parent_func_index).ty,
7083 .dbg_inline_end,7145 .dbg_inline_end,
7084 );7146 );
7085 }7147 }
70867148
7087 if (should_memoize and is_comptime_call) {7149 if (should_memoize and is_comptime_call) {
7088 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");7150 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
7090 // TODO: check whether any external comptime memory was mutated by the7156 // TODO: check whether any external comptime memory was mutated by the
7091 // comptime function call. If so, then do not memoize the call here.7157 // comptime function call. If so, then do not memoize the call here.
7092 _ = try mod.intern(.{ .memoized_call = .{7158 _ = try mod.intern(.{ .memoized_call = .{
7093 .func = module_fn_index,7159 .func = module_fn_index,
7094 .arg_values = memoized_arg_values,7160 .arg_values = memoized_arg_values,
7095 .result = try result_val.intern(fn_ret_ty, mod),7161 .result = result_transformed,
7096 } });7162 } });
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);
7097 }7178 }
70987179
7099 break :res2 result;7180 break :res2 result;
...@@ -7110,9 +7191,9 @@ fn analyzeCall(...@@ -7110,9 +7191,9 @@ fn analyzeCall(
7110 if (i < fn_params_len) {7191 if (i < fn_params_len) {
7111 const opts: CoerceOpts = .{ .param_src = .{7192 const opts: CoerceOpts = .{ .param_src = .{
7112 .func_inst = func,7193 .func_inst = func,
7113 .param_i = @as(u32, @intCast(i)),7194 .param_i = @intCast(i),
7114 } };7195 } };
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();
7116 args[i] = sema.analyzeCallArg(7197 args[i] = sema.analyzeCallArg(
7117 block,7198 block,
7118 .unneeded,7199 .unneeded,
...@@ -7152,13 +7233,13 @@ fn analyzeCall(...@@ -7152,13 +7233,13 @@ fn analyzeCall(
7152 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);7233 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
71537234
7154 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());7235 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7155 if (sema.owner_func != null and func_ty_info.return_type.toType().isError(mod)) {7236 if (sema.owner_func_index != .none and func_ty_info.return_type.toType().isError(mod)) {
7156 sema.owner_func.?.calls_or_awaits_errorable_fn = true;7237 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
7157 }7238 }
71587239
7159 if (try sema.resolveMaybeUndefVal(func)) |func_val| {7240 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7160 if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| {7241 if (mod.intern_pool.isFuncBody(func_val.toIntern())) {
7161 try mod.ensureFuncBodyAnalysisQueued(func_index);7242 try mod.ensureFuncBodyAnalysisQueued(func_val.toIntern());
7162 }7243 }
7163 }7244 }
71647245
...@@ -7219,7 +7300,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ...@@ -7219,7 +7300,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
7219 @tagName(backend), @tagName(target.cpu.arch),7300 @tagName(backend), @tagName(target.cpu.arch),
7220 });7301 });
7221 }7302 }
7222 const func_decl = mod.declPtr(sema.owner_func.?.owner_decl);7303 const func_decl = mod.funcOwnerDeclPtr(sema.owner_func_index);
7223 if (!func_ty.eql(func_decl.ty, mod)) {7304 if (!func_ty.eql(func_decl.ty, mod)) {
7224 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{7305 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{
7225 func_ty.fmt(mod), func_decl.ty.fmt(mod),7306 func_ty.fmt(mod), func_decl.ty.fmt(mod),
...@@ -7235,17 +7316,18 @@ fn analyzeInlineCallArg(...@@ -7235,17 +7316,18 @@ fn analyzeInlineCallArg(
7235 param_block: *Block,7316 param_block: *Block,
7236 arg_src: LazySrcLoc,7317 arg_src: LazySrcLoc,
7237 inst: Zir.Inst.Index,7318 inst: Zir.Inst.Index,
7238 new_fn_info: *InternPool.Key.FuncType,7319 new_param_types: []InternPool.Index,
7239 arg_i: *usize,7320 arg_i: *u32,
7240 uncasted_args: []const Air.Inst.Ref,7321 uncasted_args: []const Air.Inst.Ref,
7241 is_comptime_call: bool,7322 is_comptime_call: bool,
7242 should_memoize: *bool,7323 should_memoize: *bool,
7243 memoized_arg_values: []InternPool.Index,7324 memoized_arg_values: []InternPool.Index,
7244 raw_param_types: []const InternPool.Index,7325 raw_param_types: InternPool.Index.Slice,
7245 func_inst: Air.Inst.Ref,7326 func_inst: Air.Inst.Ref,
7246 has_comptime_args: *bool,7327 has_comptime_args: *bool,
7247) !void {7328) !void {
7248 const mod = sema.mod;7329 const mod = sema.mod;
7330 const ip = &mod.intern_pool;
7249 const zir_tags = sema.code.instructions.items(.tag);7331 const zir_tags = sema.code.instructions.items(.tag);
7250 switch (zir_tags[inst]) {7332 switch (zir_tags[inst]) {
7251 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,7333 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
...@@ -7260,13 +7342,13 @@ fn analyzeInlineCallArg(...@@ -7260,13 +7342,13 @@ fn analyzeInlineCallArg(
7260 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);7342 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);
7261 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];7343 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
7262 const param_ty = param_ty: {7344 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.*];
7264 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;7346 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;
7265 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);7347 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
7266 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);7348 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
7267 break :param_ty param_ty.toIntern();7349 break :param_ty param_ty.toIntern();
7268 };7350 };
7269 new_fn_info.param_types[arg_i.*] = param_ty;7351 new_param_types[arg_i.*] = param_ty;
7270 const uncasted_arg = uncasted_args[arg_i.*];7352 const uncasted_arg = uncasted_args[arg_i.*];
7271 if (try sema.typeRequiresComptime(param_ty.toType())) {7353 if (try sema.typeRequiresComptime(param_ty.toType())) {
7272 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {7354 _ = 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(...@@ -7278,7 +7360,7 @@ fn analyzeInlineCallArg(
7278 }7360 }
7279 const casted_arg = sema.coerceExtra(arg_block, param_ty.toType(), uncasted_arg, arg_src, .{ .param_src = .{7361 const casted_arg = sema.coerceExtra(arg_block, param_ty.toType(), uncasted_arg, arg_src, .{ .param_src = .{
7280 .func_inst = func_inst,7362 .func_inst = func_inst,
7281 .param_i = @as(u32, @intCast(arg_i.*)),7363 .param_i = @intCast(arg_i.*),
7282 } }) catch |err| switch (err) {7364 } }) catch |err| switch (err) {
7283 error.NotCoercible => unreachable,7365 error.NotCoercible => unreachable,
7284 else => |e| return e,7366 else => |e| return e,
...@@ -7317,7 +7399,7 @@ fn analyzeInlineCallArg(...@@ -7317,7 +7399,7 @@ fn analyzeInlineCallArg(
7317 .param_anytype, .param_anytype_comptime => {7399 .param_anytype, .param_anytype_comptime => {
7318 // No coercion needed.7400 // No coercion needed.
7319 const uncasted_arg = uncasted_args[arg_i.*];7401 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
7322 if (is_comptime_call) {7404 if (is_comptime_call) {
7323 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);7405 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
...@@ -7371,50 +7453,12 @@ fn analyzeCallArg(...@@ -7371,50 +7453,12 @@ fn analyzeCallArg(
7371 };7453 };
7372}7454}
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
7411fn instantiateGenericCall(7456fn instantiateGenericCall(
7412 sema: *Sema,7457 sema: *Sema,
7413 block: *Block,7458 block: *Block,
7414 func: Air.Inst.Ref,7459 func: Air.Inst.Ref,
7415 func_src: LazySrcLoc,7460 func_src: LazySrcLoc,
7416 call_src: LazySrcLoc,7461 call_src: LazySrcLoc,
7417 generic_func_ty: Type,
7418 ensure_result_used: bool,7462 ensure_result_used: bool,
7419 uncasted_args: []const Air.Inst.Ref,7463 uncasted_args: []const Air.Inst.Ref,
7420 call_tag: Air.Inst.Tag,7464 call_tag: Air.Inst.Tag,
...@@ -7423,299 +7467,32 @@ fn instantiateGenericCall(...@@ -7423,299 +7467,32 @@ fn instantiateGenericCall(
7423) CompileError!Air.Inst.Ref {7467) CompileError!Air.Inst.Ref {
7424 const mod = sema.mod;7468 const mod = sema.mod;
7425 const gpa = sema.gpa;7469 const gpa = sema.gpa;
7470 const ip = &mod.intern_pool;
74267471
7427 const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");7472 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())) {7473 const generic_owner = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7429 .func => |function| function.index,7474 .func => func_val.toIntern(),
7430 .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.getFunctionIndex(mod).unwrap().?,7475 .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.toIntern(),
7431 else => unreachable,7476 else => unreachable,
7432 };7477 };
7433 const module_fn = mod.funcPtr(module_fn_index);7478 const generic_owner_func = mod.intern_pool.indexToKey(generic_owner).func;
7434 // Check the Module's generic function map with an adapted context, so that we7479
7435 // can match against `uncasted_args` rather than doing the work below to create a7480 // Even though there may already be a generic instantiation corresponding
7436 // generic Scope only to junk it if it matches an existing instantiation.7481 // to this callsite, we must evaluate the expressions of the generic
7437 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);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);
7438 const namespace_index = fn_owner_decl.src_namespace;7489 const namespace_index = fn_owner_decl.src_namespace;
7439 const namespace = mod.namespacePtr(namespace_index);7490 const namespace = mod.namespacePtr(namespace_index);
7440 const fn_zir = namespace.file_scope.zir;7491 const fn_zir = namespace.file_scope.zir;
7441 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);7492 const fn_info = fn_zir.getFnInfo(generic_owner_func.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;
74747493
7475 if (known_unique) {7494 const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len);
7476 if (is_comptime or is_anytype or is_generic) {7495 @memset(comptime_args, .none);
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);
77197496
7720 // Re-run the block that creates the function, with the comptime parameters7497 // Re-run the block that creates the function, with the comptime parameters
7721 // pre-populated inside `inst_map`. This causes `param_comptime` and7498 // pre-populated inside `inst_map`. This causes `param_comptime` and
...@@ -7726,205 +7503,145 @@ fn resolveGenericInstantiationType(...@@ -7726,205 +7503,145 @@ fn resolveGenericInstantiationType(
7726 .gpa = gpa,7503 .gpa = gpa,
7727 .arena = sema.arena,7504 .arena = sema.arena,
7728 .code = fn_zir,7505 .code = fn_zir,
7729 .owner_decl = new_decl,7506 // We pass the generic callsite's owner decl here because whatever `Decl`
7730 .owner_decl_index = new_decl_index,7507 // dependencies are chased at this point should be attached to the
7731 .func = null,7508 // callsite, not the `Decl` associated with the `func_instance`.
7732 .func_index = .none,7509 .owner_decl = sema.owner_decl,
7510 .owner_decl_index = sema.owner_decl_index,
7511 .func_index = sema.owner_func_index,
7733 .fn_ret_ty = Type.void,7512 .fn_ret_ty = Type.void,
7734 .owner_func = null,7513 .fn_ret_ty_ies = null,
7735 .owner_func_index = .none,7514 .owner_func_index = .none,
7736 // TODO: fully migrate functions into InternPool7515 .comptime_args = comptime_args,
7737 .comptime_args = try mod.tmp_hack_arena.allocator().alloc(TypedValue, uncasted_args.len),7516 .generic_owner = generic_owner,
7738 .comptime_args_fn_inst = module_fn.zir_body_inst,7517 .generic_call_src = call_src,
7739 .preallocated_new_func = new_module_func.toOptional(),7518 .generic_call_decl = block.src_decl.toOptional(),
7740 .is_generic_instantiation = true,
7741 .branch_quota = sema.branch_quota,7519 .branch_quota = sema.branch_quota,
7742 .branch_count = sema.branch_count,7520 .branch_count = sema.branch_count,
7743 .comptime_mutable_decls = sema.comptime_mutable_decls,7521 .comptime_mutable_decls = sema.comptime_mutable_decls,
7744 };7522 };
7745 defer child_sema.deinit();7523 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);
7748 defer wip_captures.deinit();7526 defer wip_captures.deinit();
77497527
7750 var child_block: Block = .{7528 var child_block: Block = .{
7751 .parent = null,7529 .parent = null,
7752 .sema = &child_sema,7530 .sema = &child_sema,
7753 .src_decl = new_decl_index,7531 .src_decl = generic_owner_func.owner_decl,
7754 .namespace = namespace,7532 .namespace = namespace_index,
7755 .wip_capture_scope = wip_captures.scope,7533 .wip_capture_scope = wip_captures.scope,
7756 .instructions = .{},7534 .instructions = .{},
7757 .inlining = null,7535 .inlining = null,
7758 .is_comptime = true,7536 .is_comptime = true,
7759 };7537 };
7760 defer {7538 defer child_block.instructions.deinit(gpa);
7761 child_block.instructions.deinit(gpa);
7762 child_block.params.deinit(gpa);
7763 }
77647539
7765 try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);7540 try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
77667541
7767 var arg_i: usize = 0;7542 for (fn_info.param_body[0..uncasted_args.len], uncasted_args, 0..) |inst, arg, i| {
7768 for (fn_info.param_body) |inst| {7543 // `child_sema` will use a different `inst_map` which means we have to
7769 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;7544 // convert from parent-relative `Air.Inst.Ref` to child-relative here.
7770 var is_comptime = false;7545 // Constants are simple; runtime-known values need a new instruction.
7771 var is_anytype = false;7546 child_sema.inst_map.putAssumeCapacityNoClobber(inst, if (try sema.resolveMaybeUndefVal(arg)) |val|
7772 switch (zir_tags[inst]) {7547 Air.internedToRef(val.toIntern())
7773 .param => {7548 else
7774 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));7549 // We insert into the map an instruction which is runtime-known
7775 },7550 // but has the type of the argument.
7776 .param_comptime => {7551 try child_block.addInst(.{
7777 is_comptime = true;7552 .tag = .arg,
7778 },7553 .data = .{ .arg = .{
7779 .param_anytype => {7554 .ty = Air.internedToRef(sema.typeOf(arg).toIntern()),
7780 is_anytype = true;7555 .src_index = @intCast(i),
7781 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));7556 } },
7782 },7557 }));
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;
7822 }7558 }
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
7830 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);7560 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;7561 const callee_index = (child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern();
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;
78657562
7866 const arg = child_sema.inst_map.get(inst).?;7563 const callee = mod.funcInfo(callee_index);
7867 const arg_ty = child_sema.typeOf(arg);7564 callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota);
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 }
78887565
7889 arg_i += 1;7566 // Make a runtime call to the new function, making sure to omit the comptime args.
7890 }7567 const func_ty = callee.ty.toType();
7568 const func_ty_info = mod.typeToFunc(func_ty).?;
78917569
7892 try wip_captures.finalize();7570 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);
7896 // If the call evaluated to a return type that requires comptime, never mind7572 // If the call evaluated to a return type that requires comptime, never mind
7897 // our generic instantiation. Instead we need to perform a comptime call.7573 // our generic instantiation. Instead we need to perform a comptime call.
7898 const new_fn_info = mod.typeToFunc(new_decl.ty).?;7574 if (try sema.typeRequiresComptime(func_ty_info.return_type.toType())) {
7899 if (try sema.typeRequiresComptime(new_fn_info.return_type.toType())) {
7900 return error.ComptimeReturn;7575 return error.ComptimeReturn;
7901 }7576 }
7902 // Similarly, if the call evaluated to a generic type we need to instead7577 // Similarly, if the call evaluated to a generic type we need to instead
7903 // call it inline.7578 // 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) {
7905 return error.GenericPoison;7580 return error.GenericPoison;
7906 }7581 }
79077582
7908 new_decl.val = (try mod.intern(.{ .func = .{7583 const runtime_args_len: u32 = func_ty_info.param_types.len;
7909 .ty = new_decl.ty.toIntern(),7584 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
7910 .index = new_func,7585 {
7911 } })).toValue();7586 var runtime_i: u32 = 0;
7912 new_decl.alignment = .none;7587 for (uncasted_args, 0..) |uncasted_arg, total_i| {
7913 new_decl.has_tv = true;7588 // In the case of a function call generated by the language, the LazySrcLoc
7914 new_decl.owns_tv = true;7589 // provided for `call_src` may not point to anything interesting.
7915 new_decl.analysis = .complete;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(.{7613 if (sema.owner_func_index != .none and
7918 .func = module_fn_index,7614 func_ty_info.return_type.toType().isError(mod))
7919 .args_index = monomorphed_args_index,7615 {
7920 .args_len = monomorphed_arg_i,7616 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
7921 }, new_decl.val.toIntern(), .{ .mod = mod });7617 }
7618
7619 try mod.ensureFuncBodyAnalysisQueued(callee_index);
79227620
7923 // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field7621 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
7924 // will be populated, ensuring it will have `analyzeBody` called with the ZIR7622 runtime_args_len);
7925 // parameters mapped appropriately.7623 const result = try block.addInst(.{
7926 try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func });7624 .tag = call_tag,
7927 return new_func;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;
7928}7645}
79297646
7930fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {7647fn 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)...@@ -7944,8 +7661,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
7944fn emitDbgInline(7661fn emitDbgInline(
7945 sema: *Sema,7662 sema: *Sema,
7946 block: *Block,7663 block: *Block,
7947 old_func: Module.Fn.Index,7664 old_func: InternPool.Index,
7948 new_func: Module.Fn.Index,7665 new_func: InternPool.Index,
7949 new_func_ty: Type,7666 new_func_ty: Type,
7950 tag: Air.Inst.Tag,7667 tag: Air.Inst.Tag,
7951) CompileError!void {7668) CompileError!void {
...@@ -8149,6 +7866,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8149,6 +7866,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8149 defer tracy.end();7866 defer tracy.end();
81507867
8151 const mod = sema.mod;7868 const mod = sema.mod;
7869 const ip = &mod.intern_pool;
8152 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;7870 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
8153 const src = LazySrcLoc.nodeOffset(extra.node);7871 const src = LazySrcLoc.nodeOffset(extra.node);
8154 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };7872 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...@@ -8159,7 +7877,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8159 if (val.isUndef(mod)) {7877 if (val.isUndef(mod)) {
8160 return sema.addConstUndef(Type.err_int);7878 return sema.addConstUndef(Type.err_int);
8161 }7879 }
8162 const err_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;7880 const err_name = ip.indexToKey(val.toIntern()).err.name;
8163 return sema.addConstant(try mod.intValue(7881 return sema.addConstant(try mod.intValue(
8164 Type.err_int,7882 Type.err_int,
8165 try mod.getErrorValue(err_name),7883 try mod.getErrorValue(err_name),
...@@ -8167,17 +7885,19 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8167,17 +7885,19 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8167 }7885 }
81687886
8169 const op_ty = sema.typeOf(uncasted_operand);7887 const op_ty = sema.typeOf(uncasted_operand);
8170 try sema.resolveInferredErrorSetTy(block, src, op_ty);7888 switch (try sema.resolveInferredErrorSetTy(block, src, op_ty.toIntern())) {
8171 if (!op_ty.isAnyError(mod)) {7889 .anyerror_type => {},
8172 const names = op_ty.errorSetNames(mod);7890 else => |err_set_ty_index| {
8173 switch (names.len) {7891 const names = ip.indexToKey(err_set_ty_index).error_set_type.names;
8174 0 => return sema.addConstant(try mod.intValue(Type.err_int, 0)),7892 switch (names.len) {
8175 1 => {7893 0 => return sema.addConstant(try mod.intValue(Type.err_int, 0)),
8176 const int = @as(Module.ErrorInt, @intCast(mod.global_error_set.getIndex(names[0]).?));7894 1 => {
8177 return sema.addIntUnsigned(Type.err_int, int);7895 const int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[0]).?);
8178 },7896 return sema.addIntUnsigned(Type.err_int, int);
8179 else => {},7897 },
8180 }7898 else => {},
7899 }
7900 },
8181 }7901 }
81827902
8183 try sema.requireRuntimeBlock(block, src, operand_src);7903 try sema.requireRuntimeBlock(block, src, operand_src);
...@@ -8226,6 +7946,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -8226,6 +7946,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8226 defer tracy.end();7946 defer tracy.end();
82277947
8228 const mod = sema.mod;7948 const mod = sema.mod;
7949 const ip = &mod.intern_pool;
8229 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;7950 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
8230 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;7951 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
8231 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };7952 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...@@ -8254,23 +7975,25 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
8254 return Air.Inst.Ref.anyerror_type;7975 return Air.Inst.Ref.anyerror_type;
8255 }7976 }
82567977
8257 if (mod.typeToInferredErrorSetIndex(lhs_ty).unwrap()) |ies_index| {7978 if (ip.isInferredErrorSetType(lhs_ty.toIntern())) {
8258 try sema.resolveInferredErrorSet(block, src, ies_index);7979 switch (try sema.resolveInferredErrorSet(block, src, lhs_ty.toIntern())) {
8259 // isAnyError might have changed from a false negative to a true positive after resolution.7980 // isAnyError might have changed from a false negative to a true
8260 if (lhs_ty.isAnyError(mod)) {7981 // positive after resolution.
8261 return Air.Inst.Ref.anyerror_type;7982 .anyerror_type => return .anyerror_type,
7983 else => {},
8262 }7984 }
8263 }7985 }
8264 if (mod.typeToInferredErrorSetIndex(rhs_ty).unwrap()) |ies_index| {7986 if (ip.isInferredErrorSetType(rhs_ty.toIntern())) {
8265 try sema.resolveInferredErrorSet(block, src, ies_index);7987 switch (try sema.resolveInferredErrorSet(block, src, rhs_ty.toIntern())) {
8266 // isAnyError might have changed from a false negative to a true positive after resolution.7988 // isAnyError might have changed from a false negative to a true
8267 if (rhs_ty.isAnyError(mod)) {7989 // positive after resolution.
8268 return Air.Inst.Ref.anyerror_type;7990 .anyerror_type => return .anyerror_type,
7991 else => {},
8269 }7992 }
8270 }7993 }
82717994
8272 const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty);7995 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());
8274}7997}
82757998
8276fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {7999fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -8747,9 +8470,7 @@ fn zirFunc(...@@ -8747,9 +8470,7 @@ fn zirFunc(
8747 inst: Zir.Inst.Index,8470 inst: Zir.Inst.Index,
8748 inferred_error_set: bool,8471 inferred_error_set: bool,
8749) CompileError!Air.Inst.Ref {8472) CompileError!Air.Inst.Ref {
8750 const tracy = trace(@src());8473 const mod = sema.mod;
8751 defer tracy.end();
8752
8753 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;8474 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
8754 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);8475 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
8755 const target = sema.mod.getTarget();8476 const target = sema.mod.getTarget();
...@@ -8790,8 +8511,7 @@ fn zirFunc(...@@ -8790,8 +8511,7 @@ fn zirFunc(
8790 // If this instruction has a body it means it's the type of the `owner_decl`8511 // If this instruction has a body it means it's the type of the `owner_decl`
8791 // otherwise it's a function type without a `callconv` attribute and should8512 // otherwise it's a function type without a `callconv` attribute and should
8792 // never be `.C`.8513 // never be `.C`.
8793 // NOTE: revisit when doing #17178514 const cc: std.builtin.CallingConvention = if (has_body and mod.declPtr(block.src_decl).is_exported)
8794 const cc: std.builtin.CallingConvention = if (sema.owner_decl.is_exported and has_body)
8795 .C8515 .C
8796 else8516 else
8797 .Unspecified;8517 .Unspecified;
...@@ -8802,7 +8522,7 @@ fn zirFunc(...@@ -8802,7 +8522,7 @@ fn zirFunc(
8802 inst,8522 inst,
8803 .none,8523 .none,
8804 target_util.defaultAddressSpace(target, .function),8524 target_util.defaultAddressSpace(target, .function),
8805 FuncLinkSection.default,8525 .default,
8806 cc,8526 cc,
8807 ret_ty,8527 ret_ty,
8808 false,8528 false,
...@@ -8830,10 +8550,21 @@ fn resolveGenericBody(...@@ -8830,10 +8550,21 @@ fn resolveGenericBody(
8830 const err = err: {8550 const err = err: {
8831 // Make sure any nested param instructions don't clobber our work.8551 // Make sure any nested param instructions don't clobber our work.
8832 const prev_params = block.params;8552 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;
8833 block.params = .{};8557 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;
8834 defer {8562 defer {
8835 block.params.deinit(sema.gpa);
8836 block.params = prev_params;8563 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;
8837 }8568 }
88388569
8839 const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err;8570 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:...@@ -8952,7 +8683,7 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
8952 }8683 }
8953}8684}
89548685
8955const FuncLinkSection = union(enum) {8686const Section = union(enum) {
8956 generic,8687 generic,
8957 default,8688 default,
8958 explicit: InternPool.NullTerminatedString,8689 explicit: InternPool.NullTerminatedString,
...@@ -8967,8 +8698,7 @@ fn funcCommon(...@@ -8967,8 +8698,7 @@ fn funcCommon(
8967 alignment: ?Alignment,8698 alignment: ?Alignment,
8968 /// null means generic poison8699 /// null means generic poison
8969 address_space: ?std.builtin.AddressSpace,8700 address_space: ?std.builtin.AddressSpace,
8970 /// outer null means generic poison; inner null means default link section8701 section: Section,
8971 section: FuncLinkSection,
8972 /// null means generic poison8702 /// null means generic poison
8973 cc: ?std.builtin.CallingConvention,8703 cc: ?std.builtin.CallingConvention,
8974 /// this might be Type.generic_poison8704 /// this might be Type.generic_poison
...@@ -8984,6 +8714,8 @@ fn funcCommon(...@@ -8984,6 +8714,8 @@ fn funcCommon(
8984) CompileError!Air.Inst.Ref {8714) CompileError!Air.Inst.Ref {
8985 const mod = sema.mod;8715 const mod = sema.mod;
8986 const gpa = sema.gpa;8716 const gpa = sema.gpa;
8717 const target = mod.getTarget();
8718 const ip = &mod.intern_pool;
8987 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };8719 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
8988 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };8720 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };
8989 const func_src = LazySrcLoc.nodeOffset(src_node_offset);8721 const func_src = LazySrcLoc.nodeOffset(src_node_offset);
...@@ -9001,226 +8733,150 @@ fn funcCommon(...@@ -9001,226 +8733,150 @@ fn funcCommon(
9001 try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?);8733 try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?);
9002 }8734 }
90038735
9004 var destroy_fn_on_error = false;8736 const is_source_decl = sema.generic_owner == .none;
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);
90208737
9021 const target = mod.getTarget();8738 // In the case of generic calling convention, or generic alignment, we use
9022 const fn_ty: Type = fn_ty: {8739 // default values which are only meaningful for the generic function, *not*
9023 // In the case of generic calling convention, or generic alignment, we use8740 // the instantiation, which can depend on comptime parameters.
9024 // default values which are only meaningful for the generic function, *not*8741 // Related proposal: https://github.com/ziglang/zig/issues/11834
9025 // the instantiation, which can depend on comptime parameters.8742 const cc_resolved = cc orelse .Unspecified;
9026 // Related proposal: https://github.com/ziglang/zig/issues/118348743 var comptime_bits: u32 = 0;
9027 const cc_resolved = cc orelse .Unspecified;8744 for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| {
9028 const param_types = try sema.arena.alloc(InternPool.Index, block.params.items.len);8745 const param_ty = param_ty_ip.toType();
9029 var comptime_bits: u32 = 0;8746 const is_noalias = blk: {
9030 for (param_types, block.params.items, 0..) |*dest_param_ty, param, i| {8747 const index = std.math.cast(u5, i) orelse break :blk false;
9031 const is_noalias = blk: {8748 break :blk @as(u1, @truncate(noalias_bits >> index)) != 0;
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,
9076 };8749 };
90778750 const param_src: LazySrcLoc = .{ .fn_proto_param = .{
9078 const return_type: Type = if (!inferred_error_set or ret_poison)8751 .decl = block.src_decl,
9079 bare_return_type8752 .fn_proto_node_offset = src_node_offset,
9080 else blk: {8753 .param_index = @intCast(i),
9081 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);8754 } };
9082 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{8755 const requires_comptime = try sema.typeRequiresComptime(param_ty);
9083 .func = new_func_index,8756 if (param_is_comptime or requires_comptime) {
9084 });8757 comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error
9085 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });8758 }
9086 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);8759 const this_generic = param_ty.isGenericPoison();
9087 };8760 is_generic = is_generic or this_generic;
90888761 if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) {
9089 if (!return_type.isValidReturnType(mod)) {8762 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});
9090 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";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 "";
9091 const msg = msg: {8769 const msg = msg: {
9092 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{8770 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{
9093 opaque_str, return_type.fmt(mod),8771 opaque_str, param_ty.fmt(mod),
9094 });8772 });
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);
9098 break :msg msg;8776 break :msg msg;
9099 };8777 };
9100 return sema.failWithOwnedErrorMsg(msg);8778 return sema.failWithOwnedErrorMsg(msg);
9101 }8779 }
9102 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and8780 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) {
9103 !try sema.validateExternType(return_type, .ret_ty))
9104 {
9105 const msg = msg: {8781 const msg = msg: {
9106 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{8782 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
9107 return_type.fmt(mod), @tagName(cc_resolved),8783 param_ty.fmt(mod), @tagName(cc_resolved),
9108 });8784 });
9109 errdefer msg.destroy(gpa);8785 errdefer msg.destroy(sema.gpa);
91108786
9111 const src_decl = mod.declPtr(block.src_decl);8787 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);
9115 break :msg msg;8791 break :msg msg;
9116 };8792 };
9117 return sema.failWithOwnedErrorMsg(msg);8793 return sema.failWithOwnedErrorMsg(msg);
9118 }8794 }
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 comptime8802 const src_decl = mod.declPtr(block.src_decl);
9121 if (!sema.is_generic_instantiation and has_body and ret_ty_requires_comptime) comptime_check: {8803 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param_ty);
9122 for (block.params.items) |param| {
9123 if (!param.is_comptime) break;
9124 } else break :comptime_check;
91258804
9126 const msg = try sema.errMsg(8805 try sema.addDeclaredHereNote(msg, param_ty);
9127 block,8806 break :msg msg;
9128 ret_ty_src,8807 };
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 }
9152 return sema.failWithOwnedErrorMsg(msg);8808 return sema.failWithOwnedErrorMsg(msg);
9153 }8809 }
91548810 if (is_source_decl and !this_generic and is_noalias and
9155 const arch = mod.getTarget().cpu.arch;8811 !(param_ty.zigTypeTag(mod) == .Pointer or param_ty.isPtrLikeOptional(mod)))
9156 if (switch (cc_resolved) {8812 {
9157 .Unspecified, .C, .Naked, .Async, .Inline => null,8813 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
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'", .{});
9196 }8814 }
9197 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;8815 }
9198 is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
91998816
9200 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {8817 var ret_ty_requires_comptime = false;
9201 // Make sure that StackTrace's fields are resolved so that the backend can8818 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
9202 // lower this fn type.8819 ret_ty_requires_comptime = ret_comptime;
9203 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");8820 break :rp bare_return_type.isGenericPoison();
9204 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);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);
9205 }8842 }
92068843 const func_index = try ip.getFuncInstance(gpa, .{
9207 break :fn_ty try mod.funcType(.{
9208 .param_types = param_types,8844 .param_types = param_types,
9209 .noalias_bits = noalias_bits,8845 .noalias_bits = noalias_bits,
9210 .comptime_bits = comptime_bits,8846 .bare_return_type = bare_return_type.toIntern(),
9211 .return_type = return_type.toIntern(),
9212 .cc = cc_resolved,8847 .cc = cc_resolved,
9213 .cc_is_generic = cc == null,8848 .alignment = alignment.?,
9214 .alignment = alignment orelse .none,8849 .section = switch (section) {
9215 .align_is_generic = alignment == null,8850 .generic => unreachable,
9216 .section_is_generic = section == .generic,8851 .default => .none,
9217 .addrspace_is_generic = address_space == null,8852 .explicit => |x| x.toOptional(),
9218 .is_var_args = var_args,8853 },
9219 .is_generic = is_generic,
9220 .is_noinline = is_noinline,8854 .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,
9221 });8859 });
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`.
9224 sema.owner_decl.@"linksection" = switch (section) {8880 sema.owner_decl.@"linksection" = switch (section) {
9225 .generic => .none,8881 .generic => .none,
9226 .default => .none,8882 .default => .none,
...@@ -9229,9 +8885,73 @@ fn funcCommon(...@@ -9229,9 +8885,73 @@ fn funcCommon(
9229 sema.owner_decl.alignment = alignment orelse .none;8885 sema.owner_decl.alignment = alignment orelse .none;
9230 sema.owner_decl.@"addrspace" = address_space orelse .generic;8886 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
9232 if (is_extern) {8947 if (is_extern) {
9233 return sema.addConstant((try mod.intern(.{ .extern_func = .{8948 assert(comptime_bits == 0);
9234 .ty = fn_ty.toIntern(),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,
9235 .decl = sema.owner_decl_index,8955 .decl = sema.owner_decl_index,
9236 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(8956 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
9237 gpa,8957 gpa,
...@@ -9239,129 +8959,241 @@ fn funcCommon(...@@ -9239,129 +8959,241 @@ fn funcCommon(
9239 .node_offset_lib_name = src_node_offset,8959 .node_offset_lib_name = src_node_offset,
9240 }, lib_name),8960 }, lib_name),
9241 )).toOptional() else .none,8961 )).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 );
9243 }8980 }
92448981
9245 if (!has_body) {8982 if (has_body) {
9246 return sema.addType(fn_ty);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 );
9247 }9011 }
92489012
9249 const is_inline = fn_ty.fnCallingConvention(mod) == .Inline;9013 return finishFunc(
9250 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;9014 sema,
92519015 block,
9252 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {9016 .none,
9253 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;9017 func_ty,
9254 } else null;9018 ret_poison,
92559019 bare_return_type,
9256 const new_func = mod.funcPtr(new_func_index);9020 ret_ty_src,
9257 const hash = new_func.hash;9021 cc_resolved,
9258 const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;9022 is_source_decl,
9259 new_func.* = .{9023 ret_ty_requires_comptime,
9260 .state = anal_state,9024 func_inst,
9261 .zir_body_inst = func_inst,9025 cc_src,
9262 .owner_decl = sema.owner_decl_index,9026 is_noinline,
9263 .generic_owner_decl = generic_owner_decl,9027 is_generic,
9264 .comptime_args = comptime_args,9028 final_is_generic,
9265 .hash = hash,9029 );
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());
9277}9030}
92789031
9279fn analyzeParameter(9032fn finishFunc(
9280 sema: *Sema,9033 sema: *Sema,
9281 block: *Block,9034 block: *Block,
9282 param_src: LazySrcLoc,9035 opt_func_index: InternPool.Index,
9283 param: Block.Param,9036 func_ty: InternPool.Index,
9284 comptime_bits: *u32,9037 ret_poison: bool,
9285 i: usize,9038 bare_return_type: Type,
9286 is_generic: *bool,9039 ret_ty_src: LazySrcLoc,
9287 cc: std.builtin.CallingConvention,9040 cc_resolved: std.builtin.CallingConvention,
9288 has_body: bool,9041 is_source_decl: bool,
9289 is_noalias: bool,9042 ret_ty_requires_comptime: bool,
9290) !void {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 {
9291 const mod = sema.mod;9049 const mod = sema.mod;
9292 const requires_comptime = try sema.typeRequiresComptime(param.ty);9050 const ip = &mod.intern_pool;
9293 if (param.is_comptime or requires_comptime) {9051 const gpa = sema.gpa;
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;
9298 const target = mod.getTarget();9052 const target = mod.getTarget();
9299 if (param.is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc)) {9053
9300 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});9054 const return_type: Type = if (opt_func_index == .none or ret_poison)
9301 }9055 bare_return_type
9302 if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc)) {9056 else
9303 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});9057 ip.funcTypeReturnType(ip.typeOf(opt_func_index)).toType();
9304 }9058
9305 if (!param.ty.isValidParamType(mod)) {9059 if (!return_type.isValidReturnType(mod)) {
9306 const opaque_str = if (param.ty.zigTypeTag(mod) == .Opaque) "opaque " else "";9060 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";
9307 const msg = msg: {9061 const msg = msg: {
9308 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{9062 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{
9309 opaque_str, param.ty.fmt(mod),9063 opaque_str, return_type.fmt(mod),
9310 });9064 });
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);
9314 break :msg msg;9068 break :msg msg;
9315 };9069 };
9316 return sema.failWithOwnedErrorMsg(msg);9070 return sema.failWithOwnedErrorMsg(msg);
9317 }9071 }
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 {
9319 const msg = msg: {9075 const msg = msg: {
9320 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{9076 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
9321 param.ty.fmt(mod), @tagName(cc),9077 return_type.fmt(mod), @tagName(cc_resolved),
9322 });9078 });
9323 errdefer msg.destroy(sema.gpa);9079 errdefer msg.destroy(gpa);
93249080
9325 const src_decl = mod.declPtr(block.src_decl);9081 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);
9329 break :msg msg;9085 break :msg msg;
9330 };9086 };
9331 return sema.failWithOwnedErrorMsg(msg);9087 return sema.failWithOwnedErrorMsg(msg);
9332 }9088 }
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);9090 // If the return type is comptime-only but not dependent on parameters then
9341 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param.ty);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);9097 const msg = try sema.errMsg(
9344 break :msg msg;9098 block,
9345 };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 }
9346 return sema.failWithOwnedErrorMsg(msg);9127 return sema.failWithOwnedErrorMsg(msg);
9347 }9128 }
9348 if (!sema.is_generic_instantiation and !this_generic and is_noalias and9129
9349 !(param.ty.zigTypeTag(mod) == .Pointer or param.ty.isPtrLikeOptional(mod)))9130 const arch = target.cpu.arch;
9350 {9131 if (switch (cc_resolved) {
9351 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});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 });
9352 }9167 }
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);
9353}9182}
93549183
9355fn zirParam(9184fn zirParam(
9356 sema: *Sema,9185 sema: *Sema,
9357 block: *Block,9186 block: *Block,
9358 inst: Zir.Inst.Index,9187 inst: Zir.Inst.Index,
9188 param_index: u32,
9359 comptime_syntax: bool,9189 comptime_syntax: bool,
9360) CompileError!void {9190) CompileError!void {
9191 const mod = sema.mod;
9192 const gpa = sema.gpa;
9361 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;9193 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
9362 const src = inst_data.src();9194 const src = inst_data.src();
9363 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);9195 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);
9365 const body = sema.code.extra[extra.end..][0..extra.data.body_len];9197 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
93669198
9367 // We could be in a generic function instantiation, or we could be evaluating a generic9199 // We could be in a generic function instantiation, or we could be evaluating a generic
...@@ -9370,16 +9202,21 @@ fn zirParam(...@@ -9370,16 +9202,21 @@ fn zirParam(
9370 const err = err: {9202 const err = err: {
9371 // Make sure any nested param instructions don't clobber our work.9203 // Make sure any nested param instructions don't clobber our work.
9372 const prev_params = block.params;9204 const prev_params = block.params;
9373 const prev_preallocated_new_func = sema.preallocated_new_func;
9374 const prev_no_partial_func_type = sema.no_partial_func_ty;9205 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;
9375 block.params = .{};9209 block.params = .{};
9376 sema.preallocated_new_func = .none;
9377 sema.no_partial_func_ty = true;9210 sema.no_partial_func_ty = true;
9211 sema.generic_owner = .none;
9212 sema.generic_call_src = .unneeded;
9213 sema.generic_call_decl = .none;
9378 defer {9214 defer {
9379 block.params.deinit(sema.gpa);
9380 block.params = prev_params;9215 block.params = prev_params;
9381 sema.preallocated_new_func = prev_preallocated_new_func;
9382 sema.no_partial_func_ty = prev_no_partial_func_type;9216 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;
9383 }9220 }
93849221
9385 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {9222 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
...@@ -9390,7 +9227,7 @@ fn zirParam(...@@ -9390,7 +9227,7 @@ fn zirParam(
9390 };9227 };
9391 switch (err) {9228 switch (err) {
9392 error.GenericPoison => {9229 error.GenericPoison => {
9393 if (sema.inst_map.get(inst)) |_| {9230 if (sema.inst_map.contains(inst)) {
9394 // A generic function is about to evaluate to another generic function.9231 // A generic function is about to evaluate to another generic function.
9395 // Return an error instead.9232 // Return an error instead.
9396 return error.GenericPoison;9233 return error.GenericPoison;
...@@ -9398,8 +9235,8 @@ fn zirParam(...@@ -9398,8 +9235,8 @@ fn zirParam(
9398 // The type is not available until the generic instantiation.9235 // The type is not available until the generic instantiation.
9399 // We result the param instruction with a poison value and9236 // We result the param instruction with a poison value and
9400 // insert an anytype parameter.9237 // insert an anytype parameter.
9401 try block.params.append(sema.gpa, .{9238 try block.params.append(sema.arena, .{
9402 .ty = Type.generic_poison,9239 .ty = .generic_poison_type,
9403 .is_comptime = comptime_syntax,9240 .is_comptime = comptime_syntax,
9404 .name = param_name,9241 .name = param_name,
9405 });9242 });
...@@ -9409,9 +9246,10 @@ fn zirParam(...@@ -9409,9 +9246,10 @@ fn zirParam(
9409 else => |e| return e,9246 else => |e| return e,
9410 }9247 }
9411 };9248 };
9249
9412 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {9250 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {
9413 error.GenericPoison => {9251 error.GenericPoison => {
9414 if (sema.inst_map.get(inst)) |_| {9252 if (sema.inst_map.contains(inst)) {
9415 // A generic function is about to evaluate to another generic function.9253 // A generic function is about to evaluate to another generic function.
9416 // Return an error instead.9254 // Return an error instead.
9417 return error.GenericPoison;9255 return error.GenericPoison;
...@@ -9419,8 +9257,8 @@ fn zirParam(...@@ -9419,8 +9257,8 @@ fn zirParam(
9419 // The type is not available until the generic instantiation.9257 // The type is not available until the generic instantiation.
9420 // We result the param instruction with a poison value and9258 // We result the param instruction with a poison value and
9421 // insert an anytype parameter.9259 // insert an anytype parameter.
9422 try block.params.append(sema.gpa, .{9260 try block.params.append(sema.arena, .{
9423 .ty = Type.generic_poison,9261 .ty = .generic_poison_type,
9424 .is_comptime = comptime_syntax,9262 .is_comptime = comptime_syntax,
9425 .name = param_name,9263 .name = param_name,
9426 });9264 });
...@@ -9429,8 +9267,9 @@ fn zirParam(...@@ -9429,8 +9267,9 @@ fn zirParam(
9429 },9267 },
9430 else => |e| return e,9268 else => |e| return e,
9431 } or comptime_syntax;9269 } or comptime_syntax;
9270
9432 if (sema.inst_map.get(inst)) |arg| {9271 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) {
9434 // We have a comptime value for this parameter so it should be elided from the9273 // We have a comptime value for this parameter so it should be elided from the
9435 // function type of the function instruction in this block.9274 // function type of the function instruction in this block.
9436 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {9275 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
...@@ -9440,32 +9279,53 @@ fn zirParam(...@@ -9440,32 +9279,53 @@ fn zirParam(
9440 // have the callee source location return `GenericPoison`9279 // have the callee source location return `GenericPoison`
9441 // so that the instantiation is failed and the coercion9280 // so that the instantiation is failed and the coercion
9442 // is handled by comptime call logic instead.9281 // is handled by comptime call logic instead.
9443 assert(sema.is_generic_instantiation);9282 assert(sema.generic_owner != .none);
9444 return error.GenericPoison;9283 return error.GenericPoison;
9445 },9284 },
9446 else => return err,9285 else => |e| return e,
9447 };9286 };
9448 sema.inst_map.putAssumeCapacity(inst, coerced_arg);9287 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);
9450 }9310 }
9451 // Even though a comptime argument is provided, the generic function wants to treat9311 // Even though a comptime argument is provided, the generic function wants to treat
9452 // this as a runtime parameter.9312 // this as a runtime parameter.
9453 assert(sema.inst_map.remove(inst));9313 assert(sema.inst_map.remove(inst));
9454 }9314 }
94559315
9456 if (sema.preallocated_new_func != .none) {9316 if (sema.generic_owner != .none) {
9457 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {9317 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
9458 // In this case we are instantiating a generic function call with a non-comptime9318 // In this case we are instantiating a generic function call with a non-comptime
9459 // non-anytype parameter that ended up being a one-possible-type.9319 // non-anytype parameter that ended up being a one-possible-type.
9460 // We don't want the parameter to be part of the instantiated function type.9320 // We don't want the parameter to be part of the instantiated function type.
9461 const result = try sema.addConstant(opv);9321 sema.inst_map.putAssumeCapacity(inst, Air.internedToRef(opv.toIntern()));
9462 sema.inst_map.putAssumeCapacity(inst, result);9322 sema.comptime_args[param_index] = opv.toIntern();
9463 return;9323 return;
9464 }9324 }
9465 }9325 }
94669326
9467 try block.params.append(sema.gpa, .{9327 try block.params.append(sema.arena, .{
9468 .ty = param_ty,9328 .ty = param_ty.toIntern(),
9469 .is_comptime = comptime_syntax,9329 .is_comptime = comptime_syntax,
9470 .name = param_name,9330 .name = param_name,
9471 });9331 });
...@@ -9473,17 +9333,15 @@ fn zirParam(...@@ -9473,17 +9333,15 @@ fn zirParam(
9473 if (is_comptime) {9333 if (is_comptime) {
9474 // If this is a comptime parameter we can add a constant generic_poison9334 // If this is a comptime parameter we can add a constant generic_poison
9475 // since this is also a generic parameter.9335 // since this is also a generic parameter.
9476 const result = try sema.addConstant(Value.generic_poison);9336 sema.inst_map.putAssumeCapacityNoClobber(inst, .generic_poison);
9477 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
9478 } else {9337 } else {
9479 // Otherwise we need a dummy runtime instruction.9338 // 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);
9481 try sema.air_instructions.append(sema.gpa, .{9340 try sema.air_instructions.append(sema.gpa, .{
9482 .tag = .alloc,9341 .tag = .alloc,
9483 .data = .{ .ty = param_ty },9342 .data = .{ .ty = param_ty },
9484 });9343 });
9485 const result = Air.indexToRef(result_index);9344 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(result_index));
9486 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
9487 }9345 }
9488}9346}
94899347
...@@ -9491,24 +9349,76 @@ fn zirParamAnytype(...@@ -9491,24 +9349,76 @@ fn zirParamAnytype(
9491 sema: *Sema,9349 sema: *Sema,
9492 block: *Block,9350 block: *Block,
9493 inst: Zir.Inst.Index,9351 inst: Zir.Inst.Index,
9352 param_index: u32,
9494 comptime_syntax: bool,9353 comptime_syntax: bool,
9495) CompileError!void {9354) CompileError!void {
9355 const mod = sema.mod;
9356 const gpa = sema.gpa;
9496 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;9357 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
9499 if (sema.inst_map.get(inst)) |air_ref| {9361 if (sema.inst_map.get(inst)) |air_ref| {
9500 const param_ty = sema.typeOf(air_ref);9362 const param_ty = sema.typeOf(air_ref);
9501 if (comptime_syntax or try sema.typeRequiresComptime(param_ty)) {9363 // If we have a comptime value for this parameter, it should be elided
9502 // We have a comptime value for this parameter so it should be elided from the9364 // from the function type of the function instruction in this block.
9503 // 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();
9504 return;9367 return;
9505 }9368 }
9506 if (null != try sema.typeHasOnePossibleValue(param_ty)) {9369 const arg_src: LazySrcLoc = if (sema.generic_call_src == .node_offset) .{ .call_arg = .{
9507 return;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);
9508 }9393 }
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.
9509 // The map is already populated but we do need to add a runtime parameter.9419 // The map is already populated but we do need to add a runtime parameter.
9510 try block.params.append(sema.gpa, .{9420 try block.params.append(sema.arena, .{
9511 .ty = param_ty,9421 .ty = param_ty.toIntern(),
9512 .is_comptime = false,9422 .is_comptime = false,
9513 .name = param_name,9423 .name = param_name,
9514 });9424 });
...@@ -9517,8 +9427,8 @@ fn zirParamAnytype(...@@ -9517,8 +9427,8 @@ fn zirParamAnytype(
95179427
9518 // We are evaluating a generic function without any comptime args provided.9428 // We are evaluating a generic function without any comptime args provided.
95199429
9520 try block.params.append(sema.gpa, .{9430 try block.params.append(sema.arena, .{
9521 .ty = Type.generic_poison,9431 .ty = .generic_poison_type,
9522 .is_comptime = comptime_syntax,9432 .is_comptime = comptime_syntax,
9523 .name = param_name,9433 .name = param_name,
9524 });9434 });
...@@ -10673,7 +10583,7 @@ const SwitchProngAnalysis = struct {...@@ -10673,7 +10583,7 @@ const SwitchProngAnalysis = struct {
10673 return sema.bitCast(block, item_ty, spa.operand, operand_src, null);10583 return sema.bitCast(block, item_ty, spa.operand, operand_src, null);
10674 }10584 }
1067510585
10676 var names: Module.Fn.InferredErrorSet.NameMap = .{};10586 var names: InferredErrorSet.NameMap = .{};
10677 try names.ensureUnusedCapacity(sema.arena, case_vals.len);10587 try names.ensureUnusedCapacity(sema.arena, case_vals.len);
10678 for (case_vals) |err| {10588 for (case_vals) |err| {
10679 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;10589 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...@@ -11041,97 +10951,100 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
11041 }10951 }
11042 }10952 }
1104310953
11044 try sema.resolveInferredErrorSetTy(block, src, operand_ty);10954 switch (try sema.resolveInferredErrorSetTy(block, src, operand_ty.toIntern())) {
1104510955 .anyerror_type => {
11046 if (operand_ty.isAnyError(mod)) {10956 if (special_prong != .@"else") {
11047 if (special_prong != .@"else") {10957 return sema.fail(
11048 return sema.fail(10958 block,
11049 block,10959 src,
11050 src,10960 "else prong required when switching on type 'anyerror'",
11051 "else prong required when switching on type 'anyerror'",10961 .{},
11052 .{},10962 );
11053 );10963 }
11054 }10964 else_error_ty = Type.anyerror;
11055 else_error_ty = Type.anyerror;10965 },
11056 } else else_validation: {10966 else => |err_set_ty_index| else_validation: {
11057 var maybe_msg: ?*Module.ErrorMsg = null;10967 const error_names = ip.indexToKey(err_set_ty_index).error_set_type.names;
11058 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);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| {10983 try sema.errNote(
11061 if (!seen_errors.contains(error_name) and special_prong != .@"else") {
11062 const msg = maybe_msg orelse blk: {
11063 maybe_msg = try sema.errMsg(
11064 block,10984 block,
11065 src,10985 src,
11066 "switch must handle all possibilities",10986 msg,
11067 .{},10987 "unhandled error value: 'error.{}'",
10988 .{error_name.fmt(ip)},
11068 );10989 );
11069 break :blk maybe_msg.?;10990 }
11070 };
11071
11072 try sema.errNote(
11073 block,
11074 src,
11075 msg,
11076 "unhandled error value: 'error.{}'",
11077 .{error_name.fmt(ip)},
11078 );
11079 }10991 }
11080 }
1108110992
11082 if (maybe_msg) |msg| {10993 if (maybe_msg) |msg| {
11083 maybe_msg = null;10994 maybe_msg = null;
11084 try sema.addDeclaredHereNote(msg, operand_ty);10995 try sema.addDeclaredHereNote(msg, operand_ty);
11085 return sema.failWithOwnedErrorMsg(msg);10996 return sema.failWithOwnedErrorMsg(msg);
11086 }10997 }
1108710998
11088 if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames(mod).len) {10999 if (special_prong == .@"else" and
11089 // In order to enable common patterns for generic code allow simple else bodies11000 seen_errors.count() == error_names.len)
11090 // else => unreachable,11001 {
11091 // else => return,11002 // In order to enable common patterns for generic code allow simple else bodies
11092 // else => |e| return e,11003 // else => unreachable,
11093 // even if all the possible errors were already handled.11004 // else => return,
11094 const tags = sema.code.instructions.items(.tag);11005 // else => |e| return e,
11095 for (special.body) |else_inst| switch (tags[else_inst]) {11006 // even if all the possible errors were already handled.
11096 .dbg_block_begin,11007 const tags = sema.code.instructions.items(.tag);
11097 .dbg_block_end,11008 for (special.body) |else_inst| switch (tags[else_inst]) {
11098 .dbg_stmt,11009 .dbg_block_begin,
11099 .dbg_var_val,11010 .dbg_block_end,
11100 .ret_type,11011 .dbg_stmt,
11101 .as_node,11012 .dbg_var_val,
11102 .ret_node,11013 .ret_type,
11103 .@"unreachable",11014 .as_node,
11104 .@"defer",11015 .ret_node,
11105 .defer_err_code,11016 .@"unreachable",
11106 .err_union_code,11017 .@"defer",
11107 .ret_err_value_code,11018 .defer_err_code,
11108 .restore_err_ret_index,11019 .err_union_code,
11109 .is_non_err,11020 .ret_err_value_code,
11110 .ret_is_non_err,11021 .restore_err_ret_index,
11111 .condbr,11022 .is_non_err,
11112 => {},11023 .ret_is_non_err,
11113 else => break,11024 .condbr,
11114 } else break :else_validation;11025 => {},
11026 else => break,
11027 } else break :else_validation;
1111511028
11116 return sema.fail(11029 return sema.fail(
11117 block,11030 block,
11118 special_prong_src,11031 special_prong_src,
11119 "unreachable else prong; all cases already handled",11032 "unreachable else prong; all cases already handled",
11120 .{},11033 .{},
11121 );11034 );
11122 }11035 }
1112311036
11124 const error_names = operand_ty.errorSetNames(mod);11037 var names: InferredErrorSet.NameMap = .{};
11125 var names: Module.Fn.InferredErrorSet.NameMap = .{};11038 try names.ensureUnusedCapacity(sema.arena, error_names.len);
11126 try names.ensureUnusedCapacity(sema.arena, error_names.len);11039 for (error_names.get(ip)) |error_name| {
11127 for (error_names) |error_name| {11040 if (seen_errors.contains(error_name)) continue;
11128 if (seen_errors.contains(error_name)) continue;
1112911041
11130 names.putAssumeCapacityNoClobber(error_name, {});11042 names.putAssumeCapacityNoClobber(error_name, {});
11131 }11043 }
11132 // No need to keep the hash map metadata correct; here we11044 // No need to keep the hash map metadata correct; here we
11133 // extract the (sorted) keys only.11045 // extract the (sorted) keys only.
11134 else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());11046 else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
11047 },
11135 }11048 }
11136 },11049 },
11137 .Int, .ComptimeInt => {11050 .Int, .ComptimeInt => {
...@@ -16295,6 +16208,7 @@ fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -16295,6 +16208,7 @@ fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
1629516208
16296fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {16209fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
16297 const mod = sema.mod;16210 const mod = sema.mod;
16211 const ip = &mod.intern_pool;
16298 const inst_data = sema.code.instructions.items(.data)[inst].inst_node;16212 const inst_data = sema.code.instructions.items(.data)[inst].inst_node;
16299 var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?;16213 var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?;
16300 // Note: The target closure must be in this scope list.16214 // 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!...@@ -16305,8 +16219,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1630516219
16306 // Fail this decl if a scope it depended on failed.16220 // Fail this decl if a scope it depended on failed.
16307 if (scope.failed()) {16221 if (scope.failed()) {
16308 if (sema.owner_func) |owner_func| {16222 if (sema.owner_func_index != .none) {
16309 owner_func.state = .dependency_failure;16223 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
16310 } else {16224 } else {
16311 sema.owner_decl.analysis = .dependency_failure;16225 sema.owner_decl.analysis = .dependency_failure;
16312 }16226 }
...@@ -16423,8 +16337,8 @@ fn zirBuiltinSrc(...@@ -16423,8 +16337,8 @@ fn zirBuiltinSrc(
16423 const mod = sema.mod;16337 const mod = sema.mod;
16424 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;16338 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;
16425 const src = LazySrcLoc.nodeOffset(extra.node);16339 const src = LazySrcLoc.nodeOffset(extra.node);
16426 const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{});16340 if (sema.func_index == .none) return sema.fail(block, src, "@src outside function", .{});
16427 const fn_owner_decl = mod.declPtr(func.owner_decl);16341 const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index);
1642816342
16429 const func_name_val = blk: {16343 const func_name_val = blk: {
16430 var anon_decl = try block.startAnonDecl();16344 var anon_decl = try block.startAnonDecl();
...@@ -16548,10 +16462,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16548,10 +16462,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16548 const param_info_decl = mod.declPtr(param_info_decl_index);16462 const param_info_decl = mod.declPtr(param_info_decl_index);
16549 const param_info_ty = param_info_decl.val.toType();16463 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);
16552 for (param_vals, 0..) |*param_val, i| {16467 for (param_vals, 0..) |*param_val, i| {
16553 const info = mod.typeToFunc(ty).?;16468 const param_ty = func_ty_info.param_types.get(ip)[i];
16554 const param_ty = info.param_types[i];
16555 const is_generic = param_ty == .generic_poison_type;16469 const is_generic = param_ty == .generic_poison_type;
16556 const param_ty_val = try ip.get(gpa, .{ .opt = .{16470 const param_ty_val = try ip.get(gpa, .{ .opt = .{
16557 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),16471 .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...@@ -16560,7 +16474,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1656016474
16561 const is_noalias = blk: {16475 const is_noalias = blk: {
16562 const index = std.math.cast(u5, i) orelse break :blk false;16476 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;
16564 };16478 };
1656516479
16566 const param_fields = .{16480 const param_fields = .{
...@@ -16603,23 +16517,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16603,23 +16517,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16603 } });16517 } });
16604 };16518 };
1660516519
16606 const info = mod.typeToFunc(ty).?;
16607 const ret_ty_opt = try mod.intern(.{ .opt = .{16520 const ret_ty_opt = try mod.intern(.{ .opt = .{
16608 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),16521 .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,
16610 } });16526 } });
1661116527
16612 const callconv_ty = try sema.getBuiltinType("CallingConvention");16528 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1661316529
16614 const field_values = .{16530 const field_values = .{
16615 // calling_convention: CallingConvention,16531 // 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(),
16617 // alignment: comptime_int,16533 // alignment: comptime_int,
16618 (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).toIntern(),16534 (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).toIntern(),
16619 // is_generic: bool,16535 // is_generic: bool,
16620 Value.makeBool(info.is_generic).toIntern(),16536 Value.makeBool(func_ty_info.is_generic).toIntern(),
16621 // is_var_args: bool,16537 // is_var_args: bool,
16622 Value.makeBool(info.is_var_args).toIntern(),16538 Value.makeBool(func_ty_info.is_var_args).toIntern(),
16623 // return_type: ?type,16539 // return_type: ?type,
16624 ret_ty_opt,16540 ret_ty_opt,
16625 // args: []const Fn.Param,16541 // args: []const Fn.Param,
...@@ -16860,50 +16776,51 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16860,50 +16776,51 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1686016776
16861 try sema.queueFullTypeResolution(error_field_ty);16777 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
16866 // Build our list of Error values16779 // Build our list of Error values
16867 // Optional value is only null if anyerror16780 // Optional value is only null if anyerror
16868 // Value can be zero-length slice otherwise16781 // Value can be zero-length slice otherwise
16869 const error_field_vals = if (ty.isAnyError(mod)) null else blk: {16782 const error_field_vals = switch (try sema.resolveInferredErrorSetTy(block, src, ty.toIntern())) {
16870 const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len);16783 .anyerror_type => null,
16871 for (vals, 0..) |*field_val, i| {16784 else => |err_set_ty_index| blk: {
16872 // TODO: write something like getCoercedInts to avoid needing to dupe16785 const names = ip.indexToKey(err_set_ty_index).error_set_type.names;
16873 const name = try sema.arena.dupe(u8, ip.stringToSlice(ty.errorSetNames(mod)[i]));16786 const vals = try sema.arena.alloc(InternPool.Index, names.len);
16874 const name_val = v: {16787 for (vals, 0..) |*field_val, i| {
16875 var anon_decl = try block.startAnonDecl();16788 // TODO: write something like getCoercedInts to avoid needing to dupe
16876 defer anon_decl.deinit();16789 const name = try sema.arena.dupe(u8, ip.stringToSlice(names.get(ip)[i]));
16877 const new_decl_ty = try mod.arrayType(.{16790 const name_val = v: {
16878 .len = name.len,16791 var anon_decl = try block.startAnonDecl();
16879 .child = .u8_type,16792 defer anon_decl.deinit();
16880 });16793 const new_decl_ty = try mod.arrayType(.{
16881 const new_decl = try anon_decl.finish(16794 .len = name.len,
16882 new_decl_ty,16795 .child = .u8_type,
16883 (try mod.intern(.{ .aggregate = .{16796 });
16884 .ty = new_decl_ty.toIntern(),16797 const new_decl = try anon_decl.finish(
16885 .storage = .{ .bytes = name },16798 new_decl_ty,
16886 } })).toValue(),16799 (try mod.intern(.{ .aggregate = .{
16887 .none, // default alignment16800 .ty = new_decl_ty.toIntern(),
16888 );16801 .storage = .{ .bytes = name },
16889 break :v try mod.intern(.{ .ptr = .{16802 } })).toValue(),
16890 .ty = .slice_const_u8_type,16803 .none, // default alignment
16891 .addr = .{ .decl = new_decl },16804 );
16892 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),16805 break :v try mod.intern(.{ .ptr = .{
16893 } });16806 .ty = .slice_const_u8_type,
16894 };16807 .addr = .{ .decl = new_decl },
16808 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
16809 } });
16810 };
1689516811
16896 const error_field_fields = .{16812 const error_field_fields = .{
16897 // name: []const u8,16813 // name: []const u8,
16898 name_val,16814 name_val,
16899 };16815 };
16900 field_val.* = try mod.intern(.{ .aggregate = .{16816 field_val.* = try mod.intern(.{ .aggregate = .{
16901 .ty = error_field_ty.toIntern(),16817 .ty = error_field_ty.toIntern(),
16902 .storage = .{ .elems = &error_field_fields },16818 .storage = .{ .elems = &error_field_fields },
16903 } });16819 } });
16904 }16820 }
1690516821
16906 break :blk vals;16822 break :blk vals;
16823 },
16907 };16824 };
1690816825
16909 // Build our ?[]const Error value16826 // Build our ?[]const Error value
...@@ -18425,9 +18342,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)...@@ -18425,9 +18342,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
18425 // This is only relevant at runtime.18342 // This is only relevant at runtime.
18426 if (start_block.is_comptime or start_block.is_typeof) return;18343 if (start_block.is_comptime or start_block.is_typeof) return;
1842718344
18428 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;18345 const mod = sema.mod;
18429 if (!sema.owner_func.?.calls_or_awaits_errorable_fn) return;18346 const ip = &mod.intern_pool;
18430 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;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
18432 const tracy = trace(@src());18352 const tracy = trace(@src());
18433 defer tracy.end();18353 defer tracy.end();
...@@ -18464,17 +18384,30 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)...@@ -18464,17 +18384,30 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
1846418384
18465fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {18385fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {
18466 const mod = sema.mod;18386 const mod = sema.mod;
18467 const gpa = sema.gpa;
18468 const ip = &mod.intern_pool;18387 const ip = &mod.intern_pool;
18469 assert(sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion);18388 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| {18404fn addToInferredErrorSetPtr(mod: *Module, ies: *InferredErrorSet, op_ty: Type) !void {
18472 const op_ty = sema.typeOf(uncasted_operand);18405 const gpa = mod.gpa;
18473 switch (op_ty.zigTypeTag(mod)) {18406 const ip = &mod.intern_pool;
18474 .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa),18407 switch (op_ty.zigTypeTag(mod)) {
18475 .ErrorUnion => try ies.addErrorSet(op_ty.errorUnionSet(mod), ip, gpa),18408 .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa),
18476 else => {},18409 .ErrorUnion => try ies.addErrorSet(op_ty.errorUnionSet(mod), ip, gpa),
18477 }18410 else => {},
18478 }18411 }
18479}18412}
1848018413
...@@ -18488,7 +18421,7 @@ fn analyzeRet(...@@ -18488,7 +18421,7 @@ fn analyzeRet(
18488 // add the error tag to the inferred error set of the in-scope function, so18421 // add the error tag to the inferred error set of the in-scope function, so
18489 // that the coercion below works correctly.18422 // that the coercion below works correctly.
18490 const mod = sema.mod;18423 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) {
18492 try sema.addToInferredErrorSet(uncasted_operand);18425 try sema.addToInferredErrorSet(uncasted_operand);
18493 }18426 }
18494 const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, .{ .is_ret = true }) catch |err| switch (err) {18427 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 {...@@ -19461,13 +19394,14 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
1946119394
19462fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {19395fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
19463 const mod = sema.mod;19396 const mod = sema.mod;
19397 const ip = &mod.intern_pool;
19464 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");19398 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
19465 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);19399 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
19466 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);19400 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
19467 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());19401 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
1946819402
19469 if (sema.owner_func != null and19403 if (sema.owner_func_index != .none and
19470 sema.owner_func.?.calls_or_awaits_errorable_fn and19404 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and
19471 mod.comp.bin_file.options.error_return_tracing and19405 mod.comp.bin_file.options.error_return_tracing and
19472 mod.backendSupportsFeature(.error_return_trace))19406 mod.backendSupportsFeature(.error_return_trace))
19473 {19407 {
...@@ -19920,7 +19854,7 @@ fn zirReify(...@@ -19920,7 +19854,7 @@ fn zirReify(
19920 return sema.addType(Type.anyerror);19854 return sema.addType(Type.anyerror);
1992119855
19922 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));19856 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));
19923 var names: Module.Fn.InferredErrorSet.NameMap = .{};19857 var names: InferredErrorSet.NameMap = .{};
19924 try names.ensureUnusedCapacity(sema.arena, len);19858 try names.ensureUnusedCapacity(sema.arena, len);
19925 for (0..len) |i| {19859 for (0..len) |i| {
19926 const elem_val = try payload_val.elemValue(mod, i);19860 const elem_val = try payload_val.elemValue(mod, i);
...@@ -20431,8 +20365,6 @@ fn zirReify(...@@ -20431,8 +20365,6 @@ fn zirReify(
20431 .is_var_args = is_var_args,20365 .is_var_args = is_var_args,
20432 .is_generic = false,20366 .is_generic = false,
20433 .is_noinline = false,20367 .is_noinline = false,
20434 .align_is_generic = false,
20435 .cc_is_generic = false,
20436 .section_is_generic = false,20368 .section_is_generic = false,
20437 .addrspace_is_generic = false,20369 .addrspace_is_generic = false,
20438 });20370 });
...@@ -20936,8 +20868,8 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -20936,8 +20868,8 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
20936 break :disjoint true;20868 break :disjoint true;
20937 }20869 }
2093820870
20939 try sema.resolveInferredErrorSetTy(block, src, dest_ty);20871 _ = try sema.resolveInferredErrorSetTy(block, src, dest_ty.toIntern());
20940 try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty);20872 _ = try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty.toIntern());
20941 for (dest_ty.errorSetNames(mod)) |dest_err_name| {20873 for (dest_ty.errorSetNames(mod)) |dest_err_name| {
20942 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name))20874 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name))
20943 break :disjoint false;20875 break :disjoint false;
...@@ -23917,7 +23849,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -23917,7 +23849,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
23917 break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);23849 break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);
23918 } else target_util.defaultAddressSpace(target, .function);23850 } 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: {
23921 const body_len = sema.code.extra[extra_index];23853 const body_len = sema.code.extra[extra_index];
23922 extra_index += 1;23854 extra_index += 1;
23923 const body = sema.code.extra[extra_index..][0..body_len];23855 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...@@ -23926,20 +23858,20 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
23926 const ty = Type.slice_const_u8;23858 const ty = Type.slice_const_u8;
23927 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");23859 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");
23928 if (val.isGenericPoison()) {23860 if (val.isGenericPoison()) {
23929 break :blk FuncLinkSection{ .generic = {} };23861 break :blk .generic;
23930 }23862 }
23931 break :blk FuncLinkSection{ .explicit = try val.toIpString(ty, mod) };23863 break :blk .{ .explicit = try val.toIpString(ty, mod) };
23932 } else if (extra.data.bits.has_section_ref) blk: {23864 } else if (extra.data.bits.has_section_ref) blk: {
23933 const section_ref = @as(Zir.Inst.Ref, @enumFromInt(sema.code.extra[extra_index]));23865 const section_ref = @as(Zir.Inst.Ref, @enumFromInt(sema.code.extra[extra_index]));
23934 extra_index += 1;23866 extra_index += 1;
23935 const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) {23867 const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) {
23936 error.GenericPoison => {23868 error.GenericPoison => {
23937 break :blk FuncLinkSection{ .generic = {} };23869 break :blk .generic;
23938 },23870 },
23939 else => |e| return e,23871 else => |e| return e,
23940 };23872 };
23941 break :blk FuncLinkSection{ .explicit = section_name };23873 break :blk .{ .explicit = section_name };
23942 } else FuncLinkSection{ .default = {} };23874 } else .default;
2394323875
23944 const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {23876 const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
23945 const body_len = sema.code.extra[extra_index];23877 const body_len = sema.code.extra[extra_index];
...@@ -24013,7 +23945,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -24013,7 +23945,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
24013 inst,23945 inst,
24014 @"align",23946 @"align",
24015 @"addrspace",23947 @"addrspace",
24016 @"linksection",23948 section,
24017 cc,23949 cc,
24018 ret_ty,23950 ret_ty,
24019 is_var_args,23951 is_var_args,
...@@ -24846,9 +24778,9 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {...@@ -24846,9 +24778,9 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {
24846 const tv = try mod.declPtr(decl_index).typedValue();24778 const tv = try mod.declPtr(decl_index).typedValue();
24847 assert(tv.ty.zigTypeTag(mod) == .Fn);24779 assert(tv.ty.zigTypeTag(mod) == .Fn);
24848 assert(try sema.fnHasRuntimeBits(tv.ty));24780 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();
24850 try mod.ensureFuncBodyAnalysisQueued(func_index);24782 try mod.ensureFuncBodyAnalysisQueued(func_index);
24851 mod.panic_func_index = func_index.toOptional();24783 mod.panic_func_index = func_index;
24852 }24784 }
2485324785
24854 if (mod.null_stack_trace == .none) {24786 if (mod.null_stack_trace == .none) {
...@@ -24982,7 +24914,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, msg_inst: Air.Inst.Ref) !void {...@@ -24982,7 +24914,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, msg_inst: Air.Inst.Ref) !void {
2498224914
24983 try sema.prepareSimplePanic(block);24915 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);
24986 const panic_fn = try sema.analyzeDeclVal(block, .unneeded, panic_func.owner_decl);24918 const panic_fn = try sema.analyzeDeclVal(block, .unneeded, panic_func.owner_decl);
24987 const null_stack_trace = try sema.addConstant(mod.null_stack_trace.toValue());24919 const null_stack_trace = try sema.addConstant(mod.null_stack_trace.toValue());
2498824920
...@@ -25688,7 +25620,7 @@ fn fieldCallBind(...@@ -25688,7 +25620,7 @@ fn fieldCallBind(
25688 if (mod.typeToFunc(decl_type)) |func_type| f: {25620 if (mod.typeToFunc(decl_type)) |func_type| f: {
25689 if (func_type.param_types.len == 0) break :f;25621 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();
25692 // zig fmt: off25624 // zig fmt: off
25693 if (first_param_type.isGenericPoison() or (25625 if (first_param_type.isGenericPoison() or (
25694 first_param_type.zigTypeTag(mod) == .Pointer and25626 first_param_type.zigTypeTag(mod) == .Pointer and
...@@ -27526,7 +27458,7 @@ fn coerceExtra(...@@ -27526,7 +27458,7 @@ fn coerceExtra(
27526 errdefer msg.destroy(sema.gpa);27458 errdefer msg.destroy(sema.gpa);
2752727459
27528 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };27460 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);
27530 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});27462 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});
27531 break :msg msg;27463 break :msg msg;
27532 };27464 };
...@@ -27556,9 +27488,11 @@ fn coerceExtra(...@@ -27556,9 +27488,11 @@ fn coerceExtra(
27556 try in_memory_result.report(sema, block, inst_src, msg);27488 try in_memory_result.report(sema, block, inst_src, msg);
2755727489
27558 // Add notes about function return type27490 // 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 {
27560 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };27494 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);
27562 if (inst_ty.isError(mod) and !dest_ty.isError(mod)) {27496 if (inst_ty.isError(mod) and !dest_ty.isError(mod)) {
27563 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});27497 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});
27564 } else {27498 } else {
...@@ -28160,42 +28094,29 @@ fn coerceInMemoryAllowedErrorSets(...@@ -28160,42 +28094,29 @@ fn coerceInMemoryAllowedErrorSets(
28160 return .ok;28094 return .ok;
28161 }28095 }
2816228096
28163 if (mod.typeToInferredErrorSetIndex(dest_ty).unwrap()) |dst_ies_index| {28097 if (dest_ty.toIntern() == .adhoc_inferred_error_set_type) {
28164 const dst_ies = mod.inferredErrorSetPtr(dst_ies_index);28098 // We are trying to coerce an error set to the current function's
28165 // We will make an effort to return `ok` without resolving either error set, to28099 // inferred error set.
28166 // avoid unnecessary "unable to resolve error set" dependency loop errors.28100 const dst_ies = sema.fn_ret_ty_ies.?;
28167 switch (src_ty.toIntern()) {28101 try dst_ies.addErrorSet(src_ty, ip, gpa);
28168 .anyerror_type => {},28102 return .ok;
28169 else => switch (ip.indexToKey(src_ty.toIntern())) {28103 }
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 }
2818728104
28188 if (dst_ies.func == sema.owner_func_index.unwrap()) {28105 if (ip.isInferredErrorSetType(dest_ty.toIntern())) {
28189 // We are trying to coerce an error set to the current function's28106 const dst_ies_func_index = ip.iesFuncIndex(dest_ty.toIntern());
28190 // inferred error set.28107 if (sema.fn_ret_ty_ies) |dst_ies| {
28191 try dst_ies.addErrorSet(src_ty, ip, gpa);28108 if (dst_ies.func == dst_ies_func_index) {
28192 return .ok;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 }
28193 }28114 }
2819428115 switch (try sema.resolveInferredErrorSet(block, dest_src, dest_ty.toIntern())) {
28195 try sema.resolveInferredErrorSet(block, dest_src, dst_ies_index);28116 // isAnyError might have changed from a false negative to a true
28196 // isAnyError might have changed from a false negative to a true positive after resolution.28117 // positive after resolution.
28197 if (dest_ty.isAnyError(mod)) {28118 .anyerror_type => return .ok,
28198 return .ok;28119 else => {},
28199 }28120 }
28200 }28121 }
2820128122
...@@ -28210,17 +28131,15 @@ fn coerceInMemoryAllowedErrorSets(...@@ -28210,17 +28131,15 @@ fn coerceInMemoryAllowedErrorSets(
28210 },28131 },
2821128132
28212 else => switch (ip.indexToKey(src_ty.toIntern())) {28133 else => switch (ip.indexToKey(src_ty.toIntern())) {
28213 .inferred_error_set_type => |src_index| {28134 .inferred_error_set_type => {
28214 const src_data = mod.inferredErrorSetPtr(src_index);28135 const resolved_src_ty = try sema.resolveInferredErrorSet(block, src_src, src_ty.toIntern());
28215
28216 try sema.resolveInferredErrorSet(block, src_src, src_index);
28217 // src anyerror status might have changed after the resolution.28136 // src anyerror status might have changed after the resolution.
28218 if (src_ty.isAnyError(mod)) {28137 if (resolved_src_ty == .anyerror_type) {
28219 // dest_ty.isAnyError(mod) == true is already checked for at this point.28138 // dest_ty.isAnyError(mod) == true is already checked for at this point.
28220 return .from_anyerror;28139 return .from_anyerror;
28221 }28140 }
2822228141
28223 for (src_data.errors.keys()) |key| {28142 for (ip.indexToKey(resolved_src_ty).error_set_type.names.get(ip)) |key| {
28224 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) {28143 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) {
28225 try missing_error_buf.append(key);28144 try missing_error_buf.append(key);
28226 }28145 }
...@@ -28235,7 +28154,7 @@ fn coerceInMemoryAllowedErrorSets(...@@ -28235,7 +28154,7 @@ fn coerceInMemoryAllowedErrorSets(
28235 return .ok;28154 return .ok;
28236 },28155 },
28237 .error_set_type => |error_set_type| {28156 .error_set_type => |error_set_type| {
28238 for (error_set_type.names) |name| {28157 for (error_set_type.names.get(ip)) |name| {
28239 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) {28158 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) {
28240 try missing_error_buf.append(name);28159 try missing_error_buf.append(name);
28241 }28160 }
...@@ -28264,11 +28183,12 @@ fn coerceInMemoryAllowedFns(...@@ -28264,11 +28183,12 @@ fn coerceInMemoryAllowedFns(
28264 src_src: LazySrcLoc,28183 src_src: LazySrcLoc,
28265) !InMemoryCoercionResult {28184) !InMemoryCoercionResult {
28266 const mod = sema.mod;28185 const mod = sema.mod;
28186 const ip = &mod.intern_pool;
2826728187
28268 {28188 const dest_info = mod.typeToFunc(dest_ty).?;
28269 const dest_info = mod.typeToFunc(dest_ty).?;28189 const src_info = mod.typeToFunc(src_ty).?;
28270 const src_info = mod.typeToFunc(src_ty).?;
2827128190
28191 {
28272 if (dest_info.is_var_args != src_info.is_var_args) {28192 if (dest_info.is_var_args != src_info.is_var_args) {
28273 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };28193 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
28274 }28194 }
...@@ -28302,9 +28222,6 @@ fn coerceInMemoryAllowedFns(...@@ -28302,9 +28222,6 @@ fn coerceInMemoryAllowedFns(
28302 }28222 }
2830328223
28304 const params_len = params_len: {28224 const params_len = params_len: {
28305 const dest_info = mod.typeToFunc(dest_ty).?;
28306 const src_info = mod.typeToFunc(src_ty).?;
28307
28308 if (dest_info.param_types.len != src_info.param_types.len) {28225 if (dest_info.param_types.len != src_info.param_types.len) {
28309 return InMemoryCoercionResult{ .fn_param_count = .{28226 return InMemoryCoercionResult{ .fn_param_count = .{
28310 .actual = src_info.param_types.len,28227 .actual = src_info.param_types.len,
...@@ -28323,13 +28240,10 @@ fn coerceInMemoryAllowedFns(...@@ -28323,13 +28240,10 @@ fn coerceInMemoryAllowedFns(
28323 };28240 };
2832428241
28325 for (0..params_len) |param_i| {28242 for (0..params_len) |param_i| {
28326 const dest_info = mod.typeToFunc(dest_ty).?;28243 const dest_param_ty = dest_info.param_types.get(ip)[param_i].toType();
28327 const src_info = mod.typeToFunc(src_ty).?;28244 const src_param_ty = src_info.param_types.get(ip)[param_i].toType();
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();
2833128245
28332 const param_i_small = @as(u5, @intCast(param_i));28246 const param_i_small: u5 = @intCast(param_i);
28333 if (dest_info.paramIsComptime(param_i_small) != src_info.paramIsComptime(param_i_small)) {28247 if (dest_info.paramIsComptime(param_i_small) != src_info.paramIsComptime(param_i_small)) {
28334 return InMemoryCoercionResult{ .fn_param_comptime = .{28248 return InMemoryCoercionResult{ .fn_param_comptime = .{
28335 .index = param_i,28249 .index = param_i,
...@@ -30471,6 +30385,7 @@ fn addReferencedBy(...@@ -30471,6 +30385,7 @@ fn addReferencedBy(
3047130385
30472fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {30386fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
30473 const mod = sema.mod;30387 const mod = sema.mod;
30388 const ip = &mod.intern_pool;
30474 const decl = mod.declPtr(decl_index);30389 const decl = mod.declPtr(decl_index);
30475 if (decl.analysis == .in_progress) {30390 if (decl.analysis == .in_progress) {
30476 const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(mod), "dependency loop detected", .{});30391 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 {...@@ -30478,8 +30393,8 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
30478 }30393 }
3047930394
30480 mod.ensureDeclAnalyzed(decl_index) catch |err| {30395 mod.ensureDeclAnalyzed(decl_index) catch |err| {
30481 if (sema.owner_func) |owner_func| {30396 if (sema.owner_func_index != .none) {
30482 owner_func.state = .dependency_failure;30397 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
30483 } else {30398 } else {
30484 sema.owner_decl.analysis = .dependency_failure;30399 sema.owner_decl.analysis = .dependency_failure;
30485 }30400 }
...@@ -30487,10 +30402,12 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {...@@ -30487,10 +30402,12 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
30487 };30402 };
30488}30403}
3048930404
30490fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void {30405fn ensureFuncBodyAnalyzed(sema: *Sema, func: InternPool.Index) CompileError!void {
30491 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {30406 const mod = sema.mod;
30492 if (sema.owner_func) |owner_func| {30407 const ip = &mod.intern_pool;
30493 owner_func.state = .dependency_failure;30408 mod.ensureFuncBodyAnalyzed(func) catch |err| {
30409 if (sema.owner_func_index != .none) {
30410 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
30494 } else {30411 } else {
30495 sema.owner_decl.analysis = .dependency_failure;30412 sema.owner_decl.analysis = .dependency_failure;
30496 }30413 }
...@@ -30566,7 +30483,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {...@@ -30566,7 +30483,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {
30566 const tv = try decl.typedValue();30483 const tv = try decl.typedValue();
30567 if (tv.ty.zigTypeTag(mod) != .Fn) return;30484 if (tv.ty.zigTypeTag(mod) != .Fn) return;
30568 if (!try sema.fnHasRuntimeBits(tv.ty)) return;30485 if (!try sema.fnHasRuntimeBits(tv.ty)) return;
30569 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn30486 const func_index = tv.val.toIntern();
30487 if (!mod.intern_pool.isFuncBody(func_index)) return; // undef or extern function
30570 try mod.ensureFuncBodyAnalysisQueued(func_index);30488 try mod.ensureFuncBodyAnalysisQueued(func_index);
30571}30489}
3057230490
...@@ -30582,7 +30500,7 @@ fn analyzeRef(...@@ -30582,7 +30500,7 @@ fn analyzeRef(
30582 if (try sema.resolveMaybeUndefVal(operand)) |val| {30500 if (try sema.resolveMaybeUndefVal(operand)) |val| {
30583 switch (mod.intern_pool.indexToKey(val.toIntern())) {30501 switch (mod.intern_pool.indexToKey(val.toIntern())) {
30584 .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),30502 .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),
30586 else => {},30504 else => {},
30587 }30505 }
30588 var anon_decl = try block.startAnonDecl();30506 var anon_decl = try block.startAnonDecl();
...@@ -30752,73 +30670,85 @@ fn analyzeIsNonErrComptimeOnly(...@@ -30752,73 +30670,85 @@ fn analyzeIsNonErrComptimeOnly(
30752 operand: Air.Inst.Ref,30670 operand: Air.Inst.Ref,
30753) CompileError!Air.Inst.Ref {30671) CompileError!Air.Inst.Ref {
30754 const mod = sema.mod;30672 const mod = sema.mod;
30673 const ip = &mod.intern_pool;
30755 const operand_ty = sema.typeOf(operand);30674 const operand_ty = sema.typeOf(operand);
30756 const ot = operand_ty.zigTypeTag(mod);30675 const ot = operand_ty.zigTypeTag(mod);
30757 if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true;30676 if (ot != .ErrorSet and ot != .ErrorUnion) return .bool_true;
30758 if (ot == .ErrorSet) return Air.Inst.Ref.bool_false;30677 if (ot == .ErrorSet) return .bool_false;
30759 assert(ot == .ErrorUnion);30678 assert(ot == .ErrorUnion);
3076030679
30761 const payload_ty = operand_ty.errorUnionPayload(mod);30680 const payload_ty = operand_ty.errorUnionPayload(mod);
30762 if (payload_ty.zigTypeTag(mod) == .NoReturn) {30681 if (payload_ty.zigTypeTag(mod) == .NoReturn) {
30763 return Air.Inst.Ref.bool_false;30682 return .bool_false;
30764 }30683 }
3076530684
30766 if (Air.refToIndex(operand)) |operand_inst| {30685 if (Air.refToIndex(operand)) |operand_inst| {
30767 switch (sema.air_instructions.items(.tag)[operand_inst]) {30686 switch (sema.air_instructions.items(.tag)[operand_inst]) {
30768 .wrap_errunion_payload => return Air.Inst.Ref.bool_true,30687 .wrap_errunion_payload => return .bool_true,
30769 .wrap_errunion_err => return Air.Inst.Ref.bool_false,30688 .wrap_errunion_err => return .bool_false,
30770 else => {},30689 else => {},
30771 }30690 }
30772 } else if (operand == .undef) {30691 } else if (operand == .undef) {
30773 return sema.addConstUndef(Type.bool);30692 return sema.addConstUndef(Type.bool);
30774 } else if (@intFromEnum(operand) < InternPool.static_len) {30693 } else if (@intFromEnum(operand) < InternPool.static_len) {
30775 // None of the ref tags can be errors.30694 // None of the ref tags can be errors.
30776 return Air.Inst.Ref.bool_true;30695 return .bool_true;
30777 }30696 }
3077830697
30779 const maybe_operand_val = try sema.resolveMaybeUndefVal(operand);30698 const maybe_operand_val = try sema.resolveMaybeUndefVal(operand);
3078030699
30781 // exception if the error union error set is known to be empty,30700 // exception if the error union error set is known to be empty,
30782 // we allow the comparison but always make it comptime-known.30701 // we allow the comparison but always make it comptime-known.
30783 const set_ty = operand_ty.errorUnionSet(mod);30702 const set_ty = ip.errorUnionSet(operand_ty.toIntern());
30784 switch (set_ty.toIntern()) {30703 switch (set_ty) {
30785 .anyerror_type => {},30704 .anyerror_type => {},
30786 else => switch (mod.intern_pool.indexToKey(set_ty.toIntern())) {30705 else => switch (ip.indexToKey(set_ty)) {
30787 .error_set_type => |error_set_type| {30706 .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;
30789 },30708 },
30790 .inferred_error_set_type => |ies_index| blk: {30709 .inferred_error_set_type => |func_index| blk: {
30791 // If the error set is empty, we must return a comptime true or false.30710 // If the error set is empty, we must return a comptime true or false.
30792 // However we want to avoid unnecessarily resolving an inferred error set30711 // However we want to avoid unnecessarily resolving an inferred error set
30793 // in case it is already non-empty.30712 // in case it is already non-empty.
30794 const ies = mod.inferredErrorSetPtr(ies_index);30713 switch (ip.funcIesResolved(func_index).*) {
30795 if (ies.is_anyerror) break :blk;30714 .anyerror_type => break :blk,
30796 if (ies.errors.count() != 0) break :blk;30715 .none => {},
30716 else => |i| if (ip.indexToKey(i).error_set_type.names.len != 0) break :blk,
30717 }
30797 if (maybe_operand_val == null) {30718 if (maybe_operand_val == null) {
30798 // Try to avoid resolving inferred error set if possible.30719 if (sema.fn_ret_ty_ies) |ies| {
30799 if (ies.errors.count() != 0) break :blk;30720 if (set_ty == .adhoc_inferred_error_set_type or
30800 if (ies.is_anyerror) break :blk;30721 ies.func == func_index)
30801 for (ies.inferred_error_sets.keys()) |other_ies_index| {30722 {
30802 if (ies_index == other_ies_index) continue;30723 // Try to avoid resolving inferred error set if possible.
30803 try sema.resolveInferredErrorSet(block, src, other_ies_index);30724 if (ies.errors.count() != 0) return .none;
30804 const other_ies = mod.inferredErrorSetPtr(other_ies_index);30725 switch (ies.resolved) {
30805 if (other_ies.is_anyerror) {30726 .anyerror_type => return .none,
30806 ies.is_anyerror = true;30727 .none => {},
30807 ies.is_resolved = true;30728 else => switch (ip.indexToKey(ies.resolved).error_set_type.names.len) {
30808 break :blk;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;
30809 }30745 }
30810
30811 if (other_ies.errors.count() != 0) break :blk;
30812 }30746 }
30813 if (ies.func == sema.owner_func_index.unwrap()) {30747 const resolved_ty = try sema.resolveInferredErrorSet(block, src, set_ty);
30814 // We're checking the inferred errorset of the current function and none of30748 if (resolved_ty == .anyerror_type)
30815 // its child inferred error sets contained any errors meaning that any value30749 break :blk;
30816 // so far with this type can't contain errors either.30750 if (ip.indexToKey(resolved_ty).error_set_type.names.len == 0)
30817 return Air.Inst.Ref.bool_true;30751 return .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;
30822 }30752 }
30823 },30753 },
30824 else => unreachable,30754 else => unreachable,
...@@ -30830,12 +30760,12 @@ fn analyzeIsNonErrComptimeOnly(...@@ -30830,12 +30760,12 @@ fn analyzeIsNonErrComptimeOnly(
30830 return sema.addConstUndef(Type.bool);30760 return sema.addConstUndef(Type.bool);
30831 }30761 }
30832 if (err_union.getErrorName(mod) == .none) {30762 if (err_union.getErrorName(mod) == .none) {
30833 return Air.Inst.Ref.bool_true;30763 return .bool_true;
30834 } else {30764 } else {
30835 return Air.Inst.Ref.bool_false;30765 return .bool_false;
30836 }30766 }
30837 }30767 }
30838 return Air.Inst.Ref.none;30768 return .none;
30839}30769}
3084030770
30841fn analyzeIsNonErr(30771fn analyzeIsNonErr(
...@@ -31768,24 +31698,39 @@ fn wrapErrorUnionSet(...@@ -31768,24 +31698,39 @@ fn wrapErrorUnionSet(
31768 const inst_ty = sema.typeOf(inst);31698 const inst_ty = sema.typeOf(inst);
31769 const dest_err_set_ty = dest_ty.errorUnionSet(mod);31699 const dest_err_set_ty = dest_ty.errorUnionSet(mod);
31770 if (try sema.resolveMaybeUndefVal(inst)) |val| {31700 if (try sema.resolveMaybeUndefVal(inst)) |val| {
31701 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
31771 switch (dest_err_set_ty.toIntern()) {31702 switch (dest_err_set_ty.toIntern()) {
31772 .anyerror_type => {},31703 .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 },
31773 else => switch (ip.indexToKey(dest_err_set_ty.toIntern())) {31717 else => switch (ip.indexToKey(dest_err_set_ty.toIntern())) {
31774 .error_set_type => |error_set_type| ok: {31718 .error_set_type => |error_set_type| ok: {
31775 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
31776 if (error_set_type.nameIndex(ip, expected_name) != null) break :ok;31719 if (error_set_type.nameIndex(ip, expected_name) != null) break :ok;
31777 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);31720 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
31778 },31721 },
31779 .inferred_error_set_type => |ies_index| ok: {31722 .inferred_error_set_type => |func_index| ok: {
31780 const ies = mod.inferredErrorSetPtr(ies_index);
31781 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
31782
31783 // We carefully do this in an order that avoids unnecessarily31723 // We carefully do this in an order that avoids unnecessarily
31784 // resolving the destination error set type.31724 // resolving the destination error set type.
31785 if (ies.is_anyerror) break :ok;31725 switch (ip.funcIesResolved(func_index).*) {
3178631726 .anyerror_type => break :ok,
31787 if (ies.errors.contains(expected_name)) break :ok;31727 .none => if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
31788 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) break :ok;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
31790 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);31735 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
31791 },31736 },
...@@ -31794,9 +31739,7 @@ fn wrapErrorUnionSet(...@@ -31794,9 +31739,7 @@ fn wrapErrorUnionSet(
31794 }31739 }
31795 return sema.addConstant((try mod.intern(.{ .error_union = .{31740 return sema.addConstant((try mod.intern(.{ .error_union = .{
31796 .ty = dest_ty.toIntern(),31741 .ty = dest_ty.toIntern(),
31797 .val = .{31742 .val = .{ .err_name = expected_name },
31798 .err_name = mod.intern_pool.indexToKey(try val.intern(dest_err_set_ty, mod)).err.name,
31799 },
31800 } })).toValue());31743 } })).toValue());
31801 }31744 }
3180231745
...@@ -33273,17 +33216,31 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike {...@@ -33273,17 +33216,31 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike {
33273 };33216 };
33274}33217}
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
33276pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {33230pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
33277 const mod = sema.mod;33231 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)) {
33281 // Ensure the type exists so that backends can assume that.33238 // Ensure the type exists so that backends can assume that.
33282 _ = try sema.getBuiltinType("StackTrace");33239 _ = try sema.getBuiltinType("StackTrace");
33283 }33240 }
3328433241
33285 for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| {33242 for (0..fn_ty_info.param_types.len) |i| {
33286 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType());33243 try sema.resolveTypeFully(fn_ty_info.param_types.get(ip)[i].toType());
33287 }33244 }
33288}33245}
3328933246
...@@ -33448,7 +33405,9 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -33448,7 +33405,9 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
33448 // the function is instantiated.33405 // the function is instantiated.
33449 return;33406 return;
33450 }33407 }
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];
33452 try sema.resolveTypeLayout(param_ty.toType());33411 try sema.resolveTypeLayout(param_ty.toType());
33453 }33412 }
33454 try sema.resolveTypeLayout(info.return_type.toType());33413 try sema.resolveTypeLayout(info.return_type.toType());
...@@ -33578,10 +33537,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -33578,10 +33537,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
33578 .code = zir,33537 .code = zir,
33579 .owner_decl = decl,33538 .owner_decl = decl,
33580 .owner_decl_index = decl_index,33539 .owner_decl_index = decl_index,
33581 .func = null,
33582 .func_index = .none,33540 .func_index = .none,
33583 .fn_ret_ty = Type.void,33541 .fn_ret_ty = Type.void,
33584 .owner_func = null,33542 .fn_ret_ty_ies = null,
33585 .owner_func_index = .none,33543 .owner_func_index = .none,
33586 .comptime_mutable_decls = &comptime_mutable_decls,33544 .comptime_mutable_decls = &comptime_mutable_decls,
33587 };33545 };
...@@ -33600,10 +33558,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -33600,10 +33558,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
33600 .inlining = null,33558 .inlining = null,
33601 .is_comptime = true,33559 .is_comptime = true,
33602 };33560 };
33603 defer {33561 defer assert(block.instructions.items.len == 0);
33604 assert(block.instructions.items.len == 0);
33605 block.params.deinit(gpa);
33606 }
3360733562
33608 const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 };33563 const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 };
33609 const backing_int_ty = blk: {33564 const backing_int_ty = blk: {
...@@ -33633,10 +33588,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -33633,10 +33588,9 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
33633 .code = zir,33588 .code = zir,
33634 .owner_decl = decl,33589 .owner_decl = decl,
33635 .owner_decl_index = decl_index,33590 .owner_decl_index = decl_index,
33636 .func = null,
33637 .func_index = .none,33591 .func_index = .none,
33638 .fn_ret_ty = Type.void,33592 .fn_ret_ty = Type.void,
33639 .owner_func = null,33593 .fn_ret_ty_ies = null,
33640 .owner_func_index = .none,33594 .owner_func_index = .none,
33641 .comptime_mutable_decls = undefined,33595 .comptime_mutable_decls = undefined,
33642 };33596 };
...@@ -33808,6 +33762,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33808,6 +33762,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33808 .bool,33762 .bool,
33809 .void,33763 .void,
33810 .anyerror,33764 .anyerror,
33765 .adhoc_inferred_error_set,
33811 .noreturn,33766 .noreturn,
33812 .generic_poison,33767 .generic_poison,
33813 .atomic_order,33768 .atomic_order,
...@@ -33943,7 +33898,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {...@@ -33943,7 +33898,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
33943 // the function is instantiated.33898 // the function is instantiated.
33944 return;33899 return;
33945 }33900 }
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];
33947 try sema.resolveTypeFully(param_ty.toType());33904 try sema.resolveTypeFully(param_ty.toType());
33948 }33905 }
33949 try sema.resolveTypeFully(info.return_type.toType());33906 try sema.resolveTypeFully(info.return_type.toType());
...@@ -34056,6 +34013,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {...@@ -34056,6 +34013,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
34056 .void_type,34013 .void_type,
34057 .type_type,34014 .type_type,
34058 .anyerror_type,34015 .anyerror_type,
34016 .adhoc_inferred_error_set_type,
34059 .comptime_int_type,34017 .comptime_int_type,
34060 .comptime_float_type,34018 .comptime_float_type,
34061 .noreturn_type,34019 .noreturn_type,
...@@ -34209,29 +34167,28 @@ fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_obj: *Module.Union) Compi...@@ -34209,29 +34167,28 @@ fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_obj: *Module.Union) Compi
34209 union_obj.status = .have_field_types;34167 union_obj.status = .have_field_types;
34210}34168}
3421134169
34170/// Returns a normal error set corresponding to the fully populated inferred
34171/// error set.
34212fn resolveInferredErrorSet(34172fn resolveInferredErrorSet(
34213 sema: *Sema,34173 sema: *Sema,
34214 block: *Block,34174 block: *Block,
34215 src: LazySrcLoc,34175 src: LazySrcLoc,
34216 ies_index: Module.Fn.InferredErrorSet.Index,34176 ies_index: InternPool.Index,
34217) CompileError!void {34177) CompileError!InternPool.Index {
34218 const mod = sema.mod;34178 const mod = sema.mod;
34219 const ies = mod.inferredErrorSetPtr(ies_index);34179 const ip = &mod.intern_pool;
3422034180 const func_index = ip.iesFuncIndex(ies_index);
34221 if (ies.is_resolved) return;34181 const func = mod.funcInfo(func_index);
3422234182 const resolved_ty = func.resolvedErrorSet(ip).*;
34223 const func = mod.funcPtr(ies.func);34183 if (resolved_ty != .none) return resolved_ty;
34224 if (func.state == .in_progress) {34184 if (func.analysis(ip).state == .in_progress)
34225 return sema.fail(block, src, "unable to resolve inferred error set", .{});34185 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, we34187 // In order to ensure that all dependencies are properly added to the set,
34229 // need to ensure the function body is analyzed of the inferred error set.34188 // we need to ensure the function body is analyzed of the inferred error
34230 // However, in the case of comptime/inline function calls with inferred error sets,34189 // set. However, in the case of comptime/inline function calls with
34231 // each call gets a new InferredErrorSet object, which contains the same34190 // inferred error sets, each call gets an adhoc InferredErrorSet object, which
34232 // `Module.Fn.Index`. Not only is the function not relevant to the inferred error set34191 // has no corresponding function body.
34233 // in this case, it may be a generic function which would cause an assertion failure
34234 // if we called `ensureFuncBodyAnalyzed` on it here.
34235 const ies_func_owner_decl = mod.declPtr(func.owner_decl);34192 const ies_func_owner_decl = mod.declPtr(func.owner_decl);
34236 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;34193 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;
34237 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,34194 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
...@@ -34239,7 +34196,7 @@ fn resolveInferredErrorSet(...@@ -34239,7 +34196,7 @@ fn resolveInferredErrorSet(
34239 // so here we can simply skip this case.34196 // so here we can simply skip this case.
34240 if (ies_func_info.return_type == .generic_poison_type) {34197 if (ies_func_info.return_type == .generic_poison_type) {
34241 assert(ies_func_info.cc == .Inline);34198 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) {
34243 if (ies_func_info.is_generic) {34200 if (ies_func_info.is_generic) {
34244 const msg = msg: {34201 const msg = msg: {
34245 const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{});34202 const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{});
...@@ -34252,33 +34209,101 @@ fn resolveInferredErrorSet(...@@ -34252,33 +34209,101 @@ fn resolveInferredErrorSet(
34252 }34209 }
34253 // In this case we are dealing with the actual InferredErrorSet object that34210 // In this case we are dealing with the actual InferredErrorSet object that
34254 // corresponds to the function, not one created to track an inline/comptime call.34211 // 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);
34256 }34213 }
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
34260 for (ies.inferred_error_sets.keys()) |other_ies_index| {34235 for (ies.inferred_error_sets.keys()) |other_ies_index| {
34261 if (ies_index == other_ies_index) continue;34236 if (ies_index == other_ies_index) continue;
34262 try sema.resolveInferredErrorSet(block, src, other_ies_index);34237 switch (try sema.resolveInferredErrorSet(block, src, other_ies_index)) {
3426334238 .anyerror_type => {
34264 const other_ies = mod.inferredErrorSetPtr(other_ies_index);34239 ies.resolved = .anyerror_type;
34265 for (other_ies.errors.keys()) |key| {34240 return;
34266 try ies.errors.put(sema.gpa, key, {});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 },
34267 }34248 }
34268 if (other_ies.is_anyerror)
34269 ies.is_anyerror = true;
34270 }34249 }
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;
34271}34292}
3427234293
34273fn resolveInferredErrorSetTy(34294fn resolveInferredErrorSetTy(
34274 sema: *Sema,34295 sema: *Sema,
34275 block: *Block,34296 block: *Block,
34276 src: LazySrcLoc,34297 src: LazySrcLoc,
34277 ty: Type,34298 ty: InternPool.Index,
34278) CompileError!void {34299) CompileError!InternPool.Index {
34279 const mod = sema.mod;34300 const mod = sema.mod;
34280 if (mod.typeToInferredErrorSetIndex(ty).unwrap()) |ies_index| {34301 const ip = &mod.intern_pool;
34281 try sema.resolveInferredErrorSet(block, src, ies_index);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,
34282 }34307 }
34283}34308}
3428434309
...@@ -34346,10 +34371,9 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -34346,10 +34371,9 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
34346 .code = zir,34371 .code = zir,
34347 .owner_decl = decl,34372 .owner_decl = decl,
34348 .owner_decl_index = decl_index,34373 .owner_decl_index = decl_index,
34349 .func = null,
34350 .func_index = .none,34374 .func_index = .none,
34351 .fn_ret_ty = Type.void,34375 .fn_ret_ty = Type.void,
34352 .owner_func = null,34376 .fn_ret_ty_ies = null,
34353 .owner_func_index = .none,34377 .owner_func_index = .none,
34354 .comptime_mutable_decls = &comptime_mutable_decls,34378 .comptime_mutable_decls = &comptime_mutable_decls,
34355 };34379 };
...@@ -34368,10 +34392,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -34368,10 +34392,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
34368 .inlining = null,34392 .inlining = null,
34369 .is_comptime = true,34393 .is_comptime = true,
34370 };34394 };
34371 defer {34395 defer assert(block_scope.instructions.items.len == 0);
34372 assert(block_scope.instructions.items.len == 0);
34373 block_scope.params.deinit(gpa);
34374 }
3437534396
34376 struct_obj.fields = .{};34397 struct_obj.fields = .{};
34377 try struct_obj.fields.ensureTotalCapacity(mod.tmp_hack_arena.allocator(), fields_len);34398 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 {...@@ -34693,10 +34714,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
34693 .code = zir,34714 .code = zir,
34694 .owner_decl = decl,34715 .owner_decl = decl,
34695 .owner_decl_index = decl_index,34716 .owner_decl_index = decl_index,
34696 .func = null,
34697 .func_index = .none,34717 .func_index = .none,
34698 .fn_ret_ty = Type.void,34718 .fn_ret_ty = Type.void,
34699 .owner_func = null,34719 .fn_ret_ty_ies = null,
34700 .owner_func_index = .none,34720 .owner_func_index = .none,
34701 .comptime_mutable_decls = &comptime_mutable_decls,34721 .comptime_mutable_decls = &comptime_mutable_decls,
34702 };34722 };
...@@ -34715,10 +34735,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -34715,10 +34735,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
34715 .inlining = null,34735 .inlining = null,
34716 .is_comptime = true,34736 .is_comptime = true,
34717 };34737 };
34718 defer {34738 defer assert(block_scope.instructions.items.len == 0);
34719 assert(block_scope.instructions.items.len == 0);
34720 block_scope.params.deinit(gpa);
34721 }
3472234739
34723 if (body.len != 0) {34740 if (body.len != 0) {
34724 try sema.analyzeBody(&block_scope, body);34741 try sema.analyzeBody(&block_scope, body);
...@@ -35050,7 +35067,7 @@ fn generateUnionTagTypeNumbered(...@@ -35050,7 +35067,7 @@ fn generateUnionTagTypeNumbered(
35050 errdefer mod.destroyDecl(new_decl_index);35067 errdefer mod.destroyDecl(new_decl_index);
35051 const fqn = try union_obj.getFullyQualifiedName(mod);35068 const fqn = try union_obj.getFullyQualifiedName(mod);
35052 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});35069 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, .{
35054 .ty = Type.noreturn,35071 .ty = Type.noreturn,
35055 .val = Value.@"unreachable",35072 .val = Value.@"unreachable",
35056 }, name);35073 }, name);
...@@ -35101,7 +35118,7 @@ fn generateUnionTagTypeSimple(...@@ -35101,7 +35118,7 @@ fn generateUnionTagTypeSimple(
35101 errdefer mod.destroyDecl(new_decl_index);35118 errdefer mod.destroyDecl(new_decl_index);
35102 const fqn = try union_obj.getFullyQualifiedName(mod);35119 const fqn = try union_obj.getFullyQualifiedName(mod);
35103 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});35120 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, .{
35105 .ty = Type.noreturn,35122 .ty = Type.noreturn,
35106 .val = Value.@"unreachable",35123 .val = Value.@"unreachable",
35107 }, name);35124 }, name);
...@@ -35148,10 +35165,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {...@@ -35148,10 +35165,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
35148 .inlining = null,35165 .inlining = null,
35149 .is_comptime = true,35166 .is_comptime = true,
35150 };35167 };
35151 defer {35168 defer block.instructions.deinit(gpa);
35152 block.instructions.deinit(gpa);
35153 block.params.deinit(gpa);
35154 }
3515535169
35156 const decl_index = try getBuiltinDecl(sema, &block, name);35170 const decl_index = try getBuiltinDecl(sema, &block, name);
35157 return sema.analyzeDeclVal(&block, src, decl_index);35171 return sema.analyzeDeclVal(&block, src, decl_index);
...@@ -35202,10 +35216,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {...@@ -35202,10 +35216,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
35202 .inlining = null,35216 .inlining = null,
35203 .is_comptime = true,35217 .is_comptime = true,
35204 };35218 };
35205 defer {35219 defer block.instructions.deinit(sema.gpa);
35206 block.instructions.deinit(sema.gpa);
35207 block.params.deinit(sema.gpa);
35208 }
35209 const src = LazySrcLoc.nodeOffset(0);35220 const src = LazySrcLoc.nodeOffset(0);
3521035221
35211 const result_ty = sema.analyzeAsType(&block, src, ty_inst) catch |err| switch (err) {35222 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 {...@@ -35261,6 +35272,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35261 .bool_type,35272 .bool_type,
35262 .type_type,35273 .type_type,
35263 .anyerror_type,35274 .anyerror_type,
35275 .adhoc_inferred_error_set_type,
35264 .comptime_int_type,35276 .comptime_int_type,
35265 .comptime_float_type,35277 .comptime_float_type,
35266 .enum_literal_type,35278 .enum_literal_type,
...@@ -35314,6 +35326,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -35314,6 +35326,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35314 .var_args_param_type,35326 .var_args_param_type,
35315 .none,35327 .none,
35316 => unreachable,35328 => unreachable,
35329
35317 _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) {35330 _ => switch (mod.intern_pool.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
35318 .type_int_signed, // i0 handled above35331 .type_int_signed, // i0 handled above
35319 .type_int_unsigned, // u0 handled above35332 .type_int_unsigned, // u0 handled above
...@@ -35322,11 +35335,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -35322,11 +35335,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35322 .type_optional, // ?noreturn handled above35335 .type_optional, // ?noreturn handled above
35323 .type_anyframe,35336 .type_anyframe,
35324 .type_error_union,35337 .type_error_union,
35338 .type_anyerror_union,
35325 .type_error_set,35339 .type_error_set,
35326 .type_inferred_error_set,35340 .type_inferred_error_set,
35327 .type_opaque,35341 .type_opaque,
35328 .type_function,35342 .type_function,
35329 => null,35343 => null,
35344
35330 .simple_type, // handled above35345 .simple_type, // handled above
35331 // values, not types35346 // values, not types
35332 .undef,35347 .undef,
...@@ -35370,7 +35385,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -35370,7 +35385,9 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35370 .float_comptime_float,35385 .float_comptime_float,
35371 .variable,35386 .variable,
35372 .extern_func,35387 .extern_func,
35373 .func,35388 .func_decl,
35389 .func_instance,
35390 .func_coerced,
35374 .only_possible_value,35391 .only_possible_value,
35375 .union_value,35392 .union_value,
35376 .bytes,35393 .bytes,
...@@ -35379,6 +35396,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -35379,6 +35396,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35379 // memoized value, not types35396 // memoized value, not types
35380 .memoized_call,35397 .memoized_call,
35381 => unreachable,35398 => unreachable,
35399
35382 .type_array_big,35400 .type_array_big,
35383 .type_array_small,35401 .type_array_small,
35384 .type_vector,35402 .type_vector,
...@@ -35911,6 +35929,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -35911,6 +35929,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
35911 .prefetch_options,35929 .prefetch_options,
35912 .export_options,35930 .export_options,
35913 .extern_options,35931 .extern_options,
35932 .adhoc_inferred_error_set,
35914 => false,35933 => false,
3591535934
35916 .type,35935 .type,
...@@ -36772,7 +36791,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {...@@ -36772,7 +36791,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {
36772 const arena = sema.arena;36791 const arena = sema.arena;
36773 const lhs_names = lhs.errorSetNames(mod);36792 const lhs_names = lhs.errorSetNames(mod);
36774 const rhs_names = rhs.errorSetNames(mod);36793 const rhs_names = rhs.errorSetNames(mod);
36775 var names: Module.Fn.InferredErrorSet.NameMap = .{};36794 var names: InferredErrorSet.NameMap = .{};
36776 try names.ensureUnusedCapacity(arena, lhs_names.len);36795 try names.ensureUnusedCapacity(arena, lhs_names.len);
3677736796
36778 for (lhs_names) |name| {36797 for (lhs_names) |name| {
src/TypedValue.zig+1-1
...@@ -205,7 +205,7 @@ pub fn print(...@@ -205,7 +205,7 @@ pub fn print(
205 mod.declPtr(extern_func.decl).name.fmt(ip),205 mod.declPtr(extern_func.decl).name.fmt(ip),
206 }),206 }),
207 .func => |func| return writer.print("(function '{}')", .{207 .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),
209 }),209 }),
210 .int => |int| switch (int.storage) {210 .int => |int| switch (int.storage) {
211 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),211 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
src/Zir.zig+20-4
...@@ -65,9 +65,13 @@ pub const ExtraIndex = enum(u32) {...@@ -65,9 +65,13 @@ pub const ExtraIndex = enum(u32) {
65 _,65 _,
66};66};
6767
68fn ExtraData(comptime T: type) type {
69 return struct { data: T, end: usize };
70}
71
68/// Returns the requested data, as well as the new index which is at the start of the72/// Returns the requested data, as well as the new index which is at the start of the
69/// trailers for the object.73/// 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) {
71 const fields = @typeInfo(T).Struct.fields;75 const fields = @typeInfo(T).Struct.fields;
72 var i: usize = index;76 var i: usize = index;
73 var result: T = undefined;77 var result: T = undefined;
...@@ -90,13 +94,24 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en...@@ -90,13 +94,24 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
90 };94 };
91}95}
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
94pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {103pub 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;
96 while (code.string_bytes[end] != 0) {111 while (code.string_bytes[end] != 0) {
97 end += 1;112 end += 1;
98 }113 }
99 return code.string_bytes[index..end :0];114 return code.string_bytes[start..end :0];
100}115}
101116
102pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {117pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
...@@ -2076,6 +2091,7 @@ pub const Inst = struct {...@@ -2076,6 +2091,7 @@ pub const Inst = struct {
2076 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),2091 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
2077 optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),2092 optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type),
2078 anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type),2093 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),
2079 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),2095 generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type),
2080 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),2096 empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type),
2081 undef = @intFromEnum(InternPool.Index.undef),2097 undef = @intFromEnum(InternPool.Index.undef),
src/arch/aarch64/CodeGen.zig+36-31
...@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;...@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
13const TypedValue = @import("../../TypedValue.zig");13const TypedValue = @import("../../TypedValue.zig");
14const link = @import("../../link.zig");14const link = @import("../../link.zig");
15const Module = @import("../../Module.zig");15const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");
16const Compilation = @import("../../Compilation.zig");17const Compilation = @import("../../Compilation.zig");
17const ErrorMsg = Module.ErrorMsg;18const ErrorMsg = Module.ErrorMsg;
18const Target = std.Target;19const Target = std.Target;
...@@ -49,7 +50,8 @@ liveness: Liveness,...@@ -49,7 +50,8 @@ liveness: Liveness,
49bin_file: *link.File,50bin_file: *link.File,
50debug_output: DebugInfoOutput,51debug_output: DebugInfoOutput,
51target: *const std.Target,52target: *const std.Target,
52mod_fn: *const Module.Fn,53func_index: InternPool.Index,
54owner_decl: Module.Decl.Index,
53err_msg: ?*ErrorMsg,55err_msg: ?*ErrorMsg,
54args: []MCValue,56args: []MCValue,
55ret_mcv: MCValue,57ret_mcv: MCValue,
...@@ -199,7 +201,7 @@ const DbgInfoReloc = struct {...@@ -199,7 +201,7 @@ const DbgInfoReloc = struct {
199 else => unreachable, // not a possible argument201 else => unreachable, // not a possible argument
200202
201 };203 };
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);
203 },205 },
204 .plan9 => {},206 .plan9 => {},
205 .none => {},207 .none => {},
...@@ -245,7 +247,7 @@ const DbgInfoReloc = struct {...@@ -245,7 +247,7 @@ const DbgInfoReloc = struct {
245 break :blk .nop;247 break :blk .nop;
246 },248 },
247 };249 };
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);
249 },251 },
250 .plan9 => {},252 .plan9 => {},
251 .none => {},253 .none => {},
...@@ -328,7 +330,7 @@ const Self = @This();...@@ -328,7 +330,7 @@ const Self = @This();
328pub fn generate(330pub fn generate(
329 bin_file: *link.File,331 bin_file: *link.File,
330 src_loc: Module.SrcLoc,332 src_loc: Module.SrcLoc,
331 module_fn_index: Module.Fn.Index,333 func_index: InternPool.Index,
332 air: Air,334 air: Air,
333 liveness: Liveness,335 liveness: Liveness,
334 code: *std.ArrayList(u8),336 code: *std.ArrayList(u8),
...@@ -339,8 +341,8 @@ pub fn generate(...@@ -339,8 +341,8 @@ pub fn generate(
339 }341 }
340342
341 const mod = bin_file.options.module.?;343 const mod = bin_file.options.module.?;
342 const module_fn = mod.funcPtr(module_fn_index);344 const func = mod.funcInfo(func_index);
343 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);345 const fn_owner_decl = mod.declPtr(func.owner_decl);
344 assert(fn_owner_decl.has_tv);346 assert(fn_owner_decl.has_tv);
345 const fn_type = fn_owner_decl.ty;347 const fn_type = fn_owner_decl.ty;
346348
...@@ -359,7 +361,8 @@ pub fn generate(...@@ -359,7 +361,8 @@ pub fn generate(
359 .debug_output = debug_output,361 .debug_output = debug_output,
360 .target = &bin_file.options.target,362 .target = &bin_file.options.target,
361 .bin_file = bin_file,363 .bin_file = bin_file,
362 .mod_fn = module_fn,364 .func_index = func_index,
365 .owner_decl = func.owner_decl,
363 .err_msg = null,366 .err_msg = null,
364 .args = undefined, // populated after `resolveCallingConventionValues`367 .args = undefined, // populated after `resolveCallingConventionValues`
365 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`368 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
...@@ -368,8 +371,8 @@ pub fn generate(...@@ -368,8 +371,8 @@ pub fn generate(
368 .branch_stack = &branch_stack,371 .branch_stack = &branch_stack,
369 .src_loc = src_loc,372 .src_loc = src_loc,
370 .stack_align = undefined,373 .stack_align = undefined,
371 .end_di_line = module_fn.rbrace_line,374 .end_di_line = func.rbrace_line,
372 .end_di_column = module_fn.rbrace_column,375 .end_di_column = func.rbrace_column,
373 };376 };
374 defer function.stack.deinit(bin_file.allocator);377 defer function.stack.deinit(bin_file.allocator);
375 defer function.blocks.deinit(bin_file.allocator);378 defer function.blocks.deinit(bin_file.allocator);
...@@ -416,8 +419,8 @@ pub fn generate(...@@ -416,8 +419,8 @@ pub fn generate(
416 .src_loc = src_loc,419 .src_loc = src_loc,
417 .code = code,420 .code = code,
418 .prev_di_pc = 0,421 .prev_di_pc = 0,
419 .prev_di_line = module_fn.lbrace_line,422 .prev_di_line = func.lbrace_line,
420 .prev_di_column = module_fn.lbrace_column,423 .prev_di_column = func.lbrace_column,
421 .stack_size = function.max_end_stack,424 .stack_size = function.max_end_stack,
422 .saved_regs_stack_space = function.saved_regs_stack_space,425 .saved_regs_stack_space = function.saved_regs_stack_space,
423 };426 };
...@@ -4011,12 +4014,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -4011,12 +4014,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
4011 const atom_index = switch (self.bin_file.tag) {4014 const atom_index = switch (self.bin_file.tag) {
4012 .macho => blk: {4015 .macho => blk: {
4013 const macho_file = self.bin_file.cast(link.File.MachO).?;4016 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);
4015 break :blk macho_file.getAtom(atom).getSymbolIndex().?;4018 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
4016 },4019 },
4017 .coff => blk: {4020 .coff => blk: {
4018 const coff_file = self.bin_file.cast(link.File.Coff).?;4021 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);
4020 break :blk coff_file.getAtom(atom).getSymbolIndex().?;4023 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
4021 },4024 },
4022 else => unreachable, // unsupported target format4025 else => unreachable, // unsupported target format
...@@ -4190,10 +4193,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -4190,10 +4193,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
4190 while (self.args[arg_index] == .none) arg_index += 1;4193 while (self.args[arg_index] == .none) arg_index += 1;
4191 self.arg_index = arg_index + 1;4194 self.arg_index = arg_index + 1;
41924195
4196 const mod = self.bin_file.options.module.?;
4193 const ty = self.typeOfIndex(inst);4197 const ty = self.typeOfIndex(inst);
4194 const tag = self.air.instructions.items(.tag)[inst];4198 const tag = self.air.instructions.items(.tag)[inst];
4195 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;4199 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
4198 try self.dbg_info_relocs.append(self.gpa, .{4202 try self.dbg_info_relocs.append(self.gpa, .{
4199 .tag = tag,4203 .tag = tag,
...@@ -4348,7 +4352,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4348,7 +4352,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4348 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);4352 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
4349 if (self.bin_file.cast(link.File.MachO)) |macho_file| {4353 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4350 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);4354 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);
4352 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;4356 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
4353 _ = try self.addInst(.{4357 _ = try self.addInst(.{
4354 .tag = .call_extern,4358 .tag = .call_extern,
...@@ -4617,9 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4617,9 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
4617fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {4621fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4618 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;4622 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
4619 const mod = self.bin_file.options.module.?;4623 const mod = self.bin_file.options.module.?;
4620 const function = mod.funcPtr(ty_fn.func);4624 const func = mod.funcInfo(ty_fn.func);
4621 // TODO emit debug info for function change4625 // TODO emit debug info for function change
4622 _ = function;4626 _ = func;
4623 return self.finishAir(inst, .dead, .{ .none, .none, .none });4627 return self.finishAir(inst, .dead, .{ .none, .none, .none });
4624}4628}
46254629
...@@ -5529,12 +5533,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5529,12 +5533,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5529 const atom_index = switch (self.bin_file.tag) {5533 const atom_index = switch (self.bin_file.tag) {
5530 .macho => blk: {5534 .macho => blk: {
5531 const macho_file = self.bin_file.cast(link.File.MachO).?;5535 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);
5533 break :blk macho_file.getAtom(atom).getSymbolIndex().?;5537 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5534 },5538 },
5535 .coff => blk: {5539 .coff => blk: {
5536 const coff_file = self.bin_file.cast(link.File.Coff).?;5540 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);
5538 break :blk coff_file.getAtom(atom).getSymbolIndex().?;5542 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
5539 },5543 },
5540 else => unreachable, // unsupported target format5544 else => unreachable, // unsupported target format
...@@ -5650,12 +5654,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5650,12 +5654,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5650 const atom_index = switch (self.bin_file.tag) {5654 const atom_index = switch (self.bin_file.tag) {
5651 .macho => blk: {5655 .macho => blk: {
5652 const macho_file = self.bin_file.cast(link.File.MachO).?;5656 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);
5654 break :blk macho_file.getAtom(atom).getSymbolIndex().?;5658 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5655 },5659 },
5656 .coff => blk: {5660 .coff => blk: {
5657 const coff_file = self.bin_file.cast(link.File.Coff).?;5661 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);
5659 break :blk coff_file.getAtom(atom).getSymbolIndex().?;5663 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
5660 },5664 },
5661 else => unreachable, // unsupported target format5665 else => unreachable, // unsupported target format
...@@ -5847,12 +5851,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5847,12 +5851,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5847 const atom_index = switch (self.bin_file.tag) {5851 const atom_index = switch (self.bin_file.tag) {
5848 .macho => blk: {5852 .macho => blk: {
5849 const macho_file = self.bin_file.cast(link.File.MachO).?;5853 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);
5851 break :blk macho_file.getAtom(atom).getSymbolIndex().?;5855 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5852 },5856 },
5853 .coff => blk: {5857 .coff => blk: {
5854 const coff_file = self.bin_file.cast(link.File.Coff).?;5858 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);
5856 break :blk coff_file.getAtom(atom).getSymbolIndex().?;5860 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
5857 },5861 },
5858 else => unreachable, // unsupported target format5862 else => unreachable, // unsupported target format
...@@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6164 self.bin_file,6168 self.bin_file,
6165 self.src_loc,6169 self.src_loc,
6166 arg_tv,6170 arg_tv,
6167 self.mod_fn.owner_decl,6171 self.owner_decl,
6168 )) {6172 )) {
6169 .mcv => |mcv| switch (mcv) {6173 .mcv => |mcv| switch (mcv) {
6170 .none => .none,6174 .none => .none,
...@@ -6198,6 +6202,7 @@ const CallMCValues = struct {...@@ -6198,6 +6202,7 @@ const CallMCValues = struct {
6198/// Caller must call `CallMCValues.deinit`.6202/// Caller must call `CallMCValues.deinit`.
6199fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {6203fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6200 const mod = self.bin_file.options.module.?;6204 const mod = self.bin_file.options.module.?;
6205 const ip = &mod.intern_pool;
6201 const fn_info = mod.typeToFunc(fn_ty).?;6206 const fn_info = mod.typeToFunc(fn_ty).?;
6202 const cc = fn_info.cc;6207 const cc = fn_info.cc;
6203 var result: CallMCValues = .{6208 var result: CallMCValues = .{
...@@ -6240,10 +6245,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6240,10 +6245,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6240 }6245 }
6241 }6246 }
62426247
6243 for (fn_info.param_types, 0..) |ty, i| {6248 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
6244 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));6249 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
6245 if (param_size == 0) {6250 if (param_size == 0) {
6246 result.args[i] = .{ .none = {} };6251 result_arg.* = .{ .none = {} };
6247 continue;6252 continue;
6248 }6253 }
62496254
...@@ -6256,7 +6261,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6256,7 +6261,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62566261
6257 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {6262 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
6258 if (param_size <= 8) {6263 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()) };
6260 ncrn += 1;6265 ncrn += 1;
6261 } else {6266 } else {
6262 return self.fail("TODO MCValues with multiple registers", .{});6267 return self.fail("TODO MCValues with multiple registers", .{});
...@@ -6273,7 +6278,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6273,7 +6278,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6273 }6278 }
6274 }6279 }
62756280
6276 result.args[i] = .{ .stack_argument_offset = nsaa };6281 result_arg.* = .{ .stack_argument_offset = nsaa };
6277 nsaa += param_size;6282 nsaa += param_size;
6278 }6283 }
6279 }6284 }
...@@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
63056310
6306 var stack_offset: u32 = 0;6311 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| {
6309 if (ty.toType().abiSize(mod) > 0) {6314 if (ty.toType().abiSize(mod) > 0) {
6310 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));6315 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
6311 const param_alignment = ty.toType().abiAlignment(mod);6316 const param_alignment = ty.toType().abiAlignment(mod);
63126317
6313 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);6318 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 };
6315 stack_offset += param_size;6320 stack_offset += param_size;
6316 } else {6321 } else {
6317 result.args[i] = .{ .none = {} };6322 result_arg.* = .{ .none = {} };
6318 }6323 }
6319 }6324 }
63206325
src/arch/arm/CodeGen.zig+27-21
...@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;...@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
13const TypedValue = @import("../../TypedValue.zig");13const TypedValue = @import("../../TypedValue.zig");
14const link = @import("../../link.zig");14const link = @import("../../link.zig");
15const Module = @import("../../Module.zig");15const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");
16const Compilation = @import("../../Compilation.zig");17const Compilation = @import("../../Compilation.zig");
17const ErrorMsg = Module.ErrorMsg;18const ErrorMsg = Module.ErrorMsg;
18const Target = std.Target;19const Target = std.Target;
...@@ -50,7 +51,7 @@ liveness: Liveness,...@@ -50,7 +51,7 @@ liveness: Liveness,
50bin_file: *link.File,51bin_file: *link.File,
51debug_output: DebugInfoOutput,52debug_output: DebugInfoOutput,
52target: *const std.Target,53target: *const std.Target,
53mod_fn: *const Module.Fn,54func_index: InternPool.Index,
54err_msg: ?*ErrorMsg,55err_msg: ?*ErrorMsg,
55args: []MCValue,56args: []MCValue,
56ret_mcv: MCValue,57ret_mcv: MCValue,
...@@ -258,6 +259,7 @@ const DbgInfoReloc = struct {...@@ -258,6 +259,7 @@ const DbgInfoReloc = struct {
258 }259 }
259260
260 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {261 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
262 const mod = function.bin_file.options.module.?;
261 switch (function.debug_output) {263 switch (function.debug_output) {
262 .dwarf => |dw| {264 .dwarf => |dw| {
263 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {265 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {
...@@ -278,7 +280,7 @@ const DbgInfoReloc = struct {...@@ -278,7 +280,7 @@ const DbgInfoReloc = struct {
278 else => unreachable, // not a possible argument280 else => unreachable, // not a possible argument
279 };281 };
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);
282 },284 },
283 .plan9 => {},285 .plan9 => {},
284 .none => {},286 .none => {},
...@@ -286,6 +288,7 @@ const DbgInfoReloc = struct {...@@ -286,6 +288,7 @@ const DbgInfoReloc = struct {
286 }288 }
287289
288 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {290 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
291 const mod = function.bin_file.options.module.?;
289 const is_ptr = switch (reloc.tag) {292 const is_ptr = switch (reloc.tag) {
290 .dbg_var_ptr => true,293 .dbg_var_ptr => true,
291 .dbg_var_val => false,294 .dbg_var_val => false,
...@@ -321,7 +324,7 @@ const DbgInfoReloc = struct {...@@ -321,7 +324,7 @@ const DbgInfoReloc = struct {
321 break :blk .nop;324 break :blk .nop;
322 },325 },
323 };326 };
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);
325 },328 },
326 .plan9 => {},329 .plan9 => {},
327 .none => {},330 .none => {},
...@@ -334,7 +337,7 @@ const Self = @This();...@@ -334,7 +337,7 @@ const Self = @This();
334pub fn generate(337pub fn generate(
335 bin_file: *link.File,338 bin_file: *link.File,
336 src_loc: Module.SrcLoc,339 src_loc: Module.SrcLoc,
337 module_fn_index: Module.Fn.Index,340 func_index: InternPool.Index,
338 air: Air,341 air: Air,
339 liveness: Liveness,342 liveness: Liveness,
340 code: *std.ArrayList(u8),343 code: *std.ArrayList(u8),
...@@ -345,8 +348,8 @@ pub fn generate(...@@ -345,8 +348,8 @@ pub fn generate(
345 }348 }
346349
347 const mod = bin_file.options.module.?;350 const mod = bin_file.options.module.?;
348 const module_fn = mod.funcPtr(module_fn_index);351 const func = mod.funcInfo(func_index);
349 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);352 const fn_owner_decl = mod.declPtr(func.owner_decl);
350 assert(fn_owner_decl.has_tv);353 assert(fn_owner_decl.has_tv);
351 const fn_type = fn_owner_decl.ty;354 const fn_type = fn_owner_decl.ty;
352355
...@@ -365,7 +368,7 @@ pub fn generate(...@@ -365,7 +368,7 @@ pub fn generate(
365 .target = &bin_file.options.target,368 .target = &bin_file.options.target,
366 .bin_file = bin_file,369 .bin_file = bin_file,
367 .debug_output = debug_output,370 .debug_output = debug_output,
368 .mod_fn = module_fn,371 .func_index = func_index,
369 .err_msg = null,372 .err_msg = null,
370 .args = undefined, // populated after `resolveCallingConventionValues`373 .args = undefined, // populated after `resolveCallingConventionValues`
371 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`374 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
...@@ -374,8 +377,8 @@ pub fn generate(...@@ -374,8 +377,8 @@ pub fn generate(
374 .branch_stack = &branch_stack,377 .branch_stack = &branch_stack,
375 .src_loc = src_loc,378 .src_loc = src_loc,
376 .stack_align = undefined,379 .stack_align = undefined,
377 .end_di_line = module_fn.rbrace_line,380 .end_di_line = func.rbrace_line,
378 .end_di_column = module_fn.rbrace_column,381 .end_di_column = func.rbrace_column,
379 };382 };
380 defer function.stack.deinit(bin_file.allocator);383 defer function.stack.deinit(bin_file.allocator);
381 defer function.blocks.deinit(bin_file.allocator);384 defer function.blocks.deinit(bin_file.allocator);
...@@ -422,8 +425,8 @@ pub fn generate(...@@ -422,8 +425,8 @@ pub fn generate(
422 .src_loc = src_loc,425 .src_loc = src_loc,
423 .code = code,426 .code = code,
424 .prev_di_pc = 0,427 .prev_di_pc = 0,
425 .prev_di_line = module_fn.lbrace_line,428 .prev_di_line = func.lbrace_line,
426 .prev_di_column = module_fn.lbrace_column,429 .prev_di_column = func.lbrace_column,
427 .stack_size = function.max_end_stack,430 .stack_size = function.max_end_stack,
428 .saved_regs_stack_space = function.saved_regs_stack_space,431 .saved_regs_stack_space = function.saved_regs_stack_space,
429 };432 };
...@@ -4163,10 +4166,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -4163,10 +4166,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
4163 while (self.args[arg_index] == .none) arg_index += 1;4166 while (self.args[arg_index] == .none) arg_index += 1;
4164 self.arg_index = arg_index + 1;4167 self.arg_index = arg_index + 1;
41654168
4169 const mod = self.bin_file.options.module.?;
4166 const ty = self.typeOfIndex(inst);4170 const ty = self.typeOfIndex(inst);
4167 const tag = self.air.instructions.items(.tag)[inst];4171 const tag = self.air.instructions.items(.tag)[inst];
4168 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;4172 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
4171 try self.dbg_info_relocs.append(self.gpa, .{4175 try self.dbg_info_relocs.append(self.gpa, .{
4172 .tag = tag,4176 .tag = tag,
...@@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
4569fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {4573fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4570 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;4574 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
4571 const mod = self.bin_file.options.module.?;4575 const mod = self.bin_file.options.module.?;
4572 const function = mod.funcPtr(ty_fn.func);4576 const func = mod.funcInfo(ty_fn.func);
4573 // TODO emit debug info for function change4577 // TODO emit debug info for function change
4574 _ = function;4578 _ = func;
4575 return self.finishAir(inst, .dead, .{ .none, .none, .none });4579 return self.finishAir(inst, .dead, .{ .none, .none, .none });
4576}4580}
45774581
...@@ -6113,11 +6117,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -6113,11 +6117,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
6113}6117}
61146118
6115fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {6119fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6120 const mod = self.bin_file.options.module.?;
6116 const mcv: MCValue = switch (try codegen.genTypedValue(6121 const mcv: MCValue = switch (try codegen.genTypedValue(
6117 self.bin_file,6122 self.bin_file,
6118 self.src_loc,6123 self.src_loc,
6119 arg_tv,6124 arg_tv,
6120 self.mod_fn.owner_decl,6125 mod.funcOwnerDeclIndex(self.func_index),
6121 )) {6126 )) {
6122 .mcv => |mcv| switch (mcv) {6127 .mcv => |mcv| switch (mcv) {
6123 .none => .none,6128 .none => .none,
...@@ -6149,6 +6154,7 @@ const CallMCValues = struct {...@@ -6149,6 +6154,7 @@ const CallMCValues = struct {
6149/// Caller must call `CallMCValues.deinit`.6154/// Caller must call `CallMCValues.deinit`.
6150fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {6155fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6151 const mod = self.bin_file.options.module.?;6156 const mod = self.bin_file.options.module.?;
6157 const ip = &mod.intern_pool;
6152 const fn_info = mod.typeToFunc(fn_ty).?;6158 const fn_info = mod.typeToFunc(fn_ty).?;
6153 const cc = fn_info.cc;6159 const cc = fn_info.cc;
6154 var result: CallMCValues = .{6160 var result: CallMCValues = .{
...@@ -6194,14 +6200,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6194,14 +6200,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6194 }6200 }
6195 }6201 }
61966202
6197 for (fn_info.param_types, 0..) |ty, i| {6203 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
6198 if (ty.toType().abiAlignment(mod) == 8)6204 if (ty.toType().abiAlignment(mod) == 8)
6199 ncrn = std.mem.alignForward(usize, ncrn, 2);6205 ncrn = std.mem.alignForward(usize, ncrn, 2);
62006206
6201 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));6207 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
6202 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {6208 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
6203 if (param_size <= 4) {6209 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] };
6205 ncrn += 1;6211 ncrn += 1;
6206 } else {6212 } else {
6207 return self.fail("TODO MCValues with multiple registers", .{});6213 return self.fail("TODO MCValues with multiple registers", .{});
...@@ -6213,7 +6219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6213,7 +6219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6213 if (ty.toType().abiAlignment(mod) == 8)6219 if (ty.toType().abiAlignment(mod) == 8)
6214 nsaa = std.mem.alignForward(u32, nsaa, 8);6220 nsaa = std.mem.alignForward(u32, nsaa, 8);
62156221
6216 result.args[i] = .{ .stack_argument_offset = nsaa };6222 result_arg.* = .{ .stack_argument_offset = nsaa };
6217 nsaa += param_size;6223 nsaa += param_size;
6218 }6224 }
6219 }6225 }
...@@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62446250
6245 var stack_offset: u32 = 0;6251 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| {
6248 if (ty.toType().abiSize(mod) > 0) {6254 if (ty.toType().abiSize(mod) > 0) {
6249 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));6255 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
6250 const param_alignment = ty.toType().abiAlignment(mod);6256 const param_alignment = ty.toType().abiAlignment(mod);
62516257
6252 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);6258 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 };
6254 stack_offset += param_size;6260 stack_offset += param_size;
6255 } else {6261 } else {
6256 result.args[i] = .{ .none = {} };6262 result_arg.* = .{ .none = {} };
6257 }6263 }
6258 }6264 }
62596265
src/arch/riscv64/CodeGen.zig+46-37
...@@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value;...@@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value;
12const TypedValue = @import("../../TypedValue.zig");12const TypedValue = @import("../../TypedValue.zig");
13const link = @import("../../link.zig");13const link = @import("../../link.zig");
14const Module = @import("../../Module.zig");14const Module = @import("../../Module.zig");
15const InternPool = @import("../../InternPool.zig");
15const Compilation = @import("../../Compilation.zig");16const Compilation = @import("../../Compilation.zig");
16const ErrorMsg = Module.ErrorMsg;17const ErrorMsg = Module.ErrorMsg;
17const Target = std.Target;18const Target = std.Target;
...@@ -43,7 +44,7 @@ air: Air,...@@ -43,7 +44,7 @@ air: Air,
43liveness: Liveness,44liveness: Liveness,
44bin_file: *link.File,45bin_file: *link.File,
45target: *const std.Target,46target: *const std.Target,
46mod_fn: *const Module.Fn,47func_index: InternPool.Index,
47code: *std.ArrayList(u8),48code: *std.ArrayList(u8),
48debug_output: DebugInfoOutput,49debug_output: DebugInfoOutput,
49err_msg: ?*ErrorMsg,50err_msg: ?*ErrorMsg,
...@@ -217,7 +218,7 @@ const Self = @This();...@@ -217,7 +218,7 @@ const Self = @This();
217pub fn generate(218pub fn generate(
218 bin_file: *link.File,219 bin_file: *link.File,
219 src_loc: Module.SrcLoc,220 src_loc: Module.SrcLoc,
220 module_fn_index: Module.Fn.Index,221 func_index: InternPool.Index,
221 air: Air,222 air: Air,
222 liveness: Liveness,223 liveness: Liveness,
223 code: *std.ArrayList(u8),224 code: *std.ArrayList(u8),
...@@ -228,8 +229,8 @@ pub fn generate(...@@ -228,8 +229,8 @@ pub fn generate(
228 }229 }
229230
230 const mod = bin_file.options.module.?;231 const mod = bin_file.options.module.?;
231 const module_fn = mod.funcPtr(module_fn_index);232 const func = mod.funcInfo(func_index);
232 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);233 const fn_owner_decl = mod.declPtr(func.owner_decl);
233 assert(fn_owner_decl.has_tv);234 assert(fn_owner_decl.has_tv);
234 const fn_type = fn_owner_decl.ty;235 const fn_type = fn_owner_decl.ty;
235236
...@@ -247,7 +248,7 @@ pub fn generate(...@@ -247,7 +248,7 @@ pub fn generate(
247 .liveness = liveness,248 .liveness = liveness,
248 .target = &bin_file.options.target,249 .target = &bin_file.options.target,
249 .bin_file = bin_file,250 .bin_file = bin_file,
250 .mod_fn = module_fn,251 .func_index = func_index,
251 .code = code,252 .code = code,
252 .debug_output = debug_output,253 .debug_output = debug_output,
253 .err_msg = null,254 .err_msg = null,
...@@ -258,8 +259,8 @@ pub fn generate(...@@ -258,8 +259,8 @@ pub fn generate(
258 .branch_stack = &branch_stack,259 .branch_stack = &branch_stack,
259 .src_loc = src_loc,260 .src_loc = src_loc,
260 .stack_align = undefined,261 .stack_align = undefined,
261 .end_di_line = module_fn.rbrace_line,262 .end_di_line = func.rbrace_line,
262 .end_di_column = module_fn.rbrace_column,263 .end_di_column = func.rbrace_column,
263 };264 };
264 defer function.stack.deinit(bin_file.allocator);265 defer function.stack.deinit(bin_file.allocator);
265 defer function.blocks.deinit(bin_file.allocator);266 defer function.blocks.deinit(bin_file.allocator);
...@@ -301,8 +302,8 @@ pub fn generate(...@@ -301,8 +302,8 @@ pub fn generate(
301 .src_loc = src_loc,302 .src_loc = src_loc,
302 .code = code,303 .code = code,
303 .prev_di_pc = 0,304 .prev_di_pc = 0,
304 .prev_di_line = module_fn.lbrace_line,305 .prev_di_line = func.lbrace_line,
305 .prev_di_column = module_fn.lbrace_column,306 .prev_di_column = func.lbrace_column,
306 };307 };
307 defer emit.deinit();308 defer emit.deinit();
308309
...@@ -1627,13 +1628,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1627,13 +1628,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
1627}1628}
16281629
1629fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {1630fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
1631 const mod = self.bin_file.options.module.?;
1630 const arg = self.air.instructions.items(.data)[inst].arg;1632 const arg = self.air.instructions.items(.data)[inst].arg;
1631 const ty = self.air.getRefType(arg.ty);1633 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
1634 switch (self.debug_output) {1637 switch (self.debug_output) {
1635 .dwarf => |dw| switch (mcv) {1638 .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, .{
1637 .register = reg.dwarfLocOp(),1640 .register = reg.dwarfLocOp(),
1638 }),1641 }),
1639 .stack_offset => {},1642 .stack_offset => {},
...@@ -1742,24 +1745,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1742,24 +1745,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1742 }1745 }
17431746
1744 if (try self.air.value(callee, mod)) |func_value| {1747 if (try self.air.value(callee, mod)) |func_value| {
1745 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {1748 switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
1746 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);1749 .func => |func| {
1747 const atom = elf_file.getAtom(atom_index);1750 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1748 _ = try atom.getOrCreateOffsetTableEntry(elf_file);1751 const atom = elf_file.getAtom(atom_index);
1749 const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));1752 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1750 try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });1753 const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1751 _ = try self.addInst(.{1754 try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
1752 .tag = .jalr,1755 _ = try self.addInst(.{
1753 .data = .{ .i_type = .{1756 .tag = .jalr,
1754 .rd = .ra,1757 .data = .{ .i_type = .{
1755 .rs1 = .ra,1758 .rd = .ra,
1756 .imm12 = 0,1759 .rs1 = .ra,
1757 } },1760 .imm12 = 0,
1758 });1761 } },
1759 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {1762 });
1760 return self.fail("TODO implement calling extern functions", .{});1763 },
1761 } else {1764 .extern_func => {
1762 return self.fail("TODO implement calling bitcasted functions", .{});1765 return self.fail("TODO implement calling extern functions", .{});
1766 },
1767 else => {
1768 return self.fail("TODO implement calling bitcasted functions", .{});
1769 },
1763 }1770 }
1764 } else {1771 } else {
1765 return self.fail("TODO implement calling runtime-known function pointer", .{});1772 return self.fail("TODO implement calling runtime-known function pointer", .{});
...@@ -1876,9 +1883,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -1876,9 +1883,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
1876fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {1883fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1877 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;1884 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
1878 const mod = self.bin_file.options.module.?;1885 const mod = self.bin_file.options.module.?;
1879 const function = mod.funcPtr(ty_fn.func);1886 const func = mod.funcInfo(ty_fn.func);
1880 // TODO emit debug info for function change1887 // TODO emit debug info for function change
1881 _ = function;1888 _ = func;
1882 return self.finishAir(inst, .dead, .{ .none, .none, .none });1889 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1883}1890}
18841891
...@@ -2569,11 +2576,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -2569,11 +2576,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
2569}2576}
25702577
2571fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {2578fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
2579 const mod = self.bin_file.options.module.?;
2572 const mcv: MCValue = switch (try codegen.genTypedValue(2580 const mcv: MCValue = switch (try codegen.genTypedValue(
2573 self.bin_file,2581 self.bin_file,
2574 self.src_loc,2582 self.src_loc,
2575 typed_value,2583 typed_value,
2576 self.mod_fn.owner_decl,2584 mod.funcOwnerDeclIndex(self.func_index),
2577 )) {2585 )) {
2578 .mcv => |mcv| switch (mcv) {2586 .mcv => |mcv| switch (mcv) {
2579 .none => .none,2587 .none => .none,
...@@ -2605,6 +2613,7 @@ const CallMCValues = struct {...@@ -2605,6 +2613,7 @@ const CallMCValues = struct {
2605/// Caller must call `CallMCValues.deinit`.2613/// Caller must call `CallMCValues.deinit`.
2606fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {2614fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2607 const mod = self.bin_file.options.module.?;2615 const mod = self.bin_file.options.module.?;
2616 const ip = &mod.intern_pool;
2608 const fn_info = mod.typeToFunc(fn_ty).?;2617 const fn_info = mod.typeToFunc(fn_ty).?;
2609 const cc = fn_info.cc;2618 const cc = fn_info.cc;
2610 var result: CallMCValues = .{2619 var result: CallMCValues = .{
...@@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2636 var next_stack_offset: u32 = 0;2645 var next_stack_offset: u32 = 0;
2637 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };2646 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| {
2640 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));2649 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
2641 if (param_size <= 8) {2650 if (param_size <= 8) {
2642 if (next_register < argument_registers.len) {2651 if (next_register < argument_registers.len) {
2643 result.args[i] = .{ .register = argument_registers[next_register] };2652 result_arg.* = .{ .register = argument_registers[next_register] };
2644 next_register += 1;2653 next_register += 1;
2645 } else {2654 } else {
2646 result.args[i] = .{ .stack_offset = next_stack_offset };2655 result_arg.* = .{ .stack_offset = next_stack_offset };
2647 next_register += next_stack_offset;2656 next_register += next_stack_offset;
2648 }2657 }
2649 } else if (param_size <= 16) {2658 } else if (param_size <= 16) {
...@@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2652 } else if (next_register < argument_registers.len) {2661 } else if (next_register < argument_registers.len) {
2653 return self.fail("TODO MCValues split register + stack", .{});2662 return self.fail("TODO MCValues split register + stack", .{});
2654 } else {2663 } else {
2655 result.args[i] = .{ .stack_offset = next_stack_offset };2664 result_arg.* = .{ .stack_offset = next_stack_offset };
2656 next_register += next_stack_offset;2665 next_register += next_stack_offset;
2657 }2666 }
2658 } else {2667 } else {
2659 result.args[i] = .{ .stack_offset = next_stack_offset };2668 result_arg.* = .{ .stack_offset = next_stack_offset };
2660 next_register += next_stack_offset;2669 next_register += next_stack_offset;
2661 }2670 }
2662 }2671 }
src/arch/sparc64/CodeGen.zig+55-46
...@@ -11,6 +11,7 @@ const Allocator = mem.Allocator;...@@ -11,6 +11,7 @@ const Allocator = mem.Allocator;
11const builtin = @import("builtin");11const builtin = @import("builtin");
12const link = @import("../../link.zig");12const link = @import("../../link.zig");
13const Module = @import("../../Module.zig");13const Module = @import("../../Module.zig");
14const InternPool = @import("../../InternPool.zig");
14const TypedValue = @import("../../TypedValue.zig");15const TypedValue = @import("../../TypedValue.zig");
15const ErrorMsg = Module.ErrorMsg;16const ErrorMsg = Module.ErrorMsg;
16const codegen = @import("../../codegen.zig");17const codegen = @import("../../codegen.zig");
...@@ -52,7 +53,7 @@ air: Air,...@@ -52,7 +53,7 @@ air: Air,
52liveness: Liveness,53liveness: Liveness,
53bin_file: *link.File,54bin_file: *link.File,
54target: *const std.Target,55target: *const std.Target,
55mod_fn: *const Module.Fn,56func_index: InternPool.Index,
56code: *std.ArrayList(u8),57code: *std.ArrayList(u8),
57debug_output: DebugInfoOutput,58debug_output: DebugInfoOutput,
58err_msg: ?*ErrorMsg,59err_msg: ?*ErrorMsg,
...@@ -260,7 +261,7 @@ const BigTomb = struct {...@@ -260,7 +261,7 @@ const BigTomb = struct {
260pub fn generate(261pub fn generate(
261 bin_file: *link.File,262 bin_file: *link.File,
262 src_loc: Module.SrcLoc,263 src_loc: Module.SrcLoc,
263 module_fn_index: Module.Fn.Index,264 func_index: InternPool.Index,
264 air: Air,265 air: Air,
265 liveness: Liveness,266 liveness: Liveness,
266 code: *std.ArrayList(u8),267 code: *std.ArrayList(u8),
...@@ -271,8 +272,8 @@ pub fn generate(...@@ -271,8 +272,8 @@ pub fn generate(
271 }272 }
272273
273 const mod = bin_file.options.module.?;274 const mod = bin_file.options.module.?;
274 const module_fn = mod.funcPtr(module_fn_index);275 const func = mod.funcInfo(func_index);
275 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);276 const fn_owner_decl = mod.declPtr(func.owner_decl);
276 assert(fn_owner_decl.has_tv);277 assert(fn_owner_decl.has_tv);
277 const fn_type = fn_owner_decl.ty;278 const fn_type = fn_owner_decl.ty;
278279
...@@ -289,8 +290,8 @@ pub fn generate(...@@ -289,8 +290,8 @@ pub fn generate(
289 .air = air,290 .air = air,
290 .liveness = liveness,291 .liveness = liveness,
291 .target = &bin_file.options.target,292 .target = &bin_file.options.target,
293 .func_index = func_index,
292 .bin_file = bin_file,294 .bin_file = bin_file,
293 .mod_fn = module_fn,
294 .code = code,295 .code = code,
295 .debug_output = debug_output,296 .debug_output = debug_output,
296 .err_msg = null,297 .err_msg = null,
...@@ -301,8 +302,8 @@ pub fn generate(...@@ -301,8 +302,8 @@ pub fn generate(
301 .branch_stack = &branch_stack,302 .branch_stack = &branch_stack,
302 .src_loc = src_loc,303 .src_loc = src_loc,
303 .stack_align = undefined,304 .stack_align = undefined,
304 .end_di_line = module_fn.rbrace_line,305 .end_di_line = func.rbrace_line,
305 .end_di_column = module_fn.rbrace_column,306 .end_di_column = func.rbrace_column,
306 };307 };
307 defer function.stack.deinit(bin_file.allocator);308 defer function.stack.deinit(bin_file.allocator);
308 defer function.blocks.deinit(bin_file.allocator);309 defer function.blocks.deinit(bin_file.allocator);
...@@ -344,8 +345,8 @@ pub fn generate(...@@ -344,8 +345,8 @@ pub fn generate(
344 .src_loc = src_loc,345 .src_loc = src_loc,
345 .code = code,346 .code = code,
346 .prev_di_pc = 0,347 .prev_di_pc = 0,
347 .prev_di_line = module_fn.lbrace_line,348 .prev_di_line = func.lbrace_line,
348 .prev_di_column = module_fn.lbrace_column,349 .prev_di_column = func.lbrace_column,
349 };350 };
350 defer emit.deinit();351 defer emit.deinit();
351352
...@@ -1345,37 +1346,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1345,37 +1346,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1345 // on linking.1346 // on linking.
1346 if (try self.air.value(callee, mod)) |func_value| {1347 if (try self.air.value(callee, mod)) |func_value| {
1347 if (self.bin_file.tag == link.File.Elf.base_tag) {1348 if (self.bin_file.tag == link.File.Elf.base_tag) {
1348 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {1349 switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
1349 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {1350 .func => |func| {
1350 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);1351 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1351 const atom = elf_file.getAtom(atom_index);1352 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1352 _ = try atom.getOrCreateOffsetTableEntry(elf_file);1353 const atom = elf_file.getAtom(atom_index);
1353 break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));1354 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1354 } else unreachable;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(.{1360 _ = try self.addInst(.{
1359 .tag = .jmpl,1361 .tag = .jmpl,
1360 .data = .{1362 .data = .{
1361 .arithmetic_3op = .{1363 .arithmetic_3op = .{
1362 .is_imm = false,1364 .is_imm = false,
1363 .rd = .o7,1365 .rd = .o7,
1364 .rs1 = .o7,1366 .rs1 = .o7,
1365 .rs2_or_imm = .{ .rs2 = .g0 },1367 .rs2_or_imm = .{ .rs2 = .g0 },
1368 },
1366 },1369 },
1367 },1370 });
1368 });
13691371
1370 // TODO Find a way to fill this delay slot1372 // TODO Find a way to fill this delay slot
1371 _ = try self.addInst(.{1373 _ = try self.addInst(.{
1372 .tag = .nop,1374 .tag = .nop,
1373 .data = .{ .nop = {} },1375 .data = .{ .nop = {} },
1374 });1376 });
1375 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {1377 },
1376 return self.fail("TODO implement calling extern functions", .{});1378 .extern_func => {
1377 } else {1379 return self.fail("TODO implement calling extern functions", .{});
1378 return self.fail("TODO implement calling bitcasted functions", .{});1380 },
1381 else => {
1382 return self.fail("TODO implement calling bitcasted functions", .{});
1383 },
1379 }1384 }
1380 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");1385 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
1381 } else {1386 } else {
...@@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
1660fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {1665fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1661 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;1666 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
1662 const mod = self.bin_file.options.module.?;1667 const mod = self.bin_file.options.module.?;
1663 const function = mod.funcPtr(ty_fn.func);1668 const func = mod.funcInfo(ty_fn.func);
1664 // TODO emit debug info for function change1669 // TODO emit debug info for function change
1665 _ = function;1670 _ = func;
1666 return self.finishAir(inst, .dead, .{ .none, .none, .none });1671 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1667}1672}
16681673
...@@ -3595,13 +3600,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live...@@ -3595,13 +3600,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
3595}3600}
35963601
3597fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {3602fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
3603 const mod = self.bin_file.options.module.?;
3598 const arg = self.air.instructions.items(.data)[inst].arg;3604 const arg = self.air.instructions.items(.data)[inst].arg;
3599 const ty = self.air.getRefType(arg.ty);3605 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
3602 switch (self.debug_output) {3609 switch (self.debug_output) {
3603 .dwarf => |dw| switch (mcv) {3610 .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, .{
3605 .register = reg.dwarfLocOp(),3612 .register = reg.dwarfLocOp(),
3606 }),3613 }),
3607 else => {},3614 else => {},
...@@ -4127,11 +4134,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re...@@ -4127,11 +4134,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re
4127}4134}
41284135
4129fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {4136fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
4137 const mod = self.bin_file.options.module.?;
4130 const mcv: MCValue = switch (try codegen.genTypedValue(4138 const mcv: MCValue = switch (try codegen.genTypedValue(
4131 self.bin_file,4139 self.bin_file,
4132 self.src_loc,4140 self.src_loc,
4133 typed_value,4141 typed_value,
4134 self.mod_fn.owner_decl,4142 mod.funcOwnerDeclIndex(self.func_index),
4135 )) {4143 )) {
4136 .mcv => |mcv| switch (mcv) {4144 .mcv => |mcv| switch (mcv) {
4137 .none => .none,4145 .none => .none,
...@@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 {...@@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 {
4452/// Caller must call `CallMCValues.deinit`.4460/// Caller must call `CallMCValues.deinit`.
4453fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {4461fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
4454 const mod = self.bin_file.options.module.?;4462 const mod = self.bin_file.options.module.?;
4463 const ip = &mod.intern_pool;
4455 const fn_info = mod.typeToFunc(fn_ty).?;4464 const fn_info = mod.typeToFunc(fn_ty).?;
4456 const cc = fn_info.cc;4465 const cc = fn_info.cc;
4457 var result: CallMCValues = .{4466 var result: CallMCValues = .{
...@@ -4486,14 +4495,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4486,14 +4495,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4486 .callee => abi.c_abi_int_param_regs_callee_view,4495 .callee => abi.c_abi_int_param_regs_callee_view,
4487 };4496 };
44884497
4489 for (fn_info.param_types, 0..) |ty, i| {4498 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
4490 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));4499 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
4491 if (param_size <= 8) {4500 if (param_size <= 8) {
4492 if (next_register < argument_registers.len) {4501 if (next_register < argument_registers.len) {
4493 result.args[i] = .{ .register = argument_registers[next_register] };4502 result_arg.* = .{ .register = argument_registers[next_register] };
4494 next_register += 1;4503 next_register += 1;
4495 } else {4504 } else {
4496 result.args[i] = .{ .stack_offset = next_stack_offset };4505 result_arg.* = .{ .stack_offset = next_stack_offset };
4497 next_register += next_stack_offset;4506 next_register += next_stack_offset;
4498 }4507 }
4499 } else if (param_size <= 16) {4508 } else if (param_size <= 16) {
...@@ -4502,11 +4511,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4502,11 +4511,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4502 } else if (next_register < argument_registers.len) {4511 } else if (next_register < argument_registers.len) {
4503 return self.fail("TODO MCValues split register + stack", .{});4512 return self.fail("TODO MCValues split register + stack", .{});
4504 } else {4513 } else {
4505 result.args[i] = .{ .stack_offset = next_stack_offset };4514 result_arg.* = .{ .stack_offset = next_stack_offset };
4506 next_register += next_stack_offset;4515 next_register += next_stack_offset;
4507 }4516 }
4508 } else {4517 } else {
4509 result.args[i] = .{ .stack_offset = next_stack_offset };4518 result_arg.* = .{ .stack_offset = next_stack_offset };
4510 next_register += next_stack_offset;4519 next_register += next_stack_offset;
4511 }4520 }
4512 }4521 }
src/arch/wasm/CodeGen.zig+16-12
...@@ -650,7 +650,7 @@ air: Air,...@@ -650,7 +650,7 @@ air: Air,
650liveness: Liveness,650liveness: Liveness,
651gpa: mem.Allocator,651gpa: mem.Allocator,
652debug_output: codegen.DebugInfoOutput,652debug_output: codegen.DebugInfoOutput,
653mod_fn: *const Module.Fn,653func_index: InternPool.Index,
654/// Contains a list of current branches.654/// Contains a list of current branches.
655/// When we return from a branch, the branch will be popped from this list,655/// When we return from a branch, the branch will be popped from this list,
656/// which means branches can only contain references from within its own branch,656/// which means branches can only contain references from within its own branch,
...@@ -1202,7 +1202,7 @@ fn genFunctype(...@@ -1202,7 +1202,7 @@ fn genFunctype(
1202pub fn generate(1202pub fn generate(
1203 bin_file: *link.File,1203 bin_file: *link.File,
1204 src_loc: Module.SrcLoc,1204 src_loc: Module.SrcLoc,
1205 func_index: Module.Fn.Index,1205 func_index: InternPool.Index,
1206 air: Air,1206 air: Air,
1207 liveness: Liveness,1207 liveness: Liveness,
1208 code: *std.ArrayList(u8),1208 code: *std.ArrayList(u8),
...@@ -1210,7 +1210,7 @@ pub fn generate(...@@ -1210,7 +1210,7 @@ pub fn generate(
1210) codegen.CodeGenError!codegen.Result {1210) codegen.CodeGenError!codegen.Result {
1211 _ = src_loc;1211 _ = src_loc;
1212 const mod = bin_file.options.module.?;1212 const mod = bin_file.options.module.?;
1213 const func = mod.funcPtr(func_index);1213 const func = mod.funcInfo(func_index);
1214 var code_gen: CodeGen = .{1214 var code_gen: CodeGen = .{
1215 .gpa = bin_file.allocator,1215 .gpa = bin_file.allocator,
1216 .air = air,1216 .air = air,
...@@ -1223,7 +1223,7 @@ pub fn generate(...@@ -1223,7 +1223,7 @@ pub fn generate(
1223 .target = bin_file.options.target,1223 .target = bin_file.options.target,
1224 .bin_file = bin_file.cast(link.File.Wasm).?,1224 .bin_file = bin_file.cast(link.File.Wasm).?,
1225 .debug_output = debug_output,1225 .debug_output = debug_output,
1226 .mod_fn = func,1226 .func_index = func_index,
1227 };1227 };
1228 defer code_gen.deinit();1228 defer code_gen.deinit();
12291229
...@@ -1237,8 +1237,9 @@ pub fn generate(...@@ -1237,8 +1237,9 @@ pub fn generate(
12371237
1238fn genFunc(func: *CodeGen) InnerError!void {1238fn genFunc(func: *CodeGen) InnerError!void {
1239 const mod = func.bin_file.base.options.module.?;1239 const mod = func.bin_file.base.options.module.?;
1240 const ip = &mod.intern_pool;
1240 const fn_info = mod.typeToFunc(func.decl.ty).?;1241 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);
1242 defer func_type.deinit(func.gpa);1243 defer func_type.deinit(func.gpa);
1243 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);1244 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);
12441245
...@@ -1347,6 +1348,7 @@ const CallWValues = struct {...@@ -1347,6 +1348,7 @@ const CallWValues = struct {
13471348
1348fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {1349fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
1349 const mod = func.bin_file.base.options.module.?;1350 const mod = func.bin_file.base.options.module.?;
1351 const ip = &mod.intern_pool;
1350 const fn_info = mod.typeToFunc(fn_ty).?;1352 const fn_info = mod.typeToFunc(fn_ty).?;
1351 const cc = fn_info.cc;1353 const cc = fn_info.cc;
1352 var result: CallWValues = .{1354 var result: CallWValues = .{
...@@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13691371
1370 switch (cc) {1372 switch (cc) {
1371 .Unspecified => {1373 .Unspecified => {
1372 for (fn_info.param_types) |ty| {1374 for (fn_info.param_types.get(ip)) |ty| {
1373 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {1375 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
1374 continue;1376 continue;
1375 }1377 }
...@@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
1379 }1381 }
1380 },1382 },
1381 .C => {1383 .C => {
1382 for (fn_info.param_types) |ty| {1384 for (fn_info.param_types.get(ip)) |ty| {
1383 const ty_classes = abi.classifyType(ty.toType(), mod);1385 const ty_classes = abi.classifyType(ty.toType(), mod);
1384 for (ty_classes) |class| {1386 for (ty_classes) |class| {
1385 if (class == .none) continue;1387 if (class == .none) continue;
...@@ -2185,6 +2187,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2185,6 +2187,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2185 const ty = func.typeOf(pl_op.operand);2187 const ty = func.typeOf(pl_op.operand);
21862188
2187 const mod = func.bin_file.base.options.module.?;2189 const mod = func.bin_file.base.options.module.?;
2190 const ip = &mod.intern_pool;
2188 const fn_ty = switch (ty.zigTypeTag(mod)) {2191 const fn_ty = switch (ty.zigTypeTag(mod)) {
2189 .Fn => ty,2192 .Fn => ty,
2190 .Pointer => ty.childType(mod),2193 .Pointer => ty.childType(mod),
...@@ -2203,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2203,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2203 } else if (func_val.getExternFunc(mod)) |extern_func| {2206 } else if (func_val.getExternFunc(mod)) |extern_func| {
2204 const ext_decl = mod.declPtr(extern_func.decl);2207 const ext_decl = mod.declPtr(extern_func.decl);
2205 const ext_info = mod.typeToFunc(ext_decl.ty).?;2208 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);
2207 defer func_type.deinit(func.gpa);2210 defer func_type.deinit(func.gpa);
2208 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);2211 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
2209 const atom = func.bin_file.getAtomPtr(atom_index);2212 const atom = func.bin_file.getAtomPtr(atom_index);
...@@ -2253,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2253,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2253 const operand = try func.resolveInst(pl_op.operand);2256 const operand = try func.resolveInst(pl_op.operand);
2254 try func.emitWValue(operand);2257 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);
2257 defer fn_type.deinit(func.gpa);2260 defer fn_type.deinit(func.gpa);
22582261
2259 const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);2262 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 {...@@ -2564,8 +2567,8 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2564 switch (func.debug_output) {2567 switch (func.debug_output) {
2565 .dwarf => |dwarf| {2568 .dwarf => |dwarf| {
2566 const src_index = func.air.instructions.items(.data)[inst].arg.src_index;2569 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);2570 const name = mod.getParamName(func.func_index, src_index);
2568 try dwarf.genArgDbgInfo(name, arg_ty, func.mod_fn.owner_decl, .{2571 try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{
2569 .wasm_local = arg.local.value,2572 .wasm_local = arg.local.value,
2570 });2573 });
2571 },2574 },
...@@ -6198,6 +6201,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6198,6 +6201,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6198fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {6201fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
6199 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});6202 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
62006203
6204 const mod = func.bin_file.base.options.module.?;
6201 const pl_op = func.air.instructions.items(.data)[inst].pl_op;6205 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
6202 const ty = func.typeOf(pl_op.operand);6206 const ty = func.typeOf(pl_op.operand);
6203 const operand = try func.resolveInst(pl_op.operand);6207 const operand = try func.resolveInst(pl_op.operand);
...@@ -6214,7 +6218,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {...@@ -6214,7 +6218,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
6214 break :blk .nop;6218 break :blk .nop;
6215 },6219 },
6216 };6220 };
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
6219 func.finishAir(inst, .none, &.{});6223 func.finishAir(inst, .none, &.{});
6220}6224}
src/arch/x86_64/CodeGen.zig+23-22
...@@ -110,20 +110,21 @@ const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };...@@ -110,20 +110,21 @@ const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
110const RegisterOffset = struct { reg: Register, off: i32 = 0 };110const RegisterOffset = struct { reg: Register, off: i32 = 0 };
111111
112const Owner = union(enum) {112const Owner = union(enum) {
113 mod_fn: *const Module.Fn,113 func_index: InternPool.Index,
114 lazy_sym: link.File.LazySymbol,114 lazy_sym: link.File.LazySymbol,
115115
116 fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {116 fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {
117 return switch (owner) {117 return switch (owner) {
118 .mod_fn => |mod_fn| mod_fn.owner_decl,118 .func_index => |func_index| mod.funcOwnerDeclIndex(func_index),
119 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod),119 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod),
120 };120 };
121 }121 }
122122
123 fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 {123 fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 {
124 switch (owner) {124 switch (owner) {
125 .mod_fn => |mod_fn| {125 .func_index => |func_index| {
126 const decl_index = mod_fn.owner_decl;126 const mod = ctx.bin_file.options.module.?;
127 const decl_index = mod.funcOwnerDeclIndex(func_index);
127 if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {128 if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
128 const atom = try macho_file.getOrCreateAtomForDecl(decl_index);129 const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
129 return macho_file.getAtom(atom).getSymbolIndex().?;130 return macho_file.getAtom(atom).getSymbolIndex().?;
...@@ -638,7 +639,7 @@ const Self = @This();...@@ -638,7 +639,7 @@ const Self = @This();
638pub fn generate(639pub fn generate(
639 bin_file: *link.File,640 bin_file: *link.File,
640 src_loc: Module.SrcLoc,641 src_loc: Module.SrcLoc,
641 module_fn_index: Module.Fn.Index,642 func_index: InternPool.Index,
642 air: Air,643 air: Air,
643 liveness: Liveness,644 liveness: Liveness,
644 code: *std.ArrayList(u8),645 code: *std.ArrayList(u8),
...@@ -649,8 +650,8 @@ pub fn generate(...@@ -649,8 +650,8 @@ pub fn generate(
649 }650 }
650651
651 const mod = bin_file.options.module.?;652 const mod = bin_file.options.module.?;
652 const module_fn = mod.funcPtr(module_fn_index);653 const func = mod.funcInfo(func_index);
653 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);654 const fn_owner_decl = mod.declPtr(func.owner_decl);
654 assert(fn_owner_decl.has_tv);655 assert(fn_owner_decl.has_tv);
655 const fn_type = fn_owner_decl.ty;656 const fn_type = fn_owner_decl.ty;
656657
...@@ -662,15 +663,15 @@ pub fn generate(...@@ -662,15 +663,15 @@ pub fn generate(
662 .target = &bin_file.options.target,663 .target = &bin_file.options.target,
663 .bin_file = bin_file,664 .bin_file = bin_file,
664 .debug_output = debug_output,665 .debug_output = debug_output,
665 .owner = .{ .mod_fn = module_fn },666 .owner = .{ .func_index = func_index },
666 .err_msg = null,667 .err_msg = null,
667 .args = undefined, // populated after `resolveCallingConventionValues`668 .args = undefined, // populated after `resolveCallingConventionValues`
668 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`669 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
669 .fn_type = fn_type,670 .fn_type = fn_type,
670 .arg_index = 0,671 .arg_index = 0,
671 .src_loc = src_loc,672 .src_loc = src_loc,
672 .end_di_line = module_fn.rbrace_line,673 .end_di_line = func.rbrace_line,
673 .end_di_column = module_fn.rbrace_column,674 .end_di_column = func.rbrace_column,
674 };675 };
675 defer {676 defer {
676 function.frame_allocs.deinit(gpa);677 function.frame_allocs.deinit(gpa);
...@@ -687,17 +688,16 @@ pub fn generate(...@@ -687,17 +688,16 @@ pub fn generate(
687 if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa);688 if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa);
688 }689 }
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
692 try function.frame_allocs.resize(gpa, FrameIndex.named_count);695 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
693 function.frame_allocs.set(696 function.frame_allocs.set(
694 @intFromEnum(FrameIndex.stack_frame),697 @intFromEnum(FrameIndex.stack_frame),
695 FrameAlloc.init(.{698 FrameAlloc.init(.{
696 .size = 0,699 .size = 0,
697 .alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack|700 .alignment = @intCast(func.analysis(ip).stack_alignment.toByteUnitsOptional() orelse 1),
698 @intCast(set_align_stack.alignment.toByteUnitsOptional().?)
699 else
700 1,
701 }),701 }),
702 );702 );
703 function.frame_allocs.set(703 function.frame_allocs.set(
...@@ -761,8 +761,8 @@ pub fn generate(...@@ -761,8 +761,8 @@ pub fn generate(
761 .debug_output = debug_output,761 .debug_output = debug_output,
762 .code = code,762 .code = code,
763 .prev_di_pc = 0,763 .prev_di_pc = 0,
764 .prev_di_line = module_fn.lbrace_line,764 .prev_di_line = func.lbrace_line,
765 .prev_di_column = module_fn.lbrace_column,765 .prev_di_column = func.lbrace_column,
766 };766 };
767 defer emit.deinit();767 defer emit.deinit();
768 emit.emitMir() catch |err| switch (err) {768 emit.emitMir() catch |err| switch (err) {
...@@ -7942,7 +7942,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -7942,7 +7942,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
79427942
7943 const ty = self.typeOfIndex(inst);7943 const ty = self.typeOfIndex(inst);
7944 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;7944 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);
7946 try self.genArgDbgInfo(ty, name, dst_mcv);7946 try self.genArgDbgInfo(ty, name, dst_mcv);
79477947
7948 break :result dst_mcv;7948 break :result dst_mcv;
...@@ -8139,7 +8139,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8139,7 +8139,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8139 if (try self.air.value(callee, mod)) |func_value| {8139 if (try self.air.value(callee, mod)) |func_value| {
8140 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);8140 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
8141 if (switch (func_key) {8141 if (switch (func_key) {
8142 .func => |func| mod.funcPtr(func.index).owner_decl,8142 .func => |func| func.owner_decl,
8143 .ptr => |ptr| switch (ptr.addr) {8143 .ptr => |ptr| switch (ptr.addr) {
8144 .decl => |decl| decl,8144 .decl => |decl| decl,
8145 else => null,8145 else => null,
...@@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
8582fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {8582fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
8583 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;8583 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
8584 const mod = self.bin_file.options.module.?;8584 const mod = self.bin_file.options.module.?;
8585 const function = mod.funcPtr(ty_fn.func);8585 const func = mod.funcInfo(ty_fn.func);
8586 // TODO emit debug info for function change8586 // TODO emit debug info for function change
8587 _ = function;8587 _ = func;
8588 return self.finishAir(inst, .unreach, .{ .none, .none, .none });8588 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
8589}8589}
85908590
...@@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues(...@@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues(
11719 stack_frame_base: FrameIndex,11719 stack_frame_base: FrameIndex,
11720) !CallMCValues {11720) !CallMCValues {
11721 const mod = self.bin_file.options.module.?;11721 const mod = self.bin_file.options.module.?;
11722 const ip = &mod.intern_pool;
11722 const cc = fn_info.cc;11723 const cc = fn_info.cc;
11723 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);11724 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
11724 defer self.gpa.free(param_types);11725 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| {
11727 dest.* = src.toType();11728 dest.* = src.toType();
11728 }11729 }
11729 // TODO: promote var arg types11730 // TODO: promote var arg types
src/codegen.zig+1-1
...@@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {...@@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
67pub fn generateFunction(67pub fn generateFunction(
68 bin_file: *link.File,68 bin_file: *link.File,
69 src_loc: Module.SrcLoc,69 src_loc: Module.SrcLoc,
70 func_index: Module.Fn.Index,70 func_index: InternPool.Index,
71 air: Air,71 air: Air,
72 liveness: Liveness,72 liveness: Liveness,
73 code: *std.ArrayList(u8),73 code: *std.ArrayList(u8),
src/codegen/c.zig+15-8
...@@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {...@@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
257 return .{ .data = ident };257 return .{ .data = ident };
258}258}
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`.
261/// It is not available when generating .h file.262/// It is not available when generating .h file.
262pub const Function = struct {263pub const Function = struct {
263 air: Air,264 air: Air,
...@@ -268,7 +269,7 @@ pub const Function = struct {...@@ -268,7 +269,7 @@ pub const Function = struct {
268 next_block_index: usize = 0,269 next_block_index: usize = 0,
269 object: Object,270 object: Object,
270 lazy_fns: LazyFnMap,271 lazy_fns: LazyFnMap,
271 func_index: Module.Fn.Index,272 func_index: InternPool.Index,
272 /// All the locals, to be emitted at the top of the function.273 /// All the locals, to be emitted at the top of the function.
273 locals: std.ArrayListUnmanaged(Local) = .{},274 locals: std.ArrayListUnmanaged(Local) = .{},
274 /// Which locals are available for reuse, based on Type.275 /// Which locals are available for reuse, based on Type.
...@@ -1487,6 +1488,7 @@ pub const DeclGen = struct {...@@ -1487,6 +1488,7 @@ pub const DeclGen = struct {
1487 ) !void {1488 ) !void {
1488 const store = &dg.ctypes.set;1489 const store = &dg.ctypes.set;
1489 const mod = dg.module;1490 const mod = dg.module;
1491 const ip = &mod.intern_pool;
14901492
1491 const fn_decl = mod.declPtr(fn_decl_index);1493 const fn_decl = mod.declPtr(fn_decl_index);
1492 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);1494 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);
...@@ -1499,7 +1501,7 @@ pub const DeclGen = struct {...@@ -1499,7 +1501,7 @@ pub const DeclGen = struct {
1499 else => unreachable,1501 else => unreachable,
1500 }1502 }
1501 }1503 }
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 ");
1503 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");1505 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
15041506
1505 const trailing = try renderTypePrefix(1507 const trailing = try renderTypePrefix(
...@@ -1744,7 +1746,7 @@ pub const DeclGen = struct {...@@ -1744,7 +1746,7 @@ pub const DeclGen = struct {
1744 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {1746 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
1745 .variable => |variable| mod.decl_exports.contains(variable.decl),1747 .variable => |variable| mod.decl_exports.contains(variable.decl),
1746 .extern_func => true,1748 .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),
1748 else => unreachable,1750 else => unreachable,
1749 };1751 };
1750 }1752 }
...@@ -1800,7 +1802,12 @@ pub const DeclGen = struct {...@@ -1800,7 +1802,12 @@ pub const DeclGen = struct {
1800 }1802 }
1801 }1803 }
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 {
1804 try dg.writeCValue(writer, c_value);1811 try dg.writeCValue(writer, c_value);
1805 try writer.writeByte('.');1812 try writer.writeByte('.');
1806 try dg.writeCValue(writer, member);1813 try dg.writeCValue(writer, member);
...@@ -4161,7 +4168,7 @@ fn airCall(...@@ -4161,7 +4168,7 @@ fn airCall(
4161 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;4168 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
4162 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {4169 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
4163 .extern_func => |extern_func| extern_func.decl,4170 .extern_func => |extern_func| extern_func.decl,
4164 .func => |func| mod.funcPtr(func.index).owner_decl,4171 .func => |func| func.owner_decl,
4165 .ptr => |ptr| switch (ptr.addr) {4172 .ptr => |ptr| switch (ptr.addr) {
4166 .decl => |decl| decl,4173 .decl => |decl| decl,
4167 else => break :known,4174 else => break :known,
...@@ -4238,9 +4245,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4238,9 +4245,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
4238 const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;4245 const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;
4239 const mod = f.object.dg.module;4246 const mod = f.object.dg.module;
4240 const writer = f.object.writer();4247 const writer = f.object.writer();
4241 const function = mod.funcPtr(ty_fn.func);4248 const owner_decl = mod.funcOwnerDeclPtr(ty_fn.func);
4242 try writer.print("/* dbg func:{s} */\n", .{4249 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),
4244 });4251 });
4245 return .none;4252 return .none;
4246}4253}
src/codegen/c/type.zig+9-5
...@@ -1722,6 +1722,7 @@ pub const CType = extern union {...@@ -1722,6 +1722,7 @@ pub const CType = extern union {
17221722
1723 .Fn => {1723 .Fn => {
1724 const info = mod.typeToFunc(ty).?;1724 const info = mod.typeToFunc(ty).?;
1725 const ip = &mod.intern_pool;
1725 if (!info.is_generic) {1726 if (!info.is_generic) {
1726 if (lookup.isMutable()) {1727 if (lookup.isMutable()) {
1727 const param_kind: Kind = switch (kind) {1728 const param_kind: Kind = switch (kind) {
...@@ -1730,7 +1731,7 @@ pub const CType = extern union {...@@ -1730,7 +1731,7 @@ pub const CType = extern union {
1730 .payload => unreachable,1731 .payload => unreachable,
1731 };1732 };
1732 _ = try lookup.typeToIndex(info.return_type.toType(), param_kind);1733 _ = 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| {
1734 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;1735 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
1735 _ = try lookup.typeToIndex(param_type.toType(), param_kind);1736 _ = try lookup.typeToIndex(param_type.toType(), param_kind);
1736 }1737 }
...@@ -2014,6 +2015,7 @@ pub const CType = extern union {...@@ -2014,6 +2015,7 @@ pub const CType = extern union {
2014 .function,2015 .function,
2015 .varargs_function,2016 .varargs_function,
2016 => {2017 => {
2018 const ip = &mod.intern_pool;
2017 const info = mod.typeToFunc(ty).?;2019 const info = mod.typeToFunc(ty).?;
2018 assert(!info.is_generic);2020 assert(!info.is_generic);
2019 const param_kind: Kind = switch (kind) {2021 const param_kind: Kind = switch (kind) {
...@@ -2023,14 +2025,14 @@ pub const CType = extern union {...@@ -2023,14 +2025,14 @@ pub const CType = extern union {
2023 };2025 };
20242026
2025 var c_params_len: usize = 0;2027 var c_params_len: usize = 0;
2026 for (info.param_types) |param_type| {2028 for (info.param_types.get(ip)) |param_type| {
2027 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;2029 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2028 c_params_len += 1;2030 c_params_len += 1;
2029 }2031 }
20302032
2031 const params_pl = try arena.alloc(Index, c_params_len);2033 const params_pl = try arena.alloc(Index, c_params_len);
2032 var c_param_i: usize = 0;2034 var c_param_i: usize = 0;
2033 for (info.param_types) |param_type| {2035 for (info.param_types.get(ip)) |param_type| {
2034 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;2036 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2035 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;2037 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
2036 c_param_i += 1;2038 c_param_i += 1;
...@@ -2147,6 +2149,7 @@ pub const CType = extern union {...@@ -2147,6 +2149,7 @@ pub const CType = extern union {
2147 => {2149 => {
2148 if (ty.zigTypeTag(mod) != .Fn) return false;2150 if (ty.zigTypeTag(mod) != .Fn) return false;
21492151
2152 const ip = &mod.intern_pool;
2150 const info = mod.typeToFunc(ty).?;2153 const info = mod.typeToFunc(ty).?;
2151 assert(!info.is_generic);2154 assert(!info.is_generic);
2152 const data = cty.cast(Payload.Function).?.data;2155 const data = cty.cast(Payload.Function).?.data;
...@@ -2160,7 +2163,7 @@ pub const CType = extern union {...@@ -2160,7 +2163,7 @@ pub const CType = extern union {
2160 return false;2163 return false;
21612164
2162 var c_param_i: usize = 0;2165 var c_param_i: usize = 0;
2163 for (info.param_types) |param_type| {2166 for (info.param_types.get(ip)) |param_type| {
2164 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;2167 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
21652168
2166 if (c_param_i >= data.param_types.len) return false;2169 if (c_param_i >= data.param_types.len) return false;
...@@ -2202,6 +2205,7 @@ pub const CType = extern union {...@@ -2202,6 +2205,7 @@ pub const CType = extern union {
2202 autoHash(hasher, t);2205 autoHash(hasher, t);
22032206
2204 const mod = self.lookup.getModule();2207 const mod = self.lookup.getModule();
2208 const ip = &mod.intern_pool;
2205 switch (t) {2209 switch (t) {
2206 .fwd_anon_struct,2210 .fwd_anon_struct,
2207 .fwd_anon_union,2211 .fwd_anon_union,
...@@ -2270,7 +2274,7 @@ pub const CType = extern union {...@@ -2270,7 +2274,7 @@ pub const CType = extern union {
2270 };2274 };
22712275
2272 self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);2276 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| {
2274 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;2278 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2275 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);2279 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
2276 }2280 }
src/codegen/llvm.zig+75-68
...@@ -867,14 +867,15 @@ pub const Object = struct {...@@ -867,14 +867,15 @@ pub const Object = struct {
867 pub fn updateFunc(867 pub fn updateFunc(
868 o: *Object,868 o: *Object,
869 mod: *Module,869 mod: *Module,
870 func_index: Module.Fn.Index,870 func_index: InternPool.Index,
871 air: Air,871 air: Air,
872 liveness: Liveness,872 liveness: Liveness,
873 ) !void {873 ) !void {
874 const func = mod.funcPtr(func_index);874 const func = mod.funcInfo(func_index);
875 const decl_index = func.owner_decl;875 const decl_index = func.owner_decl;
876 const decl = mod.declPtr(decl_index);876 const decl = mod.declPtr(decl_index);
877 const target = mod.getTarget();877 const target = mod.getTarget();
878 const ip = &mod.intern_pool;
878879
879 var dg: DeclGen = .{880 var dg: DeclGen = .{
880 .object = o,881 .object = o,
...@@ -885,24 +886,23 @@ pub const Object = struct {...@@ -885,24 +886,23 @@ pub const Object = struct {
885886
886 const llvm_func = try o.resolveLlvmFunction(decl_index);887 const llvm_func = try o.resolveLlvmFunction(decl_index);
887888
888 if (mod.align_stack_fns.get(func_index)) |align_info| {889 if (func.analysis(ip).is_noinline) {
889 o.addFnAttrInt(llvm_func, "alignstack", align_info.alignment.toByteUnitsOptional().?);
890 o.addFnAttr(llvm_func, "noinline");890 o.addFnAttr(llvm_func, "noinline");
891 } else {891 } else {
892 Object.removeFnAttr(llvm_func, "alignstack");892 Object.removeFnAttr(llvm_func, "noinline");
893 if (!func.is_noinline) Object.removeFnAttr(llvm_func, "noinline");
894 }893 }
895894
896 if (func.is_cold) {895 if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {
897 o.addFnAttr(llvm_func, "cold");896 o.addFnAttrInt(llvm_func, "alignstack", alignment);
897 o.addFnAttr(llvm_func, "noinline");
898 } else {898 } else {
899 Object.removeFnAttr(llvm_func, "cold");899 Object.removeFnAttr(llvm_func, "alignstack");
900 }900 }
901901
902 if (func.is_noinline) {902 if (func.analysis(ip).is_cold) {
903 o.addFnAttr(llvm_func, "noinline");903 o.addFnAttr(llvm_func, "cold");
904 } else {904 } else {
905 Object.removeFnAttr(llvm_func, "noinline");905 Object.removeFnAttr(llvm_func, "cold");
906 }906 }
907907
908 // TODO: disable this if safety is off for the function scope908 // TODO: disable this if safety is off for the function scope
...@@ -921,7 +921,7 @@ pub const Object = struct {...@@ -921,7 +921,7 @@ pub const Object = struct {
921 o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");921 o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
922 }922 }
923923
924 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|924 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
925 llvm_func.setSection(section);925 llvm_func.setSection(section);
926926
927 // Remove all the basic blocks of a function in order to start over, generating927 // Remove all the basic blocks of a function in order to start over, generating
...@@ -968,7 +968,7 @@ pub const Object = struct {...@@ -968,7 +968,7 @@ pub const Object = struct {
968 .byval => {968 .byval => {
969 assert(!it.byval_attr);969 assert(!it.byval_attr);
970 const param_index = it.zig_index - 1;970 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();
972 const param = llvm_func.getParam(llvm_arg_i);972 const param = llvm_func.getParam(llvm_arg_i);
973 try args.ensureUnusedCapacity(1);973 try args.ensureUnusedCapacity(1);
974974
...@@ -987,7 +987,7 @@ pub const Object = struct {...@@ -987,7 +987,7 @@ pub const Object = struct {
987 llvm_arg_i += 1;987 llvm_arg_i += 1;
988 },988 },
989 .byref => {989 .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();
991 const param_llvm_ty = try o.lowerType(param_ty);991 const param_llvm_ty = try o.lowerType(param_ty);
992 const param = llvm_func.getParam(llvm_arg_i);992 const param = llvm_func.getParam(llvm_arg_i);
993 const alignment = param_ty.abiAlignment(mod);993 const alignment = param_ty.abiAlignment(mod);
...@@ -1006,7 +1006,7 @@ pub const Object = struct {...@@ -1006,7 +1006,7 @@ pub const Object = struct {
1006 }1006 }
1007 },1007 },
1008 .byref_mut => {1008 .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();
1010 const param_llvm_ty = try o.lowerType(param_ty);1010 const param_llvm_ty = try o.lowerType(param_ty);
1011 const param = llvm_func.getParam(llvm_arg_i);1011 const param = llvm_func.getParam(llvm_arg_i);
1012 const alignment = param_ty.abiAlignment(mod);1012 const alignment = param_ty.abiAlignment(mod);
...@@ -1026,7 +1026,7 @@ pub const Object = struct {...@@ -1026,7 +1026,7 @@ pub const Object = struct {
1026 },1026 },
1027 .abi_sized_int => {1027 .abi_sized_int => {
1028 assert(!it.byval_attr);1028 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();
1030 const param = llvm_func.getParam(llvm_arg_i);1030 const param = llvm_func.getParam(llvm_arg_i);
1031 llvm_arg_i += 1;1031 llvm_arg_i += 1;
10321032
...@@ -1053,7 +1053,7 @@ pub const Object = struct {...@@ -1053,7 +1053,7 @@ pub const Object = struct {
1053 },1053 },
1054 .slice => {1054 .slice => {
1055 assert(!it.byval_attr);1055 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();
1057 const ptr_info = param_ty.ptrInfo(mod);1057 const ptr_info = param_ty.ptrInfo(mod);
10581058
1059 if (math.cast(u5, it.zig_index - 1)) |i| {1059 if (math.cast(u5, it.zig_index - 1)) |i| {
...@@ -1083,7 +1083,7 @@ pub const Object = struct {...@@ -1083,7 +1083,7 @@ pub const Object = struct {
1083 .multiple_llvm_types => {1083 .multiple_llvm_types => {
1084 assert(!it.byval_attr);1084 assert(!it.byval_attr);
1085 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];1085 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();
1087 const param_llvm_ty = try o.lowerType(param_ty);1087 const param_llvm_ty = try o.lowerType(param_ty);
1088 const param_alignment = param_ty.abiAlignment(mod);1088 const param_alignment = param_ty.abiAlignment(mod);
1089 const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);1089 const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
...@@ -1114,7 +1114,7 @@ pub const Object = struct {...@@ -1114,7 +1114,7 @@ pub const Object = struct {
1114 args.appendAssumeCapacity(casted);1114 args.appendAssumeCapacity(casted);
1115 },1115 },
1116 .float_array => {1116 .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();
1118 const param_llvm_ty = try o.lowerType(param_ty);1118 const param_llvm_ty = try o.lowerType(param_ty);
1119 const param = llvm_func.getParam(llvm_arg_i);1119 const param = llvm_func.getParam(llvm_arg_i);
1120 llvm_arg_i += 1;1120 llvm_arg_i += 1;
...@@ -1132,7 +1132,7 @@ pub const Object = struct {...@@ -1132,7 +1132,7 @@ pub const Object = struct {
1132 }1132 }
1133 },1133 },
1134 .i32_array, .i64_array => {1134 .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();
1136 const param_llvm_ty = try o.lowerType(param_ty);1136 const param_llvm_ty = try o.lowerType(param_ty);
1137 const param = llvm_func.getParam(llvm_arg_i);1137 const param = llvm_func.getParam(llvm_arg_i);
1138 llvm_arg_i += 1;1138 llvm_arg_i += 1;
...@@ -1168,7 +1168,7 @@ pub const Object = struct {...@@ -1168,7 +1168,7 @@ pub const Object = struct {
1168 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);1168 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
1169 const subprogram = dib.createFunction(1169 const subprogram = dib.createFunction(
1170 di_file.?.toScope(),1170 di_file.?.toScope(),
1171 mod.intern_pool.stringToSlice(decl.name),1171 ip.stringToSlice(decl.name),
1172 llvm_func.getValueName(),1172 llvm_func.getValueName(),
1173 di_file.?,1173 di_file.?,
1174 line_number,1174 line_number,
...@@ -1460,6 +1460,7 @@ pub const Object = struct {...@@ -1460,6 +1460,7 @@ pub const Object = struct {
1460 const target = o.target;1460 const target = o.target;
1461 const dib = o.di_builder.?;1461 const dib = o.di_builder.?;
1462 const mod = o.module;1462 const mod = o.module;
1463 const ip = &mod.intern_pool;
1463 switch (ty.zigTypeTag(mod)) {1464 switch (ty.zigTypeTag(mod)) {
1464 .Void, .NoReturn => {1465 .Void, .NoReturn => {
1465 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);1466 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
...@@ -1492,7 +1493,6 @@ pub const Object = struct {...@@ -1492,7 +1493,6 @@ pub const Object = struct {
1492 return enum_di_ty;1493 return enum_di_ty;
1493 }1494 }
14941495
1495 const ip = &mod.intern_pool;
1496 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;1496 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
14971497
1498 const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);1498 const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);
...@@ -1518,7 +1518,7 @@ pub const Object = struct {...@@ -1518,7 +1518,7 @@ pub const Object = struct {
1518 if (@sizeOf(usize) == @sizeOf(u64)) {1518 if (@sizeOf(usize) == @sizeOf(u64)) {
1519 enumerators[i] = dib.createEnumerator2(1519 enumerators[i] = dib.createEnumerator2(
1520 field_name_z,1520 field_name_z,
1521 @as(c_uint, @intCast(bigint.limbs.len)),1521 @intCast(bigint.limbs.len),
1522 bigint.limbs.ptr,1522 bigint.limbs.ptr,
1523 int_info.bits,1523 int_info.bits,
1524 int_info.signedness == .unsigned,1524 int_info.signedness == .unsigned,
...@@ -2320,8 +2320,8 @@ pub const Object = struct {...@@ -2320,8 +2320,8 @@ pub const Object = struct {
2320 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));2320 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2321 }2321 }
23222322
2323 for (0..mod.typeToFunc(ty).?.param_types.len) |i| {2323 for (0..fn_info.param_types.len) |i| {
2324 const param_ty = mod.typeToFunc(ty).?.param_types[i].toType();2324 const param_ty = fn_info.param_types.get(ip)[i].toType();
2325 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;2325 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
23262326
2327 if (isByRef(param_ty, mod)) {2327 if (isByRef(param_ty, mod)) {
...@@ -2475,9 +2475,10 @@ pub const Object = struct {...@@ -2475,9 +2475,10 @@ pub const Object = struct {
2475 const fn_type = try o.lowerType(zig_fn_type);2475 const fn_type = try o.lowerType(zig_fn_type);
24762476
2477 const fqn = try decl.getFullyQualifiedName(mod);2477 const fqn = try decl.getFullyQualifiedName(mod);
2478 const ip = &mod.intern_pool;
24782479
2479 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);2480 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);
2481 gop.value_ptr.* = llvm_fn;2482 gop.value_ptr.* = llvm_fn;
24822483
2483 const is_extern = decl.isExtern(mod);2484 const is_extern = decl.isExtern(mod);
...@@ -2486,8 +2487,8 @@ pub const Object = struct {...@@ -2486,8 +2487,8 @@ pub const Object = struct {
2486 llvm_fn.setUnnamedAddr(.True);2487 llvm_fn.setUnnamedAddr(.True);
2487 } else {2488 } else {
2488 if (target.isWasm()) {2489 if (target.isWasm()) {
2489 o.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name));2490 o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
2490 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {2491 if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
2491 if (!std.mem.eql(u8, lib_name, "c")) {2492 if (!std.mem.eql(u8, lib_name, "c")) {
2492 o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);2493 o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
2493 }2494 }
...@@ -2546,13 +2547,13 @@ pub const Object = struct {...@@ -2546,13 +2547,13 @@ pub const Object = struct {
2546 while (it.next()) |lowering| switch (lowering) {2547 while (it.next()) |lowering| switch (lowering) {
2547 .byval => {2548 .byval => {
2548 const param_index = it.zig_index - 1;2549 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();
2550 if (!isByRef(param_ty, mod)) {2551 if (!isByRef(param_ty, mod)) {
2551 o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);2552 o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
2552 }2553 }
2553 },2554 },
2554 .byref => {2555 .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];
2556 const param_llvm_ty = try o.lowerType(param_ty.toType());2557 const param_llvm_ty = try o.lowerType(param_ty.toType());
2557 const alignment = param_ty.toType().abiAlignment(mod);2558 const alignment = param_ty.toType().abiAlignment(mod);
2558 o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);2559 o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
...@@ -3031,6 +3032,7 @@ pub const Object = struct {...@@ -3031,6 +3032,7 @@ pub const Object = struct {
30313032
3032 fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {3033 fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {
3033 const mod = o.module;3034 const mod = o.module;
3035 const ip = &mod.intern_pool;
3034 const fn_info = mod.typeToFunc(fn_ty).?;3036 const fn_info = mod.typeToFunc(fn_ty).?;
3035 const llvm_ret_ty = try lowerFnRetTy(o, fn_info);3037 const llvm_ret_ty = try lowerFnRetTy(o, fn_info);
30363038
...@@ -3052,19 +3054,19 @@ pub const Object = struct {...@@ -3052,19 +3054,19 @@ pub const Object = struct {
3052 while (it.next()) |lowering| switch (lowering) {3054 while (it.next()) |lowering| switch (lowering) {
3053 .no_bits => continue,3055 .no_bits => continue,
3054 .byval => {3056 .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();
3056 try llvm_params.append(try o.lowerType(param_ty));3058 try llvm_params.append(try o.lowerType(param_ty));
3057 },3059 },
3058 .byref, .byref_mut => {3060 .byref, .byref_mut => {
3059 try llvm_params.append(o.context.pointerType(0));3061 try llvm_params.append(o.context.pointerType(0));
3060 },3062 },
3061 .abi_sized_int => {3063 .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();
3063 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));3065 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
3064 try llvm_params.append(o.context.intType(abi_size * 8));3066 try llvm_params.append(o.context.intType(abi_size * 8));
3065 },3067 },
3066 .slice => {3068 .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();
3068 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)3070 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
3069 param_ty.optionalChild(mod).slicePtrFieldType(mod)3071 param_ty.optionalChild(mod).slicePtrFieldType(mod)
3070 else3072 else
...@@ -3083,7 +3085,7 @@ pub const Object = struct {...@@ -3083,7 +3085,7 @@ pub const Object = struct {
3083 try llvm_params.append(o.context.intType(16));3085 try llvm_params.append(o.context.intType(16));
3084 },3086 },
3085 .float_array => |count| {3087 .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();
3087 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);3089 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
3088 const field_count = @as(c_uint, @intCast(count));3090 const field_count = @as(c_uint, @intCast(count));
3089 const arr_ty = float_ty.arrayType(field_count);3091 const arr_ty = float_ty.arrayType(field_count);
...@@ -3137,8 +3139,7 @@ pub const Object = struct {...@@ -3137,8 +3139,7 @@ pub const Object = struct {
3137 return llvm_type.getUndef();3139 return llvm_type.getUndef();
3138 }3140 }
31393141
3140 const val_key = mod.intern_pool.indexToKey(tv.val.toIntern());3142 switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
3141 switch (val_key) {
3142 .int_type,3143 .int_type,
3143 .ptr_type,3144 .ptr_type,
3144 .array_type,3145 .array_type,
...@@ -3175,12 +3176,14 @@ pub const Object = struct {...@@ -3175,12 +3176,14 @@ pub const Object = struct {
3175 .enum_literal,3176 .enum_literal,
3176 .empty_enum_value,3177 .empty_enum_value,
3177 => unreachable, // non-runtime values3178 => unreachable, // non-runtime values
3178 .extern_func, .func => {3179 .extern_func => |extern_func| {
3179 const fn_decl_index = switch (val_key) {3180 const fn_decl_index = extern_func.decl;
3180 .extern_func => |extern_func| extern_func.decl,3181 const fn_decl = mod.declPtr(fn_decl_index);
3181 .func => |func| mod.funcPtr(func.index).owner_decl,3182 try mod.markDeclAlive(fn_decl);
3182 else => unreachable,3183 return o.resolveLlvmFunction(fn_decl_index);
3183 };3184 },
3185 .func => |func| {
3186 const fn_decl_index = func.owner_decl;
3184 const fn_decl = mod.declPtr(fn_decl_index);3187 const fn_decl = mod.declPtr(fn_decl_index);
3185 try mod.markDeclAlive(fn_decl);3188 try mod.markDeclAlive(fn_decl);
3186 return o.resolveLlvmFunction(fn_decl_index);3189 return o.resolveLlvmFunction(fn_decl_index);
...@@ -4598,6 +4601,7 @@ pub const FuncGen = struct {...@@ -4598,6 +4601,7 @@ pub const FuncGen = struct {
4598 const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));4601 const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));
4599 const o = self.dg.object;4602 const o = self.dg.object;
4600 const mod = o.module;4603 const mod = o.module;
4604 const ip = &mod.intern_pool;
4601 const callee_ty = self.typeOf(pl_op.operand);4605 const callee_ty = self.typeOf(pl_op.operand);
4602 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {4606 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
4603 .Fn => callee_ty,4607 .Fn => callee_ty,
...@@ -4801,14 +4805,14 @@ pub const FuncGen = struct {...@@ -4801,14 +4805,14 @@ pub const FuncGen = struct {
4801 while (it.next()) |lowering| switch (lowering) {4805 while (it.next()) |lowering| switch (lowering) {
4802 .byval => {4806 .byval => {
4803 const param_index = it.zig_index - 1;4807 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();
4805 if (!isByRef(param_ty, mod)) {4809 if (!isByRef(param_ty, mod)) {
4806 o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);4810 o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
4807 }4811 }
4808 },4812 },
4809 .byref => {4813 .byref => {
4810 const param_index = it.zig_index - 1;4814 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();
4812 const param_llvm_ty = try o.lowerType(param_ty);4816 const param_llvm_ty = try o.lowerType(param_ty);
4813 const alignment = param_ty.abiAlignment(mod);4817 const alignment = param_ty.abiAlignment(mod);
4814 o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);4818 o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
...@@ -4828,7 +4832,7 @@ pub const FuncGen = struct {...@@ -4828,7 +4832,7 @@ pub const FuncGen = struct {
48284832
4829 .slice => {4833 .slice => {
4830 assert(!it.byval_attr);4834 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();
4832 const ptr_info = param_ty.ptrInfo(mod);4836 const ptr_info = param_ty.ptrInfo(mod);
4833 const llvm_arg_i = it.llvm_index - 2;4837 const llvm_arg_i = it.llvm_index - 2;
48344838
...@@ -4930,7 +4934,7 @@ pub const FuncGen = struct {...@@ -4930,7 +4934,7 @@ pub const FuncGen = struct {
4930 fg.context.pointerType(0).constNull(),4934 fg.context.pointerType(0).constNull(),
4931 null_opt_addr_global,4935 null_opt_addr_global,
4932 };4936 };
4933 const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?;4937 const panic_func = mod.funcInfo(mod.panic_func_index);
4934 const panic_decl = mod.declPtr(panic_func.owner_decl);4938 const panic_decl = mod.declPtr(panic_func.owner_decl);
4935 const fn_info = mod.typeToFunc(panic_decl.ty).?;4939 const fn_info = mod.typeToFunc(panic_decl.ty).?;
4936 const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);4940 const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);
...@@ -6030,7 +6034,7 @@ pub const FuncGen = struct {...@@ -6030,7 +6034,7 @@ pub const FuncGen = struct {
6030 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;6034 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
60316035
6032 const mod = o.module;6036 const mod = o.module;
6033 const func = mod.funcPtr(ty_fn.func);6037 const func = mod.funcInfo(ty_fn.func);
6034 const decl_index = func.owner_decl;6038 const decl_index = func.owner_decl;
6035 const decl = mod.declPtr(decl_index);6039 const decl = mod.declPtr(decl_index);
6036 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);6040 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
...@@ -6039,7 +6043,7 @@ pub const FuncGen = struct {...@@ -6039,7 +6043,7 @@ pub const FuncGen = struct {
6039 const cur_debug_location = self.builder.getCurrentDebugLocation2();6043 const cur_debug_location = self.builder.getCurrentDebugLocation2();
60406044
6041 try self.dbg_inlined.append(self.gpa, .{6045 try self.dbg_inlined.append(self.gpa, .{
6042 .loc = @as(*llvm.DILocation, @ptrCast(cur_debug_location)),6046 .loc = @ptrCast(cur_debug_location),
6043 .scope = self.di_scope.?,6047 .scope = self.di_scope.?,
6044 .base_line = self.base_line,6048 .base_line = self.base_line,
6045 });6049 });
...@@ -6057,8 +6061,6 @@ pub const FuncGen = struct {...@@ -6057,8 +6061,6 @@ pub const FuncGen = struct {
6057 .is_var_args = false,6061 .is_var_args = false,
6058 .is_generic = false,6062 .is_generic = false,
6059 .is_noinline = false,6063 .is_noinline = false,
6060 .align_is_generic = false,
6061 .cc_is_generic = false,
6062 .section_is_generic = false,6064 .section_is_generic = false,
6063 .addrspace_is_generic = false,6065 .addrspace_is_generic = false,
6064 });6066 });
...@@ -6090,8 +6092,7 @@ pub const FuncGen = struct {...@@ -6090,8 +6092,7 @@ pub const FuncGen = struct {
6090 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;6092 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
60916093
6092 const mod = o.module;6094 const mod = o.module;
6093 const func = mod.funcPtr(ty_fn.func);6095 const decl = mod.funcOwnerDeclPtr(ty_fn.func);
6094 const decl = mod.declPtr(func.owner_decl);
6095 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);6096 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
6096 self.di_file = di_file;6097 self.di_file = di_file;
6097 const old = self.dbg_inlined.pop();6098 const old = self.dbg_inlined.pop();
...@@ -8137,12 +8138,13 @@ pub const FuncGen = struct {...@@ -8137,12 +8138,13 @@ pub const FuncGen = struct {
8137 }8138 }
81388139
8139 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;8140 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);
8141 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;8143 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
8142 const lbrace_col = func.lbrace_column + 1;8144 const lbrace_col = func.lbrace_column + 1;
8143 const di_local_var = dib.createParameterVariable(8145 const di_local_var = dib.createParameterVariable(
8144 self.di_scope.?,8146 self.di_scope.?,
8145 func.getParamName(mod, src_index).ptr, // TODO test 0 bit args8147 mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args
8146 self.di_file.?,8148 self.di_file.?,
8147 lbrace_line,8149 lbrace_line,
8148 try o.lowerDebugType(inst_ty, .full),8150 try o.lowerDebugType(inst_ty, .full),
...@@ -10653,30 +10655,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {...@@ -10653,30 +10655,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
10653}10655}
1065410656
10655fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool {10657fn 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
10658 const target = mod.getTarget();10661 const target = mod.getTarget();
10659 switch (fn_info.cc) {10662 switch (fn_info.cc) {
10660 .Unspecified, .Inline => return isByRef(fn_info.return_type.toType(), mod),10663 .Unspecified, .Inline => return isByRef(return_type, mod),
10661 .C => switch (target.cpu.arch) {10664 .C => switch (target.cpu.arch) {
10662 .mips, .mipsel => return false,10665 .mips, .mipsel => return false,
10663 .x86_64 => switch (target.os.tag) {10666 .x86_64 => switch (target.os.tag) {
10664 .windows => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,10667 .windows => return x86_64_abi.classifyWindows(return_type, mod) == .memory,
10665 else => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),10668 else => return firstParamSRetSystemV(return_type, mod),
10666 },10669 },
10667 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type.toType(), mod)[0] == .indirect,10670 .wasm32 => return wasm_c_abi.classifyType(return_type, mod)[0] == .indirect,
10668 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,10671 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(return_type, mod) == .memory,
10669 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type.toType(), mod, .ret)) {10672 .arm, .armeb => switch (arm_c_abi.classifyType(return_type, mod, .ret)) {
10670 .memory, .i64_array => return true,10673 .memory, .i64_array => return true,
10671 .i32_array => |size| return size != 1,10674 .i32_array => |size| return size != 1,
10672 .byval => return false,10675 .byval => return false,
10673 },10676 },
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,
10675 else => return false, // TODO investigate C ABI for other architectures10678 else => return false, // TODO investigate C ABI for other architectures
10676 },10679 },
10677 .SysV => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),10680 .SysV => return firstParamSRetSystemV(return_type, mod),
10678 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,10681 .Win64 => return x86_64_abi.classifyWindows(return_type, mod) == .memory,
10679 .Stdcall => return !isScalar(mod, fn_info.return_type.toType()),10682 .Stdcall => return !isScalar(mod, return_type),
10680 else => return false,10683 else => return false,
10681 }10684 }
10682}10685}
...@@ -10888,13 +10891,17 @@ const ParamTypeIterator = struct {...@@ -10888,13 +10891,17 @@ const ParamTypeIterator = struct {
1088810891
10889 pub fn next(it: *ParamTypeIterator) ?Lowering {10892 pub fn next(it: *ParamTypeIterator) ?Lowering {
10890 if (it.zig_index >= it.fn_info.param_types.len) return null;10893 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];
10892 it.byval_attr = false;10897 it.byval_attr = false;
10893 return nextInner(it, ty.toType());10898 return nextInner(it, ty.toType());
10894 }10899 }
1089510900
10896 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.10901 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
10897 pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) ?Lowering {10902 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;
10898 if (it.zig_index >= it.fn_info.param_types.len) {10905 if (it.zig_index >= it.fn_info.param_types.len) {
10899 if (it.zig_index >= args.len) {10906 if (it.zig_index >= args.len) {
10900 return null;10907 return null;
...@@ -10902,7 +10909,7 @@ const ParamTypeIterator = struct {...@@ -10902,7 +10909,7 @@ const ParamTypeIterator = struct {
10902 return nextInner(it, fg.typeOf(args[it.zig_index]));10909 return nextInner(it, fg.typeOf(args[it.zig_index]));
10903 }10910 }
10904 } else {10911 } 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());
10906 }10913 }
10907 }10914 }
1090810915
src/codegen/spirv.zig+12-8
...@@ -238,7 +238,7 @@ pub const DeclGen = struct {...@@ -238,7 +238,7 @@ pub const DeclGen = struct {
238 if (ty.zigTypeTag(mod) == .Fn) {238 if (ty.zigTypeTag(mod) == .Fn) {
239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
240 .extern_func => |extern_func| extern_func.decl,240 .extern_func => |extern_func| extern_func.decl,
241 .func => |func| mod.funcPtr(func.index).owner_decl,241 .func => |func| func.owner_decl,
242 else => unreachable,242 else => unreachable,
243 };243 };
244 const spv_decl_index = try self.resolveDecl(fn_decl_index);244 const spv_decl_index = try self.resolveDecl(fn_decl_index);
...@@ -255,13 +255,14 @@ pub const DeclGen = struct {...@@ -255,13 +255,14 @@ pub const DeclGen = struct {
255 /// Fetch or allocate a result id for decl index. This function also marks the decl as alive.255 /// Fetch or allocate a result id for decl index. This function also marks the decl as alive.
256 /// Note: Function does not actually generate the decl.256 /// Note: Function does not actually generate the decl.
257 fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {257 fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
258 const decl = self.module.declPtr(decl_index);258 const mod = self.module;
259 try self.module.markDeclAlive(decl);259 const decl = mod.declPtr(decl_index);
260 try mod.markDeclAlive(decl);
260261
261 const entry = try self.decl_link.getOrPut(decl_index);262 const entry = try self.decl_link.getOrPut(decl_index);
262 if (!entry.found_existing) {263 if (!entry.found_existing) {
263 // TODO: Extern fn?264 // 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))
265 .func266 .func
266 else267 else
267 .global;268 .global;
...@@ -1268,6 +1269,7 @@ pub const DeclGen = struct {...@@ -1268,6 +1269,7 @@ pub const DeclGen = struct {
1268 },1269 },
1269 .Fn => switch (repr) {1270 .Fn => switch (repr) {
1270 .direct => {1271 .direct => {
1272 const ip = &mod.intern_pool;
1271 const fn_info = mod.typeToFunc(ty).?;1273 const fn_info = mod.typeToFunc(ty).?;
1272 // TODO: Put this somewhere in Sema.zig1274 // TODO: Put this somewhere in Sema.zig
1273 if (fn_info.is_var_args)1275 if (fn_info.is_var_args)
...@@ -1275,8 +1277,8 @@ pub const DeclGen = struct {...@@ -1275,8 +1277,8 @@ pub const DeclGen = struct {
12751277
1276 const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);1278 const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);
1277 defer self.gpa.free(param_ty_refs);1279 defer self.gpa.free(param_ty_refs);
1278 for (param_ty_refs, 0..) |*param_type, i| {1280 for (param_ty_refs, fn_info.param_types.get(ip)) |*param_type, fn_param_type| {
1279 param_type.* = try self.resolveType(fn_info.param_types[i].toType(), .direct);1281 param_type.* = try self.resolveType(fn_param_type.toType(), .direct);
1280 }1282 }
1281 const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct);1283 const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct);
12821284
...@@ -1576,6 +1578,7 @@ pub const DeclGen = struct {...@@ -1576,6 +1578,7 @@ pub const DeclGen = struct {
15761578
1577 fn genDecl(self: *DeclGen) !void {1579 fn genDecl(self: *DeclGen) !void {
1578 const mod = self.module;1580 const mod = self.module;
1581 const ip = &mod.intern_pool;
1579 const decl = mod.declPtr(self.decl_index);1582 const decl = mod.declPtr(self.decl_index);
1580 const spv_decl_index = try self.resolveDecl(self.decl_index);1583 const spv_decl_index = try self.resolveDecl(self.decl_index);
15811584
...@@ -1594,7 +1597,8 @@ pub const DeclGen = struct {...@@ -1594,7 +1597,8 @@ pub const DeclGen = struct {
1594 const fn_info = mod.typeToFunc(decl.ty).?;1597 const fn_info = mod.typeToFunc(decl.ty).?;
15951598
1596 try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);1599 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];
1598 const param_type_id = try self.resolveTypeId(param_type.toType());1602 const param_type_id = try self.resolveTypeId(param_type.toType());
1599 const arg_result_id = self.spv.allocId();1603 const arg_result_id = self.spv.allocId();
1600 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{1604 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
...@@ -1621,7 +1625,7 @@ pub const DeclGen = struct {...@@ -1621,7 +1625,7 @@ pub const DeclGen = struct {
1621 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});1625 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
1622 try self.spv.addFunction(spv_decl_index, self.func);1626 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
1626 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{1630 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
1627 .target = decl_id,1631 .target = decl_id,
src/link.zig+2-1
...@@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig");...@@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig");
16const LibCInstallation = @import("libc_installation.zig").LibCInstallation;16const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
17const Liveness = @import("Liveness.zig");17const Liveness = @import("Liveness.zig");
18const Module = @import("Module.zig");18const Module = @import("Module.zig");
19const InternPool = @import("InternPool.zig");
19const Package = @import("Package.zig");20const Package = @import("Package.zig");
20const Type = @import("type.zig").Type;21const Type = @import("type.zig").Type;
21const TypedValue = @import("TypedValue.zig");22const TypedValue = @import("TypedValue.zig");
...@@ -562,7 +563,7 @@ pub const File = struct {...@@ -562,7 +563,7 @@ pub const File = struct {
562 }563 }
563564
564 /// May be called before or after updateDeclExports for any given Decl.565 /// 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 {
566 if (build_options.only_c) {567 if (build_options.only_c) {
567 assert(base.tag == .c);568 assert(base.tag == .c);
568 return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness);569 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 {...@@ -88,13 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
88 }88 }
89}89}
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 {
92 const tracy = trace(@src());92 const tracy = trace(@src());
93 defer tracy.end();93 defer tracy.end();
9494
95 const gpa = self.base.allocator;95 const gpa = self.base.allocator;
9696
97 const func = module.funcPtr(func_index);97 const func = module.funcInfo(func_index);
98 const decl_index = func.owner_decl;98 const decl_index = func.owner_decl;
99 const gop = try self.decl_table.getOrPut(gpa, decl_index);99 const gop = try self.decl_table.getOrPut(gpa, decl_index);
100 if (!gop.found_existing) {100 if (!gop.found_existing) {
src/link/Coff.zig+3-3
...@@ -1032,7 +1032,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {...@@ -1032,7 +1032,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
1032 self.getAtomPtr(atom_index).sym_index = 0;1032 self.getAtomPtr(atom_index).sym_index = 0;
1033}1033}
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 {
1036 if (build_options.skip_non_native and builtin.object_format != .coff) {1036 if (build_options.skip_non_native and builtin.object_format != .coff) {
1037 @panic("Attempted to compile for object format that was disabled by build configuration");1037 @panic("Attempted to compile for object format that was disabled by build configuration");
1038 }1038 }
...@@ -1044,7 +1044,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: A...@@ -1044,7 +1044,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: A
1044 const tracy = trace(@src());1044 const tracy = trace(@src());
1045 defer tracy.end();1045 defer tracy.end();
10461046
1047 const func = mod.funcPtr(func_index);1047 const func = mod.funcInfo(func_index);
1048 const decl_index = func.owner_decl;1048 const decl_index = func.owner_decl;
1049 const decl = mod.declPtr(decl_index);1049 const decl = mod.declPtr(decl_index);
10501050
...@@ -1424,7 +1424,7 @@ pub fn updateDeclExports(...@@ -1424,7 +1424,7 @@ pub fn updateDeclExports(
1424 // detect the default subsystem.1424 // detect the default subsystem.
1425 for (exports) |exp| {1425 for (exports) |exp| {
1426 const exported_decl = mod.declPtr(exp.exported_decl);1426 const exported_decl = mod.declPtr(exp.exported_decl);
1427 if (exported_decl.getOwnedFunctionIndex(mod) == .none) continue;1427 if (exported_decl.getOwnedFunction(mod) == null) continue;
1428 const winapi_cc = switch (self.base.options.target.cpu.arch) {1428 const winapi_cc = switch (self.base.options.target.cpu.arch) {
1429 .x86 => std.builtin.CallingConvention.Stdcall,1429 .x86 => std.builtin.CallingConvention.Stdcall,
1430 else => std.builtin.CallingConvention.C,1430 else => std.builtin.CallingConvention.C,
src/link/Dwarf.zig+23-34
...@@ -1043,6 +1043,7 @@ pub fn commitDeclState(...@@ -1043,6 +1043,7 @@ pub fn commitDeclState(
1043 var dbg_line_buffer = &decl_state.dbg_line;1043 var dbg_line_buffer = &decl_state.dbg_line;
1044 var dbg_info_buffer = &decl_state.dbg_info;1044 var dbg_info_buffer = &decl_state.dbg_info;
1045 const decl = mod.declPtr(decl_index);1045 const decl = mod.declPtr(decl_index);
1046 const ip = &mod.intern_pool;
10461047
1047 const target_endian = self.target.cpu.arch.endian();1048 const target_endian = self.target.cpu.arch.endian();
10481049
...@@ -1241,20 +1242,9 @@ pub fn commitDeclState(...@@ -1241,20 +1242,9 @@ pub fn commitDeclState(
1241 while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) {1242 while (sym_index < decl_state.abbrev_table.items.len) : (sym_index += 1) {
1242 const symbol = &decl_state.abbrev_table.items[sym_index];1243 const symbol = &decl_state.abbrev_table.items[sym_index];
1243 const ty = symbol.type;1244 const ty = symbol.type;
1244 const deferred: bool = blk: {1245 if (ip.isErrorSetType(ty.toIntern())) continue;
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;
12561246
1257 symbol.offset = @as(u32, @intCast(dbg_info_buffer.items.len));1247 symbol.offset = @intCast(dbg_info_buffer.items.len);
1258 try decl_state.addDbgInfoType(mod, di_atom_index, ty);1248 try decl_state.addDbgInfoType(mod, di_atom_index, ty);
1259 }1249 }
1260 }1250 }
...@@ -1265,18 +1255,7 @@ pub fn commitDeclState(...@@ -1265,18 +1255,7 @@ pub fn commitDeclState(
1265 if (reloc.target) |target| {1255 if (reloc.target) |target| {
1266 const symbol = decl_state.abbrev_table.items[target];1256 const symbol = decl_state.abbrev_table.items[target];
1267 const ty = symbol.type;1257 const ty = symbol.type;
1268 const deferred: bool = blk: {1258 if (ip.isErrorSetType(ty.toIntern())) {
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) {
1280 log.debug("resolving %{d} deferred until flush", .{target});1259 log.debug("resolving %{d} deferred until flush", .{target});
1281 try self.global_abbrev_relocs.append(gpa, .{1260 try self.global_abbrev_relocs.append(gpa, .{
1282 .target = null,1261 .target = null,
...@@ -2505,18 +2484,18 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {...@@ -2505,18 +2484,18 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
2505 defer arena_alloc.deinit();2484 defer arena_alloc.deinit();
2506 const arena = arena_alloc.allocator();2485 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 } });
2514 var dbg_info_buffer = std.ArrayList(u8).init(arena);2487 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
2517 const di_atom_index = try self.createAtom(.di_atom);2496 const di_atom_index = try self.createAtom(.di_atom);
2518 log.debug("updateDeclDebugInfoAllocation in flushModule", .{});2497 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));
2520 log.debug("writeDeclDebugInfo in flushModule", .{});2499 log.debug("writeDeclDebugInfo in flushModule", .{});
2521 try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items);2500 try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items);
25222501
...@@ -2633,6 +2612,17 @@ fn addDbgInfoErrorSet(...@@ -2633,6 +2612,17 @@ fn addDbgInfoErrorSet(
2633 ty: Type,2612 ty: Type,
2634 target: std.Target,2613 target: std.Target,
2635 dbg_info_buffer: *std.ArrayList(u8),2614 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),
2636) !void {2626) !void {
2637 const target_endian = target.cpu.arch.endian();2627 const target_endian = target.cpu.arch.endian();
26382628
...@@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet(...@@ -2655,7 +2645,6 @@ fn addDbgInfoErrorSet(
2655 // DW.AT.const_value, DW.FORM.data82645 // DW.AT.const_value, DW.FORM.data8
2656 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);2646 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
26572647
2658 const error_names = ty.errorSetNames(mod);
2659 for (error_names) |error_name_ip| {2648 for (error_names) |error_name_ip| {
2660 const int = try mod.getErrorValue(error_name_ip);2649 const int = try mod.getErrorValue(error_name_ip);
2661 const error_name = mod.intern_pool.stringToSlice(error_name_ip);2650 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...@@ -2575,7 +2575,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2575 return local_sym;2575 return local_sym;
2576}2576}
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 {
2579 if (build_options.skip_non_native and builtin.object_format != .elf) {2579 if (build_options.skip_non_native and builtin.object_format != .elf) {
2580 @panic("Attempted to compile for object format that was disabled by build configuration");2580 @panic("Attempted to compile for object format that was disabled by build configuration");
2581 }2581 }
...@@ -2586,7 +2586,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Ai...@@ -2586,7 +2586,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Ai
2586 const tracy = trace(@src());2586 const tracy = trace(@src());
2587 defer tracy.end();2587 defer tracy.end();
25882588
2589 const func = mod.funcPtr(func_index);2589 const func = mod.funcInfo(func_index);
2590 const decl_index = func.owner_decl;2590 const decl_index = func.owner_decl;
2591 const decl = mod.declPtr(decl_index);2591 const decl = mod.declPtr(decl_index);
25922592
src/link/MachO.zig+2-2
...@@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {...@@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
1845 self.markRelocsDirtyByTarget(target);1845 self.markRelocsDirtyByTarget(target);
1846}1846}
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 {
1849 if (build_options.skip_non_native and builtin.object_format != .macho) {1849 if (build_options.skip_non_native and builtin.object_format != .macho) {
1850 @panic("Attempted to compile for object format that was disabled by build configuration");1850 @panic("Attempted to compile for object format that was disabled by build configuration");
1851 }1851 }
...@@ -1855,7 +1855,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air:...@@ -1855,7 +1855,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air:
1855 const tracy = trace(@src());1855 const tracy = trace(@src());
1856 defer tracy.end();1856 defer tracy.end();
18571857
1858 const func = mod.funcPtr(func_index);1858 const func = mod.funcInfo(func_index);
1859 const decl_index = func.owner_decl;1859 const decl_index = func.owner_decl;
1860 const decl = mod.declPtr(decl_index);1860 const decl = mod.declPtr(decl_index);
18611861
src/link/NvPtx.zig+2-1
...@@ -13,6 +13,7 @@ const assert = std.debug.assert;...@@ -13,6 +13,7 @@ const assert = std.debug.assert;
13const log = std.log.scoped(.link);13const log = std.log.scoped(.link);
1414
15const Module = @import("../Module.zig");15const Module = @import("../Module.zig");
16const InternPool = @import("../InternPool.zig");
16const Compilation = @import("../Compilation.zig");17const Compilation = @import("../Compilation.zig");
17const link = @import("../link.zig");18const link = @import("../link.zig");
18const trace = @import("../tracy.zig").trace;19const trace = @import("../tracy.zig").trace;
...@@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void {...@@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void {
68 self.base.allocator.free(self.ptx_file_name);69 self.base.allocator.free(self.ptx_file_name);
69}70}
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 {
72 if (!build_options.have_llvm) return;73 if (!build_options.have_llvm) return;
73 try self.llvm_object.updateFunc(module, func_index, air, liveness);74 try self.llvm_object.updateFunc(module, func_index, air, liveness);
74}75}
src/link/Plan9.zig+4-3
...@@ -4,6 +4,7 @@...@@ -4,6 +4,7 @@
4const Plan9 = @This();4const Plan9 = @This();
5const link = @import("../link.zig");5const link = @import("../link.zig");
6const Module = @import("../Module.zig");6const Module = @import("../Module.zig");
7const InternPool = @import("../InternPool.zig");
7const Compilation = @import("../Compilation.zig");8const Compilation = @import("../Compilation.zig");
8const aout = @import("Plan9/aout.zig");9const aout = @import("Plan9/aout.zig");
9const codegen = @import("../codegen.zig");10const codegen = @import("../codegen.zig");
...@@ -344,12 +345,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi...@@ -344,12 +345,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi
344 }345 }
345}346}
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 {
348 if (build_options.skip_non_native and builtin.object_format != .plan9) {349 if (build_options.skip_non_native and builtin.object_format != .plan9) {
349 @panic("Attempted to compile for object format that was disabled by build configuration");350 @panic("Attempted to compile for object format that was disabled by build configuration");
350 }351 }
351352
352 const func = mod.funcPtr(func_index);353 const func = mod.funcInfo(func_index);
353 const decl_index = func.owner_decl;354 const decl_index = func.owner_decl;
354 const decl = mod.declPtr(decl_index);355 const decl = mod.declPtr(decl_index);
355 self.freeUnnamedConsts(decl_index);356 self.freeUnnamedConsts(decl_index);
...@@ -908,7 +909,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {...@@ -908,7 +909,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
908 // in the deleteUnusedDecl function.909 // in the deleteUnusedDecl function.
909 const mod = self.base.options.module.?;910 const mod = self.base.options.module.?;
910 const decl = mod.declPtr(decl_index);911 const decl = mod.declPtr(decl_index);
911 const is_fn = decl.val.getFunctionIndex(mod) != .none;912 const is_fn = decl.val.isFuncBody(mod);
912 if (is_fn) {913 if (is_fn) {
913 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;914 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
914 var submap = symidx_and_submap.functions;915 var submap = symidx_and_submap.functions;
src/link/SpirV.zig+4-3
...@@ -29,6 +29,7 @@ const assert = std.debug.assert;...@@ -29,6 +29,7 @@ const assert = std.debug.assert;
29const log = std.log.scoped(.link);29const log = std.log.scoped(.link);
3030
31const Module = @import("../Module.zig");31const Module = @import("../Module.zig");
32const InternPool = @import("../InternPool.zig");
32const Compilation = @import("../Compilation.zig");33const Compilation = @import("../Compilation.zig");
33const link = @import("../link.zig");34const link = @import("../link.zig");
34const codegen = @import("../codegen/spirv.zig");35const codegen = @import("../codegen/spirv.zig");
...@@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void {...@@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void {
103 self.decl_link.deinit();104 self.decl_link.deinit();
104}105}
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 {
107 if (build_options.skip_non_native) {108 if (build_options.skip_non_native) {
108 @panic("Attempted to compile for architecture that was disabled by build configuration");109 @panic("Attempted to compile for architecture that was disabled by build configuration");
109 }110 }
110111
111 const func = module.funcPtr(func_index);112 const func = module.funcInfo(func_index);
112113
113 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);114 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
114 defer decl_gen.deinit();115 defer decl_gen.deinit();
...@@ -138,7 +139,7 @@ pub fn updateDeclExports(...@@ -138,7 +139,7 @@ pub fn updateDeclExports(
138 exports: []const *Module.Export,139 exports: []const *Module.Export,
139) !void {140) !void {
140 const decl = mod.declPtr(decl_index);141 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) {
142 // TODO: Unify with resolveDecl in spirv.zig.143 // TODO: Unify with resolveDecl in spirv.zig.
143 const entry = try self.decl_link.getOrPut(decl_index);144 const entry = try self.decl_link.getOrPut(decl_index);
144 if (!entry.found_existing) {145 if (!entry.found_existing) {
src/link/Wasm.zig+3-2
...@@ -12,6 +12,7 @@ const log = std.log.scoped(.link);...@@ -12,6 +12,7 @@ const log = std.log.scoped(.link);
12pub const Atom = @import("Wasm/Atom.zig");12pub const Atom = @import("Wasm/Atom.zig");
13const Dwarf = @import("Dwarf.zig");13const Dwarf = @import("Dwarf.zig");
14const Module = @import("../Module.zig");14const Module = @import("../Module.zig");
15const InternPool = @import("../InternPool.zig");
15const Compilation = @import("../Compilation.zig");16const Compilation = @import("../Compilation.zig");
16const CodeGen = @import("../arch/wasm/CodeGen.zig");17const CodeGen = @import("../arch/wasm/CodeGen.zig");
17const codegen = @import("../codegen.zig");18const codegen = @import("../codegen.zig");
...@@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {...@@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
1338 return index;1339 return index;
1339}1340}
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 {
1342 if (build_options.skip_non_native and builtin.object_format != .wasm) {1343 if (build_options.skip_non_native and builtin.object_format != .wasm) {
1343 @panic("Attempted to compile for object format that was disabled by build configuration");1344 @panic("Attempted to compile for object format that was disabled by build configuration");
1344 }1345 }
...@@ -1349,7 +1350,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: A...@@ -1349,7 +1350,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: A
1349 const tracy = trace(@src());1350 const tracy = trace(@src());
1350 defer tracy.end();1351 defer tracy.end();
13511352
1352 const func = mod.funcPtr(func_index);1353 const func = mod.funcInfo(func_index);
1353 const decl_index = func.owner_decl;1354 const decl_index = func.owner_decl;
1354 const decl = mod.declPtr(decl_index);1355 const decl = mod.declPtr(decl_index);
1355 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);1356 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
src/print_air.zig+1-1
...@@ -665,7 +665,7 @@ const Writer = struct {...@@ -665,7 +665,7 @@ const Writer = struct {
665 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {665 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
666 const ty_fn = w.air.instructions.items(.data)[inst].ty_fn;666 const ty_fn = w.air.instructions.items(.data)[inst].ty_fn;
667 const func_index = ty_fn.func;667 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);
669 try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});669 try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});
670 }670 }
671671
src/type.zig+53-43
...@@ -250,21 +250,19 @@ pub const Type = struct {...@@ -250,21 +250,19 @@ pub const Type = struct {
250 try print(error_union_type.payload_type.toType(), writer, mod);250 try print(error_union_type.payload_type.toType(), writer, mod);
251 return;251 return;
252 },252 },
253 .inferred_error_set_type => |index| {253 .inferred_error_set_type => |func_index| {
254 const ies = mod.inferredErrorSetPtr(index);
255 const func = ies.func;
256
257 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");254 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);
259 try owner_decl.renderFullyQualifiedName(mod, writer);256 try owner_decl.renderFullyQualifiedName(mod, writer);
260 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");257 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
261 },258 },
262 .error_set_type => |error_set_type| {259 .error_set_type => |error_set_type| {
260 const ip = &mod.intern_pool;
263 const names = error_set_type.names;261 const names = error_set_type.names;
264 try writer.writeAll("error{");262 try writer.writeAll("error{");
265 for (names, 0..) |name, i| {263 for (names.get(ip), 0..) |name, i| {
266 if (i != 0) try writer.writeByte(',');264 if (i != 0) try writer.writeByte(',');
267 try writer.print("{}", .{name.fmt(&mod.intern_pool)});265 try writer.print("{}", .{name.fmt(ip)});
268 }266 }
269 try writer.writeAll("}");267 try writer.writeAll("}");
270 },268 },
...@@ -294,6 +292,7 @@ pub const Type = struct {...@@ -294,6 +292,7 @@ pub const Type = struct {
294 .comptime_int,292 .comptime_int,
295 .comptime_float,293 .comptime_float,
296 .noreturn,294 .noreturn,
295 .adhoc_inferred_error_set,
297 => return writer.writeAll(@tagName(s)),296 => return writer.writeAll(@tagName(s)),
298297
299 .null,298 .null,
...@@ -367,7 +366,8 @@ pub const Type = struct {...@@ -367,7 +366,8 @@ pub const Type = struct {
367 try writer.writeAll("noinline ");366 try writer.writeAll("noinline ");
368 }367 }
369 try writer.writeAll("fn(");368 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| {
371 if (i != 0) try writer.writeAll(", ");371 if (i != 0) try writer.writeAll(", ");
372 if (std.math.cast(u5, i)) |index| {372 if (std.math.cast(u5, i)) |index| {
373 if (fn_info.paramIsComptime(index)) {373 if (fn_info.paramIsComptime(index)) {
...@@ -384,7 +384,7 @@ pub const Type = struct {...@@ -384,7 +384,7 @@ pub const Type = struct {
384 }384 }
385 }385 }
386 if (fn_info.is_var_args) {386 if (fn_info.is_var_args) {
387 if (fn_info.param_types.len != 0) {387 if (param_types.len != 0) {
388 try writer.writeAll(", ");388 try writer.writeAll(", ");
389 }389 }
390 try writer.writeAll("...");390 try writer.writeAll("...");
...@@ -534,6 +534,7 @@ pub const Type = struct {...@@ -534,6 +534,7 @@ pub const Type = struct {
534 .c_longdouble,534 .c_longdouble,
535 .bool,535 .bool,
536 .anyerror,536 .anyerror,
537 .adhoc_inferred_error_set,
537 .anyopaque,538 .anyopaque,
538 .atomic_order,539 .atomic_order,
539 .atomic_rmw_op,540 .atomic_rmw_op,
...@@ -697,6 +698,7 @@ pub const Type = struct {...@@ -697,6 +698,7 @@ pub const Type = struct {
697 => true,698 => true,
698699
699 .anyerror,700 .anyerror,
701 .adhoc_inferred_error_set,
700 .anyopaque,702 .anyopaque,
701 .atomic_order,703 .atomic_order,
702 .atomic_rmw_op,704 .atomic_rmw_op,
...@@ -955,7 +957,9 @@ pub const Type = struct {...@@ -955,7 +957,9 @@ pub const Type = struct {
955 },957 },
956958
957 // TODO revisit this when we have the concept of the error tag type959 // 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
960 .void,964 .void,
961 .type,965 .type,
...@@ -1419,7 +1423,9 @@ pub const Type = struct {...@@ -1419,7 +1423,9 @@ pub const Type = struct {
1419 => return AbiSizeAdvanced{ .scalar = 0 },1423 => return AbiSizeAdvanced{ .scalar = 0 },
14201424
1421 // TODO revisit this when we have the concept of the error tag type1425 // 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
1424 .prefetch_options => unreachable, // missing call to resolveTypeFields1430 .prefetch_options => unreachable, // missing call to resolveTypeFields
1425 .export_options => unreachable, // missing call to resolveTypeFields1431 .export_options => unreachable, // missing call to resolveTypeFields
...@@ -1662,7 +1668,9 @@ pub const Type = struct {...@@ -1662,7 +1668,9 @@ pub const Type = struct {
1662 .void => return 0,1668 .void => return 0,
16631669
1664 // TODO revisit this when we have the concept of the error tag type1670 // 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
1667 .anyopaque => unreachable,1675 .anyopaque => unreachable,
1668 .type => unreachable,1676 .type => unreachable,
...@@ -2050,21 +2058,19 @@ pub const Type = struct {...@@ -2050,21 +2058,19 @@ pub const Type = struct {
20502058
2051 /// Asserts that the type is an error union.2059 /// Asserts that the type is an error union.
2052 pub fn errorUnionSet(ty: Type, mod: *Module) Type {2060 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();
2054 }2062 }
20552063
2056 /// Returns false for unresolved inferred error sets.2064 /// Returns false for unresolved inferred error sets.
2057 pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool {2065 pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool {
2066 const ip = &mod.intern_pool;
2058 return switch (ty.toIntern()) {2067 return switch (ty.toIntern()) {
2059 .anyerror_type => false,2068 .anyerror_type => false,
2060 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {2069 else => switch (ip.indexToKey(ty.toIntern())) {
2061 .error_set_type => |error_set_type| error_set_type.names.len == 0,2070 .error_set_type => |error_set_type| error_set_type.names.len == 0,
2062 .inferred_error_set_type => |index| {2071 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2063 const inferred_error_set = mod.inferredErrorSetPtr(index);2072 .none, .anyerror_type => false,
2064 // Can't know for sure.2073 else => |t| ip.indexToKey(t).error_set_type.names.len == 0,
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;
2068 },2074 },
2069 else => unreachable,2075 else => unreachable,
2070 },2076 },
...@@ -2075,10 +2081,11 @@ pub const Type = struct {...@@ -2075,10 +2081,11 @@ pub const Type = struct {
2075 /// Note that the result may be a false negative if the type did not get error set2081 /// Note that the result may be a false negative if the type did not get error set
2076 /// resolution prior to this call.2082 /// resolution prior to this call.
2077 pub fn isAnyError(ty: Type, mod: *Module) bool {2083 pub fn isAnyError(ty: Type, mod: *Module) bool {
2084 const ip = &mod.intern_pool;
2078 return switch (ty.toIntern()) {2085 return switch (ty.toIntern()) {
2079 .anyerror_type => true,2086 .anyerror_type => true,
2080 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {2087 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,
2082 else => false,2089 else => false,
2083 },2090 },
2084 };2091 };
...@@ -2102,13 +2109,11 @@ pub const Type = struct {...@@ -2102,13 +2109,11 @@ pub const Type = struct {
2102 return switch (ty) {2109 return switch (ty) {
2103 .anyerror_type => true,2110 .anyerror_type => true,
2104 else => switch (ip.indexToKey(ty)) {2111 else => switch (ip.indexToKey(ty)) {
2105 .error_set_type => |error_set_type| {2112 .error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null,
2106 return error_set_type.nameIndex(ip, name) != null;2113 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2107 },2114 .anyerror_type => true,
2108 .inferred_error_set_type => |index| {2115 .none => false,
2109 const ies = ip.inferredErrorSetPtrConst(index);2116 else => |t| ip.indexToKey(t).error_set_type.nameIndex(ip, name) != null,
2110 if (ies.is_anyerror) return true;
2111 return ies.errors.contains(name);
2112 },2117 },
2113 else => unreachable,2118 else => unreachable,
2114 },2119 },
...@@ -2128,12 +2133,14 @@ pub const Type = struct {...@@ -2128,12 +2133,14 @@ pub const Type = struct {
2128 const field_name_interned = ip.getString(name).unwrap() orelse return false;2133 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2129 return error_set_type.nameIndex(ip, field_name_interned) != null;2134 return error_set_type.nameIndex(ip, field_name_interned) != null;
2130 },2135 },
2131 .inferred_error_set_type => |index| {2136 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2132 const ies = ip.inferredErrorSetPtr(index);2137 .anyerror_type => true,
2133 if (ies.is_anyerror) return true;2138 .none => false,
2134 // If the string is not interned, then the field certainly is not present.2139 else => |t| {
2135 const field_name_interned = ip.getString(name).unwrap() orelse return false;2140 // If the string is not interned, then the field certainly is not present.
2136 return ies.errors.contains(field_name_interned);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 },
2137 },2144 },
2138 else => unreachable,2145 else => unreachable,
2139 },2146 },
...@@ -2231,7 +2238,7 @@ pub const Type = struct {...@@ -2231,7 +2238,7 @@ pub const Type = struct {
2231 var ty = starting_ty;2238 var ty = starting_ty;
22322239
2233 while (true) switch (ty.toIntern()) {2240 while (true) switch (ty.toIntern()) {
2234 .anyerror_type => {2241 .anyerror_type, .adhoc_inferred_error_set_type => {
2235 // TODO revisit this when error sets support custom int types2242 // TODO revisit this when error sets support custom int types
2236 return .{ .signedness = .unsigned, .bits = 16 };2243 return .{ .signedness = .unsigned, .bits = 16 };
2237 },2244 },
...@@ -2365,7 +2372,7 @@ pub const Type = struct {...@@ -2365,7 +2372,7 @@ pub const Type = struct {
23652372
2366 /// Asserts the type is a function or a function pointer.2373 /// Asserts the type is a function or a function pointer.
2367 pub fn fnReturnType(ty: Type, mod: *Module) Type {2374 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();
2369 }2376 }
23702377
2371 /// Asserts the type is a function.2378 /// Asserts the type is a function.
...@@ -2505,6 +2512,7 @@ pub const Type = struct {...@@ -2505,6 +2512,7 @@ pub const Type = struct {
2505 .export_options,2512 .export_options,
2506 .extern_options,2513 .extern_options,
2507 .type_info,2514 .type_info,
2515 .adhoc_inferred_error_set,
2508 => return null,2516 => return null,
25092517
2510 .void => return Value.void,2518 .void => return Value.void,
...@@ -2699,6 +2707,7 @@ pub const Type = struct {...@@ -2699,6 +2707,7 @@ pub const Type = struct {
2699 .bool,2707 .bool,
2700 .void,2708 .void,
2701 .anyerror,2709 .anyerror,
2710 .adhoc_inferred_error_set,
2702 .noreturn,2711 .noreturn,
2703 .generic_poison,2712 .generic_poison,
2704 .atomic_order,2713 .atomic_order,
...@@ -2942,14 +2951,15 @@ pub const Type = struct {...@@ -2942,14 +2951,15 @@ pub const Type = struct {
2942 }2951 }
29432952
2944 // Asserts that `ty` is an error set and not `anyerror`.2953 // Asserts that `ty` is an error set and not `anyerror`.
2954 // Asserts that `ty` is resolved if it is an inferred error set.
2945 pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {2955 pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
2946 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {2956 const ip = &mod.intern_pool;
2947 .error_set_type => |x| x.names,2957 return switch (ip.indexToKey(ty.toIntern())) {
2948 .inferred_error_set_type => |index| {2958 .error_set_type => |x| x.names.get(ip),
2949 const inferred_error_set = mod.inferredErrorSetPtr(index);2959 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2950 assert(inferred_error_set.is_resolved);2960 .none => unreachable, // unresolved inferred error set
2951 assert(!inferred_error_set.is_anyerror);2961 .anyerror_type => unreachable,
2952 return inferred_error_set.errors.keys();2962 else => |t| ip.indexToKey(t).error_set_type.names.get(ip),
2953 },2963 },
2954 else => unreachable,2964 else => unreachable,
2955 };2965 };
src/value.zig+13-5
...@@ -262,6 +262,11 @@ pub const Value = struct {...@@ -262,6 +262,11 @@ pub const Value = struct {
262 return ip.getOrPutTrailingString(gpa, len);262 return ip.getOrPutTrailingString(gpa, len);
263 }263 }
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
265 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {270 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
266 if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();271 if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();
267 switch (val.tag()) {272 switch (val.tag()) {
...@@ -473,12 +478,15 @@ pub const Value = struct {...@@ -473,12 +478,15 @@ pub const Value = struct {
473 };478 };
474 }479 }
475480
476 pub fn getFunction(val: Value, mod: *Module) ?*Module.Fn {481 pub fn isFuncBody(val: Value, mod: *Module) bool {
477 return mod.funcPtrUnwrap(val.getFunctionIndex(mod));482 return mod.intern_pool.isFuncBody(val.toIntern());
478 }483 }
479484
480 pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex {485 pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func {
481 return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.toIntern()) else .none;486 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
487 .func => |x| x,
488 else => null,
489 };
482 }490 }
483491
484 pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {492 pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
...@@ -1462,7 +1470,7 @@ pub const Value = struct {...@@ -1462,7 +1470,7 @@ pub const Value = struct {
1462 return switch (mod.intern_pool.indexToKey(val.toIntern())) {1470 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1463 .variable => |variable| variable.decl,1471 .variable => |variable| variable.decl,
1464 .extern_func => |extern_func| extern_func.decl,1472 .extern_func => |extern_func| extern_func.decl,
1465 .func => |func| mod.funcPtr(func.index).owner_decl,1473 .func => |func| func.owner_decl,
1466 .ptr => |ptr| switch (ptr.addr) {1474 .ptr => |ptr| switch (ptr.addr) {
1467 .decl => |decl| decl,1475 .decl => |decl| decl,
1468 .mut_decl => |mut_decl| mut_decl.decl,1476 .mut_decl => |mut_decl| mut_decl.decl,
test/behavior/generics.zig+13
...@@ -443,3 +443,16 @@ test "generic function passed as comptime argument" {...@@ -443,3 +443,16 @@ test "generic function passed as comptime argument" {
443 };443 };
444 try S.doMath(std.math.add, 5, 6);444 try S.doMath(std.math.add, 5, 6);
445}445}
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 {...@@ -16,5 +16,7 @@ pub export fn entry() void {
16// backend=stage216// backend=stage2
17// target=native17// target=native
18//18//
19// :7:14: error: unable to resolve comptime value19// :7:14: error: runtime-known argument passed to comptime-only type parameter
20// :7:14: note: argument to parameter with comptime-only type must be comptime-known20// :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 {...@@ -6,4 +6,4 @@ export fn foo(comptime x: anytype, y: i32) i32 {
6// backend=stage26// backend=stage2
7// target=native7// target=native
8//8//
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 {...@@ -7,4 +7,4 @@ export fn foo(num: anytype) i32 {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
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 {...@@ -19,5 +19,5 @@ comptime {
19// target=native19// target=native
20//20//
21// :5:30: error: comptime parameters not allowed in function with calling convention 'C'21// :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'
23// :1:15: error: comptime parameters not allowed in function with calling convention 'C'23// :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 {...@@ -13,5 +13,5 @@ export fn entry() usize {
13// backend=stage213// backend=stage2
14// target=native14// target=native
15//15//
16// :5:16: error: unable to resolve comptime value16// :5:16: error: runtime-known argument passed to comptime parameter
17// :5:16: note: parameter is comptime17// :1:17: note: declared comptime here
test/standalone.zig-4
...@@ -213,10 +213,6 @@ pub const build_cases = [_]BuildCase{...@@ -213,10 +213,6 @@ pub const build_cases = [_]BuildCase{
213 // .build_root = "test/standalone/sigpipe",213 // .build_root = "test/standalone/sigpipe",
214 // .import = @import("standalone/sigpipe/build.zig"),214 // .import = @import("standalone/sigpipe/build.zig"),
215 //},215 //},
216 .{
217 .build_root = "test/standalone/issue_13030",
218 .import = @import("standalone/issue_13030/build.zig"),
219 },
220 // TODO restore this test216 // TODO restore this test
221 //.{217 //.{
222 // .build_root = "test/standalone/options",218 // .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}