authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-03 22:09:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-18 19:02:05-07:00
logdb33ee45b7261c9ec62a1087cfc9377bc4e7aa8f
tree81e1f629c296a8a9c9573879382586dac3784737
parent70c71935c7c9f20353dc2a50b497b752d70d3452

rework generic function calls

Abridged summary: * Move `Module.Fn` into `InternPool`. * Delete a lot of confusing and problematic `Sema` logic related to generic function calls. This commit removes `Module.Fn` and replaces it with two new `InternPool.Tag` values: * `func_decl` - corresponding to a function declared in the source code. This one contains line/column numbers, zir_body_inst, etc. * `func_instance` - one for each monomorphization of a generic function. Contains a reference to the `func_decl` from whence the instantiation came, along with the `comptime` parameter values (or types in the case of `anytype`) Since `InternPool` provides deduplication on these values, these fields are now deleted from `Module`: * `monomorphed_func_keys` * `monomorphed_funcs` * `align_stack_fns` Instead of these, Sema logic for generic function instantiation now unconditionally evaluates the function prototype expression for every generic callsite. This is technically required in order for type coercions to work. The previous code had some dubious, probably wrong hacks to make things work, such as `hashUncoerced`. I'm not 100% sure how we were able to eliminate that function and still pass all the behavior tests, but I'm pretty sure things were still broken without doing type coercion for every generic function call argument. After the function prototype is evaluated, it produces a deduplicated `func_instance` `InternPool.Index` which can then be used for the generic function call. Some other nice things made by this simplification are the removal of `comptime_args_fn_inst` and `preallocated_new_func` from `Sema`, and the messy logic associated with them. I have not yet been able to measure the perf of this against master branch. On one hand, it reduces memory usage and pointer chasing of the most heavily used `InternPool` Tag - function bodies - but on the other hand, it does evaluate function prototype expressions more than before. We will soon find out.

30 files changed, 1737 insertions(+), 1962 deletions(-)

src/Air.zig+1-1
......@@ -1003,7 +1003,7 @@ pub const Inst = struct {
10031003 },
10041004 ty_fn: struct {
10051005 ty: Ref,
1006 func: Module.Fn.Index,
1006 func: InternPool.Index,
10071007 },
10081008 br: struct {
10091009 block_inst: Index,
src/Compilation.zig+4-3
......@@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig");
2929const fatal = @import("main.zig").fatal;
3030const clangMain = @import("main.zig").clangMain;
3131const Module = @import("Module.zig");
32const InternPool = @import("InternPool.zig");
3233const BuildId = std.Build.CompileStep.BuildId;
3334const Cache = std.Build.Cache;
3435const translate_c = @import("translate_c.zig");
......@@ -227,7 +228,8 @@ const Job = union(enum) {
227228 /// Write the constant value for a Decl to the output file.
228229 codegen_decl: Module.Decl.Index,
229230 /// Write the machine code for a function to the output file.
230 codegen_func: Module.Fn.Index,
231 /// This will either be a non-generic `func_decl` or a `func_instance`.
232 codegen_func: InternPool.Index,
231233 /// Render the .h file snippet for the Decl.
232234 emit_h_decl: Module.Decl.Index,
233235 /// The Decl needs to be analyzed and possibly export itself.
......@@ -3216,8 +3218,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
32163218 // Tests are always emitted in test binaries. The decl_refs are created by
32173219 // Module.populateTestFunctions, but this will not queue body analysis, so do
32183220 // that now.
3219 const func_index = module.intern_pool.indexToFunc(decl.val.ip_index).unwrap().?;
3220 try module.ensureFuncBodyAnalysisQueued(func_index);
3221 try module.ensureFuncBodyAnalysisQueued(decl.val.toIntern());
32213222 }
32223223 },
32233224 .update_embed_file => |embed_file| {
src/InternPool.zig+490-221
......@@ -34,19 +34,13 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},
3434/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.
3535unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},
3636
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
4337/// InferredErrorSet objects are stored in this data structure because:
4438/// * They contain pointers such as the errors map and the set of other inferred error sets.
4539/// * They need to be mutated after creation.
46allocated_inferred_error_sets: std.SegmentedList(Module.Fn.InferredErrorSet, 0) = .{},
40allocated_inferred_error_sets: std.SegmentedList(Module.InferredErrorSet, 0) = .{},
4741/// When a Struct object is freed from `allocated_inferred_error_sets`, it is
4842/// pushed into this stack.
49inferred_error_sets_free_list: std.ArrayListUnmanaged(Module.Fn.InferredErrorSet.Index) = .{},
43inferred_error_sets_free_list: std.ArrayListUnmanaged(Module.InferredErrorSet.Index) = .{},
5044
5145/// Some types such as enums, structs, and unions need to store mappings from field names
5246/// to field index, or value to field index. In such cases, they will store the underlying
......@@ -73,6 +67,7 @@ const Hash = std.hash.Wyhash;
7367
7468const InternPool = @This();
7569const Module = @import("Module.zig");
70const Zir = @import("Zir.zig");
7671const Sema = @import("Sema.zig");
7772
7873const KeyAdapter = struct {
......@@ -224,7 +219,7 @@ pub const Key = union(enum) {
224219 enum_type: EnumType,
225220 func_type: FuncType,
226221 error_set_type: ErrorSetType,
227 inferred_error_set_type: Module.Fn.InferredErrorSet.Index,
222 inferred_error_set_type: Module.InferredErrorSet.Index,
228223
229224 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
230225 /// via `simple_value` and has a named `Index` tag for it.
......@@ -487,7 +482,7 @@ pub const Key = union(enum) {
487482 };
488483
489484 pub const FuncType = struct {
490 param_types: []Index,
485 param_types: Index.Slice,
491486 return_type: Index,
492487 /// Tells whether a parameter is comptime. See `paramIsComptime` helper
493488 /// method for accessing this.
......@@ -541,10 +536,61 @@ pub const Key = union(enum) {
541536 lib_name: OptionalNullTerminatedString,
542537 };
543538
544 /// Extern so it can be hashed by reinterpreting memory.
545 pub const Func = extern struct {
539 pub const Func = struct {
540 /// In the case of a generic function, this type will potentially have fewer parameters
541 /// than the generic owner's type, because the comptime parameters will be deleted.
546542 ty: Index,
547 index: Module.Fn.Index,
543 /// Index into extra array of the `FuncAnalysis` corresponding to this function.
544 /// Used for mutating that data.
545 analysis_extra_index: u32,
546 /// Index into extra array of the `zir_body_inst` corresponding to this function.
547 /// Used for mutating that data.
548 zir_body_inst_extra_index: u32,
549 /// When a generic function is instantiated, branch_quota is inherited from the
550 /// active Sema context. Importantly, this value is also updated when an existing
551 /// generic function instantiation is found and called.
552 /// This field contains the index into the extra array of this value,
553 /// so that it can be mutated.
554 /// This will be 0 when the function is not a generic function instantiation.
555 branch_quota_extra_index: u32,
556 /// The Decl that corresponds to the function itself.
557 owner_decl: Module.Decl.Index,
558 /// The ZIR instruction that is a function instruction. Use this to find
559 /// the body. We store this rather than the body directly so that when ZIR
560 /// is regenerated on update(), we can map this to the new corresponding
561 /// ZIR instruction.
562 zir_body_inst: Zir.Inst.Index,
563 /// Relative to owner Decl.
564 lbrace_line: u32,
565 /// Relative to owner Decl.
566 rbrace_line: u32,
567 lbrace_column: u32,
568 rbrace_column: u32,
569
570 /// The `func_decl` which is the generic function from whence this instance was spawned.
571 /// If this is `none` it means the function is not a generic instantiation.
572 generic_owner: Index,
573 /// If this is a generic function instantiation, this will be non-empty.
574 /// Corresponds to the parameters of the `generic_owner` type, which
575 /// may have more parameters than `ty`.
576 /// Each element is the comptime-known value the generic function was instantiated with,
577 /// or `none` if the element is runtime-known.
578 /// TODO: as a follow-up optimization, don't store `none` values here since that data
579 /// is redundant with `comptime_bits` stored elsewhere.
580 comptime_args: Index.Slice,
581
582 /// Returns a pointer that becomes invalid after any additions to the `InternPool`.
583 pub fn analysis(func: *const Func, ip: *const InternPool) *FuncAnalysis {
584 return @ptrCast(&ip.extra.items[func.analysis_extra_index]);
585 }
586
587 pub fn zirBodyInst(func: *const Func, ip: *const InternPool) *Zir.Inst.Index {
588 return @ptrCast(&ip.extra.items[func.zir_body_inst_extra_index]);
589 }
590
591 pub fn branchQuota(func: *const Func, ip: *const InternPool) *u32 {
592 return &ip.extra.items[func.zir_body_inst_extra_index];
593 }
548594 };
549595
550596 pub const Int = struct {
......@@ -679,7 +725,7 @@ pub const Key = union(enum) {
679725 };
680726
681727 pub const MemoizedCall = struct {
682 func: Module.Fn.Index,
728 func: Index,
683729 arg_values: []const Index,
684730 result: Index,
685731 };
......@@ -695,7 +741,6 @@ pub const Key = union(enum) {
695741 return switch (key) {
696742 // TODO: assert no padding in these types
697743 inline .ptr_type,
698 .func,
699744 .array_type,
700745 .vector_type,
701746 .opt_type,
......@@ -723,20 +768,11 @@ pub const Key = union(enum) {
723768 },
724769
725770 .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 },
733771
734 .variable => |variable| {
735 var hasher = Hash.init(seed);
736 std.hash.autoHash(&hasher, variable.decl);
737 return hasher.final();
738 },
739 .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)),
772 inline .opaque_type,
773 .enum_type,
774 .variable,
775 => |x| Hash.hash(seed, asBytes(&x.decl)),
740776
741777 .int => |int| {
742778 var hasher = Hash.init(seed);
......@@ -875,7 +911,9 @@ pub const Key = union(enum) {
875911
876912 .func_type => |func_type| {
877913 var hasher = Hash.init(seed);
878 for (func_type.param_types) |param_type| std.hash.autoHash(&hasher, param_type);
914 for (func_type.param_types.get(ip)) |param_type| {
915 std.hash.autoHash(&hasher, param_type);
916 }
879917 std.hash.autoHash(&hasher, func_type.return_type);
880918 std.hash.autoHash(&hasher, func_type.comptime_bits);
881919 std.hash.autoHash(&hasher, func_type.noalias_bits);
......@@ -893,6 +931,19 @@ pub const Key = union(enum) {
893931 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg);
894932 return hasher.final();
895933 },
934
935 .func => |func| {
936 if (func.generic_owner == .none)
937 return Hash.hash(seed, asBytes(&func.owner_decl) ++ asBytes(&func.ty));
938
939 var hasher = Hash.init(seed);
940 std.hash.autoHash(&hasher, func.generic_owner);
941 for (func.comptime_args.get(ip)) |arg| std.hash.autoHash(&hasher, arg);
942 std.hash.autoHash(&hasher, func.ty);
943 return hasher.final();
944 },
945
946 .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)),
896947 };
897948 }
898949
......@@ -993,7 +1044,17 @@ pub const Key = union(enum) {
9931044 },
9941045 .func => |a_info| {
9951046 const b_info = b.func;
996 return a_info.ty == b_info.ty and a_info.index == b_info.index;
1047
1048 if (a_info.generic_owner != b_info.generic_owner)
1049 return false;
1050
1051 if (a_info.ty != b_info.ty)
1052 return false;
1053
1054 if (a_info.generic_owner == .none)
1055 return a_info.owner_decl == b_info.owner_decl;
1056
1057 return std.mem.eql(Index, a_info.comptime_args.get(ip), b_info.comptime_args.get(ip));
9971058 },
9981059
9991060 .ptr => |a_info| {
......@@ -1155,7 +1216,7 @@ pub const Key = union(enum) {
11551216 .func_type => |a_info| {
11561217 const b_info = b.func_type;
11571218
1158 return std.mem.eql(Index, a_info.param_types, b_info.param_types) and
1219 return std.mem.eql(Index, a_info.param_types.get(ip), b_info.param_types.get(ip)) and
11591220 a_info.return_type == b_info.return_type and
11601221 a_info.comptime_bits == b_info.comptime_bits and
11611222 a_info.noalias_bits == b_info.noalias_bits and
......@@ -1360,6 +1421,18 @@ pub const Index = enum(u32) {
13601421
13611422 _,
13621423
1424 /// An array of `Index` existing within the `extra` array.
1425 /// This type exists to provide a struct with lifetime that is
1426 /// not invalidated when items are added to the `InternPool`.
1427 pub const Slice = struct {
1428 start: u32,
1429 len: u32,
1430
1431 pub fn get(slice: Slice, ip: *const InternPool) []Index {
1432 return @ptrCast(ip.extra.items[slice.start..][0..slice.len]);
1433 }
1434 };
1435
13631436 pub fn toType(i: Index) @import("type.zig").Type {
13641437 assert(i != .none);
13651438 return .{ .ip_index = i };
......@@ -1390,6 +1463,7 @@ pub const Index = enum(u32) {
13901463
13911464 /// This function is used in the debugger pretty formatters in tools/ to fetch the
13921465 /// Tag to encoding mapping to facilitate fancy debug printing for this type.
1466 /// TODO merge this with `Tag.Payload`.
13931467 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {
13941468 const DataIsIndex = struct { data: Index };
13951469 const DataIsExtraIndexOfEnumExplicit = struct {
......@@ -1427,11 +1501,11 @@ pub const Index = enum(u32) {
14271501 type_error_union: struct { data: *Key.ErrorUnionType },
14281502 type_error_set: struct {
14291503 const @"data.names_len" = opaque {};
1430 data: *ErrorSet,
1504 data: *Tag.ErrorSet,
14311505 @"trailing.names.len": *@"data.names_len",
14321506 trailing: struct { names: []NullTerminatedString },
14331507 },
1434 type_inferred_error_set: struct { data: Module.Fn.InferredErrorSet.Index },
1508 type_inferred_error_set: struct { data: Module.InferredErrorSet.Index },
14351509 type_enum_auto: struct {
14361510 const @"data.fields_len" = opaque {};
14371511 data: *EnumAuto,
......@@ -1451,7 +1525,7 @@ pub const Index = enum(u32) {
14511525 type_union_safety: struct { data: Module.Union.Index },
14521526 type_function: struct {
14531527 const @"data.params_len" = opaque {};
1454 data: *TypeFunction,
1528 data: *Tag.TypeFunction,
14551529 @"trailing.param_types.len": *@"data.params_len",
14561530 trailing: struct { param_types: []Index },
14571531 },
......@@ -1497,7 +1571,8 @@ pub const Index = enum(u32) {
14971571 float_comptime_float: struct { data: *Float128 },
14981572 variable: struct { data: *Tag.Variable },
14991573 extern_func: struct { data: *Key.ExternFunc },
1500 func: struct { data: *Tag.Func },
1574 func_decl: struct { data: *Tag.FuncDecl },
1575 func_instance: struct { data: *Tag.FuncInstance },
15011576 only_possible_value: DataIsIndex,
15021577 union_value: struct { data: *Key.Union },
15031578 bytes: struct { data: *Bytes },
......@@ -1826,7 +1901,7 @@ pub const Tag = enum(u8) {
18261901 /// data is payload to `ErrorSet`.
18271902 type_error_set,
18281903 /// The inferred error set type of a function.
1829 /// data is `Module.Fn.InferredErrorSet.Index`.
1904 /// data is `Module.InferredErrorSet.Index`.
18301905 type_inferred_error_set,
18311906 /// An enum type with auto-numbered tag values.
18321907 /// The enum is exhaustive.
......@@ -2005,11 +2080,16 @@ pub const Tag = enum(u8) {
20052080 /// data is extra index to Variable.
20062081 variable,
20072082 /// An extern function.
2008 /// data is extra index to Key.ExternFunc.
2083 /// data is extra index to ExternFunc.
20092084 extern_func,
2010 /// A regular function.
2011 /// data is extra index to Func.
2012 func,
2085 /// A non-extern function corresponding directly to the AST node from whence it originated.
2086 /// data is extra index to `FuncDecl`.
2087 /// Only the owner Decl is used for hashing and equality because the other
2088 /// fields can get patched up during incremental compilation.
2089 func_decl,
2090 /// A generic function instantiation.
2091 /// data is extra index to `FuncInstance`.
2092 func_instance,
20132093 /// This represents the only possible value for *some* types which have
20142094 /// only one possible value. Not all only-possible-values are encoded this way;
20152095 /// for example structs which have all comptime fields are not encoded this way.
......@@ -2114,7 +2194,8 @@ pub const Tag = enum(u8) {
21142194 .float_comptime_float => unreachable,
21152195 .variable => Variable,
21162196 .extern_func => ExternFunc,
2117 .func => Func,
2197 .func_decl => FuncDecl,
2198 .func_instance => FuncInstance,
21182199 .only_possible_value => unreachable,
21192200 .union_value => Union,
21202201 .bytes => Bytes,
......@@ -2150,36 +2231,93 @@ pub const Tag = enum(u8) {
21502231 /// The type of the aggregate.
21512232 ty: Index,
21522233 };
2153};
21542234
2155/// Trailing:
2156/// 0. name: NullTerminatedString for each names_len
2157pub const ErrorSet = struct {
2158 names_len: u32,
2159 /// Maps error names to declaration index.
2160 names_map: MapIndex,
2161};
2235 pub const FuncDecl = struct {
2236 analysis: FuncAnalysis,
2237 owner_decl: Module.Decl.Index,
2238 ty: Index,
2239 zir_body_inst: Zir.Inst.Index,
2240 lbrace_line: u32,
2241 rbrace_line: u32,
2242 lbrace_column: u32,
2243 rbrace_column: u32,
2244 };
21622245
2163/// Trailing:
2164/// 0. param_type: Index for each params_len
2165pub const TypeFunction = struct {
2166 params_len: u32,
2167 return_type: Index,
2168 comptime_bits: u32,
2169 noalias_bits: u32,
2170 flags: Flags,
2246 /// Trailing:
2247 /// 0. For each parameter of generic_owner: Index
2248 /// - comptime parameter: the comptime-known value
2249 /// - anytype parameter: the type of the runtime-known value
2250 /// - otherwise: `none`
2251 pub const FuncInstance = struct {
2252 analysis: FuncAnalysis,
2253 // Needed by the linker for codegen. Not part of hashing or equality.
2254 owner_decl: Module.Decl.Index,
2255 ty: Index,
2256 branch_quota: u32,
2257 /// Points to a `FuncDecl`.
2258 generic_owner: Index,
2259 };
21712260
2172 pub const Flags = packed struct(u32) {
2173 alignment: Alignment,
2174 cc: std.builtin.CallingConvention,
2175 is_var_args: bool,
2176 is_generic: bool,
2177 is_noinline: bool,
2178 align_is_generic: bool,
2179 cc_is_generic: bool,
2180 section_is_generic: bool,
2181 addrspace_is_generic: bool,
2182 _: u11 = 0,
2261 /// Trailing:
2262 /// 0. name: NullTerminatedString for each names_len
2263 pub const ErrorSet = struct {
2264 names_len: u32,
2265 /// Maps error names to declaration index.
2266 names_map: MapIndex,
2267 };
2268
2269 /// Trailing:
2270 /// 0. comptime_bits: u32, // if has_comptime_bits
2271 /// 1. noalias_bits: u32, // if has_noalias_bits
2272 /// 2. param_type: Index for each params_len
2273 pub const TypeFunction = struct {
2274 params_len: u32,
2275 return_type: Index,
2276 flags: Flags,
2277
2278 pub const Flags = packed struct(u32) {
2279 alignment: Alignment,
2280 cc: std.builtin.CallingConvention,
2281 is_var_args: bool,
2282 is_generic: bool,
2283 has_comptime_bits: bool,
2284 has_noalias_bits: bool,
2285 is_noinline: bool,
2286 align_is_generic: bool,
2287 cc_is_generic: bool,
2288 section_is_generic: bool,
2289 addrspace_is_generic: bool,
2290 _: u9 = 0,
2291 };
2292 };
2293};
2294
2295/// State that is mutable during semantic analysis. This data is not used for
2296/// equality or hashing.
2297pub const FuncAnalysis = packed struct(u32) {
2298 state: State,
2299 is_cold: bool,
2300 is_noinline: bool,
2301 calls_or_awaits_errorable_fn: bool,
2302 stack_alignment: Alignment,
2303 _: u15 = 0,
2304
2305 pub const State = enum(u8) {
2306 /// This function has not yet undergone analysis, because we have not
2307 /// seen a potential runtime call. It may be analyzed in future.
2308 none,
2309 /// Analysis for this function has been queued, but not yet completed.
2310 queued,
2311 /// This function intentionally only has ZIR generated because it is marked
2312 /// inline, which means no runtime version of the function will be generated.
2313 inline_only,
2314 in_progress,
2315 /// There will be a corresponding ErrorMsg in Module.failed_decls
2316 sema_failure,
2317 /// This function might be OK but it depends on another Decl which did not
2318 /// successfully complete semantic analysis.
2319 dependency_failure,
2320 success,
21832321 };
21842322};
21852323
......@@ -2499,7 +2637,7 @@ pub const Float128 = struct {
24992637/// Trailing:
25002638/// 0. arg value: Index for each args_len
25012639pub const MemoizedCall = struct {
2502 func: Module.Fn.Index,
2640 func: Index,
25032641 args_len: u32,
25042642 result: Index,
25052643};
......@@ -2553,9 +2691,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
25532691 ip.unions_free_list.deinit(gpa);
25542692 ip.allocated_unions.deinit(gpa);
25552693
2556 ip.funcs_free_list.deinit(gpa);
2557 ip.allocated_funcs.deinit(gpa);
2558
25592694 ip.inferred_error_sets_free_list.deinit(gpa);
25602695 ip.allocated_inferred_error_sets.deinit(gpa);
25612696
......@@ -2625,21 +2760,21 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
26252760
26262761 .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) },
26272762 .type_error_set => {
2628 const error_set = ip.extraDataTrail(ErrorSet, data);
2763 const error_set = ip.extraDataTrail(Tag.ErrorSet, data);
26292764 const names_len = error_set.data.names_len;
26302765 const names = ip.extra.items[error_set.end..][0..names_len];
26312766 return .{ .error_set_type = .{
2632 .names = @as([]const NullTerminatedString, @ptrCast(names)),
2767 .names = @ptrCast(names),
26332768 .names_map = error_set.data.names_map.toOptional(),
26342769 } };
26352770 },
26362771 .type_inferred_error_set => .{
2637 .inferred_error_set_type = @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(data)),
2772 .inferred_error_set_type = @enumFromInt(data),
26382773 },
26392774
26402775 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
26412776 .type_struct => {
2642 const struct_index = @as(Module.Struct.OptionalIndex, @enumFromInt(data));
2777 const struct_index: Module.Struct.OptionalIndex = @enumFromInt(data);
26432778 const namespace = if (struct_index.unwrap()) |i|
26442779 ip.structPtrConst(i).namespace.toOptional()
26452780 else
......@@ -2661,9 +2796,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
26612796 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
26622797 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];
26632798 return .{ .anon_struct_type = .{
2664 .types = @as([]const Index, @ptrCast(types)),
2665 .values = @as([]const Index, @ptrCast(values)),
2666 .names = @as([]const NullTerminatedString, @ptrCast(names)),
2799 .types = @ptrCast(types),
2800 .values = @ptrCast(values),
2801 .names = @ptrCast(names),
26672802 } };
26682803 },
26692804 .type_tuple_anon => {
......@@ -2672,8 +2807,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
26722807 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
26732808 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
26742809 return .{ .anon_struct_type = .{
2675 .types = @as([]const Index, @ptrCast(types)),
2676 .values = @as([]const Index, @ptrCast(values)),
2810 .types = @ptrCast(types),
2811 .values = @ptrCast(values),
26772812 .names = &.{},
26782813 } };
26792814 },
......@@ -2957,7 +3092,12 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
29573092 } };
29583093 },
29593094 .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) },
2960 .func => .{ .func = ip.extraData(Tag.Func, data) },
3095 .func_instance => {
3096 @panic("TODO");
3097 },
3098 .func_decl => {
3099 @panic("TODO");
3100 },
29613101 .only_possible_value => {
29623102 const ty = @as(Index, @enumFromInt(data));
29633103 const ty_item = ip.items.get(@intFromEnum(ty));
......@@ -3063,25 +3203,39 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
30633203}
30643204
30653205fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType {
3066 const type_function = ip.extraDataTrail(TypeFunction, data);
3067 const param_types = @as(
3068 []Index,
3069 @ptrCast(ip.extra.items[type_function.end..][0..type_function.data.params_len]),
3070 );
3206 const type_function = ip.extraDataTrail(Tag.TypeFunction, data);
3207 var index: usize = type_function.end;
3208 const comptime_bits: u32 = if (!type_function.data.flags.has_comptime_bits) 0 else b: {
3209 const x = ip.extra.items[index];
3210 index += 1;
3211 break :b x;
3212 };
3213 const noalias_bits: u32 = if (!type_function.data.flags.has_noalias_bits) 0 else b: {
3214 const x = ip.extra.items[index];
3215 index += 1;
3216 break :b x;
3217 };
30713218 return .{
3072 .param_types = param_types,
3219 .param_types = .{
3220 .start = @intCast(index),
3221 .len = type_function.data.params_len,
3222 },
30733223 .return_type = type_function.data.return_type,
3074 .comptime_bits = type_function.data.comptime_bits,
3075 .noalias_bits = type_function.data.noalias_bits,
3224 .comptime_bits = comptime_bits,
3225 .noalias_bits = noalias_bits,
30763226 .alignment = type_function.data.flags.alignment,
30773227 .cc = type_function.data.flags.cc,
30783228 .is_var_args = type_function.data.flags.is_var_args,
3079 .is_generic = type_function.data.flags.is_generic,
30803229 .is_noinline = type_function.data.flags.is_noinline,
30813230 .align_is_generic = type_function.data.flags.align_is_generic,
30823231 .cc_is_generic = type_function.data.flags.cc_is_generic,
30833232 .section_is_generic = type_function.data.flags.section_is_generic,
30843233 .addrspace_is_generic = type_function.data.flags.addrspace_is_generic,
3234 .is_generic = comptime_bits != 0 or
3235 type_function.data.flags.align_is_generic or
3236 type_function.data.flags.cc_is_generic or
3237 type_function.data.flags.section_is_generic or
3238 type_function.data.flags.addrspace_is_generic,
30853239 };
30863240}
30873241
......@@ -3224,10 +3378,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
32243378 const names_map = try ip.addMap(gpa);
32253379 try addStringsToMap(ip, gpa, names_map, error_set_type.names);
32263380 const names_len = @as(u32, @intCast(error_set_type.names.len));
3227 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(ErrorSet).Struct.fields.len + names_len);
3381 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.ErrorSet).Struct.fields.len + names_len);
32283382 ip.items.appendAssumeCapacity(.{
32293383 .tag = .type_error_set,
3230 .data = ip.addExtraAssumeCapacity(ErrorSet{
3384 .data = ip.addExtraAssumeCapacity(Tag.ErrorSet{
32313385 .names_len = names_len,
32323386 .names_map = names_map,
32333387 }),
......@@ -3369,36 +3523,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
33693523 }
33703524 },
33713525
3372 .func_type => |func_type| {
3373 assert(func_type.return_type != .none);
3374 for (func_type.param_types) |param_type| assert(param_type != .none);
3375
3376 const params_len = @as(u32, @intCast(func_type.param_types.len));
3377
3378 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(TypeFunction).Struct.fields.len +
3379 params_len);
3380 ip.items.appendAssumeCapacity(.{
3381 .tag = .type_function,
3382 .data = ip.addExtraAssumeCapacity(TypeFunction{
3383 .params_len = params_len,
3384 .return_type = func_type.return_type,
3385 .comptime_bits = func_type.comptime_bits,
3386 .noalias_bits = func_type.noalias_bits,
3387 .flags = .{
3388 .alignment = func_type.alignment,
3389 .cc = func_type.cc,
3390 .is_var_args = func_type.is_var_args,
3391 .is_generic = func_type.is_generic,
3392 .is_noinline = func_type.is_noinline,
3393 .align_is_generic = func_type.align_is_generic,
3394 .cc_is_generic = func_type.cc_is_generic,
3395 .section_is_generic = func_type.section_is_generic,
3396 .addrspace_is_generic = func_type.addrspace_is_generic,
3397 },
3398 }),
3399 });
3400 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(func_type.param_types)));
3401 },
3526 .func_type => unreachable, // use getFuncType() instead
3527 .extern_func => unreachable, // use getExternFunc() instead
3528 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead
34023529
34033530 .variable => |variable| {
34043531 const has_init = variable.init != .none;
......@@ -3420,16 +3547,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
34203547 });
34213548 },
34223549
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
34333550 .ptr => |ptr| {
34343551 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
34353552 switch (ptr.len) {
......@@ -4068,6 +4185,147 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
40684185 return @as(Index, @enumFromInt(ip.items.len - 1));
40694186}
40704187
4188/// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`.
4189pub const GetFuncTypeKey = struct {
4190 param_types: []Index,
4191 return_type: Index,
4192 comptime_bits: u32,
4193 noalias_bits: u32,
4194 alignment: Alignment,
4195 cc: std.builtin.CallingConvention,
4196 is_var_args: bool,
4197 is_generic: bool,
4198 is_noinline: bool,
4199 align_is_generic: bool,
4200 cc_is_generic: bool,
4201 section_is_generic: bool,
4202 addrspace_is_generic: bool,
4203};
4204
4205pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocator.Error!Index {
4206 // Validate input parameters.
4207 assert(key.return_type != .none);
4208 for (key.param_types) |param_type| assert(param_type != .none);
4209
4210 // The strategy here is to add the function type unconditionally, then to
4211 // ask if it already exists, and if so, revert the lengths of the mutated
4212 // arrays. This is similar to what `getOrPutTrailingString` does.
4213 const prev_extra_len = ip.extra.items.len;
4214 const params_len: u32 = @intCast(key.param_types.len);
4215
4216 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.TypeFunction).Struct.fields.len +
4217 @intFromBool(key.comptime_bits != 0) +
4218 @intFromBool(key.noalias_bits != 0) +
4219 params_len);
4220 try ip.items.ensureUnusedCapacity(gpa, 1);
4221
4222 ip.items.appendAssumeCapacity(.{
4223 .tag = .type_function,
4224 .data = ip.addExtraAssumeCapacity(Tag.TypeFunction{
4225 .params_len = params_len,
4226 .return_type = key.return_type,
4227 .flags = .{
4228 .alignment = key.alignment,
4229 .cc = key.cc,
4230 .is_var_args = key.is_var_args,
4231 .has_comptime_bits = key.comptime_bits != 0,
4232 .has_noalias_bits = key.noalias_bits != 0,
4233 .is_generic = key.is_generic,
4234 .is_noinline = key.is_noinline,
4235 .align_is_generic = key.align_is_generic,
4236 .cc_is_generic = key.cc_is_generic,
4237 .section_is_generic = key.section_is_generic,
4238 .addrspace_is_generic = key.addrspace_is_generic,
4239 },
4240 }),
4241 });
4242 if (key.comptime_bits != 0) ip.extra.appendAssumeCapacity(key.comptime_bits);
4243 if (key.noalias_bits != 0) ip.extra.appendAssumeCapacity(key.noalias_bits);
4244 ip.extra.appendSliceAssumeCapacity(@ptrCast(key.param_types));
4245
4246 const adapter: KeyAdapter = .{ .intern_pool = ip };
4247 const gop = try ip.map.getOrPutAdapted(gpa, Key{
4248 .func_type = indexToKeyFuncType(ip, @intCast(ip.items.len - 1)),
4249 }, adapter);
4250 if (!gop.found_existing) return @enumFromInt(ip.items.len - 1);
4251
4252 // An existing function type was found; undo the additions to our two arrays.
4253 ip.items.len -= 1;
4254 ip.extra.items.len = prev_extra_len;
4255 return @enumFromInt(gop.index);
4256}
4257
4258pub const GetExternFuncKey = struct {
4259 param_types: []const Index,
4260 noalias_bits: u32,
4261 return_type: Index,
4262 cc: std.builtin.CallingConvention,
4263 alignment: Alignment,
4264 is_var_args: bool,
4265 decl: Module.Decl.Index,
4266 lib_name: OptionalNullTerminatedString,
4267};
4268
4269pub fn getExternFunc(ip: *InternPool, gpa: Allocator, key: GetExternFuncKey) Allocator.Error!Index {
4270 _ = ip;
4271 _ = gpa;
4272 _ = key;
4273 @panic("TODO");
4274}
4275
4276pub const GetFuncDeclKey = struct {
4277 param_types: []const Index,
4278 noalias_bits: u32,
4279 comptime_bits: u32,
4280 return_type: Index,
4281 inferred_error_set: bool,
4282 /// null means generic.
4283 cc: ?std.builtin.CallingConvention,
4284 /// null means generic.
4285 alignment: ?Alignment,
4286 section: Section,
4287 /// null means generic
4288 address_space: ?std.builtin.AddressSpace,
4289 is_var_args: bool,
4290 is_generic: bool,
4291 is_noinline: bool,
4292 zir_body_inst: Zir.Inst.Index,
4293 lbrace_line: u32,
4294 rbrace_line: u32,
4295 lbrace_column: u32,
4296 rbrace_column: u32,
4297
4298 pub const Section = union(enum) {
4299 generic,
4300 default,
4301 explicit: InternPool.NullTerminatedString,
4302 };
4303};
4304
4305pub fn getFuncDecl(ip: *InternPool, gpa: Allocator, key: GetFuncDeclKey) Allocator.Error!Index {
4306 _ = ip;
4307 _ = gpa;
4308 _ = key;
4309 @panic("TODO");
4310}
4311
4312pub const GetFuncInstanceKey = struct {
4313 param_types: []const Index,
4314 noalias_bits: u32,
4315 return_type: Index,
4316 cc: std.builtin.CallingConvention,
4317 alignment: Alignment,
4318 is_noinline: bool,
4319 generic_owner: Index,
4320};
4321
4322pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, key: GetFuncInstanceKey) Allocator.Error!Index {
4323 _ = ip;
4324 _ = gpa;
4325 _ = key;
4326 @panic("TODO");
4327}
4328
40714329/// Provides API for completing an enum type after calling `getIncompleteEnum`.
40724330pub const IncompleteEnumType = struct {
40734331 index: Index,
......@@ -4347,7 +4605,6 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
43474605 Module.Decl.Index => @intFromEnum(@field(extra, field.name)),
43484606 Module.Namespace.Index => @intFromEnum(@field(extra, field.name)),
43494607 Module.Namespace.OptionalIndex => @intFromEnum(@field(extra, field.name)),
4350 Module.Fn.Index => @intFromEnum(@field(extra, field.name)),
43514608 MapIndex => @intFromEnum(@field(extra, field.name)),
43524609 OptionalMapIndex => @intFromEnum(@field(extra, field.name)),
43534610 RuntimeIndex => @intFromEnum(@field(extra, field.name)),
......@@ -4356,7 +4613,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
43564613 OptionalNullTerminatedString => @intFromEnum(@field(extra, field.name)),
43574614 i32 => @as(u32, @bitCast(@field(extra, field.name))),
43584615 Tag.TypePointer.Flags => @as(u32, @bitCast(@field(extra, field.name))),
4359 TypeFunction.Flags => @as(u32, @bitCast(@field(extra, field.name))),
4616 Tag.TypeFunction.Flags => @as(u32, @bitCast(@field(extra, field.name))),
43604617 Tag.TypePointer.PackedOffset => @as(u32, @bitCast(@field(extra, field.name))),
43614618 Tag.TypePointer.VectorIndex => @intFromEnum(@field(extra, field.name)),
43624619 Tag.Variable.Flags => @as(u32, @bitCast(@field(extra, field.name))),
......@@ -4411,23 +4668,28 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
44114668 const int32 = ip.extra.items[i + index];
44124669 @field(result, field.name) = switch (field.type) {
44134670 u32 => int32,
4414 Index => @as(Index, @enumFromInt(int32)),
4415 Module.Decl.Index => @as(Module.Decl.Index, @enumFromInt(int32)),
4416 Module.Namespace.Index => @as(Module.Namespace.Index, @enumFromInt(int32)),
4417 Module.Namespace.OptionalIndex => @as(Module.Namespace.OptionalIndex, @enumFromInt(int32)),
4418 Module.Fn.Index => @as(Module.Fn.Index, @enumFromInt(int32)),
4419 MapIndex => @as(MapIndex, @enumFromInt(int32)),
4420 OptionalMapIndex => @as(OptionalMapIndex, @enumFromInt(int32)),
4421 RuntimeIndex => @as(RuntimeIndex, @enumFromInt(int32)),
4422 String => @as(String, @enumFromInt(int32)),
4423 NullTerminatedString => @as(NullTerminatedString, @enumFromInt(int32)),
4424 OptionalNullTerminatedString => @as(OptionalNullTerminatedString, @enumFromInt(int32)),
4425 i32 => @as(i32, @bitCast(int32)),
4426 Tag.TypePointer.Flags => @as(Tag.TypePointer.Flags, @bitCast(int32)),
4427 TypeFunction.Flags => @as(TypeFunction.Flags, @bitCast(int32)),
4428 Tag.TypePointer.PackedOffset => @as(Tag.TypePointer.PackedOffset, @bitCast(int32)),
4429 Tag.TypePointer.VectorIndex => @as(Tag.TypePointer.VectorIndex, @enumFromInt(int32)),
4430 Tag.Variable.Flags => @as(Tag.Variable.Flags, @bitCast(int32)),
4671
4672 Index,
4673 Module.Decl.Index,
4674 Module.Namespace.Index,
4675 Module.Namespace.OptionalIndex,
4676 MapIndex,
4677 OptionalMapIndex,
4678 RuntimeIndex,
4679 String,
4680 NullTerminatedString,
4681 OptionalNullTerminatedString,
4682 Tag.TypePointer.VectorIndex,
4683 => @enumFromInt(int32),
4684
4685 i32,
4686 Tag.TypePointer.Flags,
4687 Tag.TypeFunction.Flags,
4688 Tag.TypePointer.PackedOffset,
4689 Tag.Variable.Flags,
4690 FuncAnalysis,
4691 => @bitCast(int32),
4692
44314693 else => @compileError("bad field type: " ++ @typeName(field.type)),
44324694 };
44334695 }
......@@ -4627,11 +4889,15 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
46274889 .decl = extern_func.decl,
46284890 .lib_name = extern_func.lib_name,
46294891 } }),
4630 .func => |func| if (ip.isFunctionType(new_ty))
4631 return ip.get(gpa, .{ .func = .{
4632 .ty = new_ty,
4633 .index = func.index,
4634 } }),
4892
4893 .func => |func| {
4894 if (func.generic_owner == .none) {
4895 @panic("TODO");
4896 } else {
4897 @panic("TODO");
4898 }
4899 },
4900
46354901 .int => |int| switch (ip.indexToKey(new_ty)) {
46364902 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
46374903 .ty = new_ty,
......@@ -4886,20 +5152,12 @@ pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType {
48865152 }
48875153}
48885154
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 {
5155pub fn indexToInferredErrorSetType(ip: *const InternPool, val: Index) Module.InferredErrorSet.OptionalIndex {
48985156 assert(val != .none);
48995157 const tags = ip.items.items(.tag);
49005158 if (tags[@intFromEnum(val)] != .type_inferred_error_set) return .none;
49015159 const datas = ip.items.items(.data);
4902 return @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(datas[@intFromEnum(val)])).toOptional();
5160 return @as(Module.InferredErrorSet.Index, @enumFromInt(datas[@intFromEnum(val)])).toOptional();
49035161}
49045162
49055163/// includes .comptime_int_type
......@@ -4994,12 +5252,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
49945252 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
49955253 const unions_size = ip.allocated_unions.len *
49965254 (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
4997 const funcs_size = ip.allocated_funcs.len *
4998 (@sizeOf(Module.Fn) + @sizeOf(Module.Decl));
49995255
50005256 // TODO: map overhead size is not taken into account
50015257 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +
5002 structs_size + unions_size + funcs_size;
5258 structs_size + unions_size;
50035259
50045260 std.debug.print(
50055261 \\InternPool size: {d} bytes
......@@ -5008,7 +5264,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
50085264 \\ {d} limbs: {d} bytes
50095265 \\ {d} structs: {d} bytes
50105266 \\ {d} unions: {d} bytes
5011 \\ {d} funcs: {d} bytes
50125267 \\
50135268 , .{
50145269 total_size,
......@@ -5022,8 +5277,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
50225277 structs_size,
50235278 ip.allocated_unions.len,
50245279 unions_size,
5025 ip.allocated_funcs.len,
5026 funcs_size,
50275280 });
50285281
50295282 const tags = ip.items.items(.tag);
......@@ -5049,10 +5302,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
50495302 .type_anyframe => 0,
50505303 .type_error_union => @sizeOf(Key.ErrorUnionType),
50515304 .type_error_set => b: {
5052 const info = ip.extraData(ErrorSet, data);
5053 break :b @sizeOf(ErrorSet) + (@sizeOf(u32) * info.names_len);
5305 const info = ip.extraData(Tag.ErrorSet, data);
5306 break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len);
50545307 },
5055 .type_inferred_error_set => @sizeOf(Module.Fn.InferredErrorSet),
5308 .type_inferred_error_set => @sizeOf(Module.InferredErrorSet),
50565309 .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),
50575310 .type_enum_auto => @sizeOf(EnumAuto),
50585311 .type_opaque => @sizeOf(Key.OpaqueType),
......@@ -5080,8 +5333,8 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
50805333 => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),
50815334
50825335 .type_function => b: {
5083 const info = ip.extraData(TypeFunction, data);
5084 break :b @sizeOf(TypeFunction) + (@sizeOf(Index) * info.params_len);
5336 const info = ip.extraData(Tag.TypeFunction, data);
5337 break :b @sizeOf(Tag.TypeFunction) + (@sizeOf(Index) * info.params_len);
50855338 },
50865339
50875340 .undef => 0,
......@@ -5130,7 +5383,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
51305383 },
51315384 .aggregate => b: {
51325385 const info = ip.extraData(Tag.Aggregate, data);
5133 const fields_len = @as(u32, @intCast(ip.aggregateTypeLenIncludingSentinel(info.ty)));
5386 const fields_len: u32 = @intCast(ip.aggregateTypeLenIncludingSentinel(info.ty));
51345387 break :b @sizeOf(Tag.Aggregate) + (@sizeOf(Index) * fields_len);
51355388 },
51365389 .repeated => @sizeOf(Repeated),
......@@ -5145,7 +5398,14 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
51455398 .float_comptime_float => @sizeOf(Float128),
51465399 .variable => @sizeOf(Tag.Variable) + @sizeOf(Module.Decl),
51475400 .extern_func => @sizeOf(Tag.ExternFunc) + @sizeOf(Module.Decl),
5148 .func => @sizeOf(Tag.Func) + @sizeOf(Module.Fn) + @sizeOf(Module.Decl),
5401 .func_decl => @sizeOf(Tag.Func) + @sizeOf(Module.Decl),
5402 .func_instance => b: {
5403 const info = ip.extraData(Tag.FuncInstance, data);
5404 const ty = ip.typeOf(info.generic_owner);
5405 const params_len = ip.indexToKey(ty).func_type.param_types.len;
5406 break :b @sizeOf(Tag.FuncInstance) + @sizeOf(Index) * params_len +
5407 @sizeOf(Module.Decl);
5408 },
51495409 .only_possible_value => 0,
51505410 .union_value => @sizeOf(Key.Union),
51515411
......@@ -5249,7 +5509,8 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
52495509 .float_comptime_float,
52505510 .variable,
52515511 .extern_func,
5252 .func,
5512 .func_decl,
5513 .func_instance,
52535514 .union_value,
52545515 .memoized_call,
52555516 => try w.print("{d}", .{data}),
......@@ -5284,19 +5545,11 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo
52845545 return ip.allocated_unions.at(@intFromEnum(index));
52855546}
52865547
5287pub fn funcPtr(ip: *InternPool, index: Module.Fn.Index) *Module.Fn {
5288 return ip.allocated_funcs.at(@intFromEnum(index));
5289}
5290
5291pub fn funcPtrConst(ip: *const InternPool, index: Module.Fn.Index) *const Module.Fn {
5292 return ip.allocated_funcs.at(@intFromEnum(index));
5293}
5294
5295pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet {
5548pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.InferredErrorSet.Index) *Module.InferredErrorSet {
52965549 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));
52975550}
52985551
5299pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.Fn.InferredErrorSet.Index) *const Module.Fn.InferredErrorSet {
5552pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.InferredErrorSet.Index) *const Module.InferredErrorSet {
53005553 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));
53015554}
53025555
......@@ -5344,43 +5597,21 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)
53445597 };
53455598}
53465599
5347pub fn createFunc(
5348 ip: *InternPool,
5349 gpa: Allocator,
5350 initialization: Module.Fn,
5351) Allocator.Error!Module.Fn.Index {
5352 if (ip.funcs_free_list.popOrNull()) |index| {
5353 ip.allocated_funcs.at(@intFromEnum(index)).* = initialization;
5354 return index;
5355 }
5356 const ptr = try ip.allocated_funcs.addOne(gpa);
5357 ptr.* = initialization;
5358 return @as(Module.Fn.Index, @enumFromInt(ip.allocated_funcs.len - 1));
5359}
5360
5361pub fn destroyFunc(ip: *InternPool, gpa: Allocator, index: Module.Fn.Index) void {
5362 ip.funcPtr(index).* = undefined;
5363 ip.funcs_free_list.append(gpa, index) catch {
5364 // In order to keep `destroyFunc` a non-fallible function, we ignore memory
5365 // allocation failures here, instead leaking the Fn until garbage collection.
5366 };
5367}
5368
53695600pub fn createInferredErrorSet(
53705601 ip: *InternPool,
53715602 gpa: Allocator,
5372 initialization: Module.Fn.InferredErrorSet,
5373) Allocator.Error!Module.Fn.InferredErrorSet.Index {
5603 initialization: Module.InferredErrorSet,
5604) Allocator.Error!Module.InferredErrorSet.Index {
53745605 if (ip.inferred_error_sets_free_list.popOrNull()) |index| {
53755606 ip.allocated_inferred_error_sets.at(@intFromEnum(index)).* = initialization;
53765607 return index;
53775608 }
53785609 const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);
53795610 ptr.* = initialization;
5380 return @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(ip.allocated_inferred_error_sets.len - 1));
5611 return @as(Module.InferredErrorSet.Index, @enumFromInt(ip.allocated_inferred_error_sets.len - 1));
53815612}
53825613
5383pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.Fn.InferredErrorSet.Index) void {
5614pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.InferredErrorSet.Index) void {
53845615 ip.inferredErrorSetPtr(index).* = undefined;
53855616 ip.inferred_error_sets_free_list.append(gpa, index) catch {
53865617 // In order to keep `destroyInferredErrorSet` a non-fallible function, we ignore memory
......@@ -5620,7 +5851,8 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
56205851 .enum_tag,
56215852 .variable,
56225853 .extern_func,
5623 .func,
5854 .func_decl,
5855 .func_instance,
56245856 .union_value,
56255857 .bytes,
56265858 .aggregate,
......@@ -5704,7 +5936,7 @@ pub fn funcReturnType(ip: *const InternPool, ty: Index) Index {
57045936 };
57055937 assert(child_item.tag == .type_function);
57065938 return @as(Index, @enumFromInt(ip.extra.items[
5707 child_item.data + std.meta.fieldIndex(TypeFunction, "return_type").?
5939 child_item.data + std.meta.fieldIndex(Tag.TypeFunction, "return_type").?
57085940 ]));
57095941}
57105942
......@@ -5712,7 +5944,7 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
57125944 return switch (ty) {
57135945 .noreturn_type => true,
57145946 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,
5947 .type_error_set => ip.extra.items[ip.items.items(.data)[@intFromEnum(ty)] + std.meta.fieldIndex(Tag.ErrorSet, "names_len").?] == 0,
57165948 else => false,
57175949 },
57185950 };
......@@ -5969,7 +6201,8 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
59696201 .float_comptime_float,
59706202 .variable,
59716203 .extern_func,
5972 .func,
6204 .func_decl,
6205 .func_instance,
59736206 .only_possible_value,
59746207 .union_value,
59756208 .bytes,
......@@ -5982,3 +6215,39 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
59826215 .none => unreachable, // special tag
59836216 };
59846217}
6218
6219pub fn isFuncBody(ip: *const InternPool, i: Index) bool {
6220 assert(i != .none);
6221 return switch (ip.items.items(.tag)[@intFromEnum(i)]) {
6222 .func_decl, .func_instance => true,
6223 else => false,
6224 };
6225}
6226
6227pub fn funcAnalysis(ip: *const InternPool, i: Index) *FuncAnalysis {
6228 assert(i != .none);
6229 const item = ip.items.get(@intFromEnum(i));
6230 const extra_index = switch (item.tag) {
6231 .func_decl => item.data + std.meta.fieldIndex(Tag.FuncDecl, "analysis").?,
6232 .func_instance => item.data + std.meta.fieldIndex(Tag.FuncInstance, "analysis").?,
6233 else => unreachable,
6234 };
6235 return @ptrCast(&ip.extra.items[extra_index]);
6236}
6237
6238pub fn funcZirBodyInst(ip: *const InternPool, i: Index) Zir.Inst.Index {
6239 assert(i != .none);
6240 const item = ip.items.get(@intFromEnum(i));
6241 const zir_body_inst_field_index = std.meta.fieldIndex(Tag.FuncDecl, "zir_body_inst").?;
6242 const extra_index = switch (item.tag) {
6243 .func_decl => item.data + zir_body_inst_field_index,
6244 .func_instance => b: {
6245 const generic_owner_field_index = std.meta.fieldIndex(Tag.FuncInstance, "generic_owner").?;
6246 const func_decl_index = ip.extra.items[item.data + generic_owner_field_index];
6247 assert(ip.items.items(.tag)[func_decl_index] == .func_decl);
6248 break :b ip.items.items(.data)[func_decl_index] + zir_body_inst_field_index;
6249 },
6250 else => unreachable,
6251 };
6252 return ip.extra.items[extra_index];
6253}
src/Module.zig+272-414
......@@ -101,16 +101,6 @@ tmp_hack_arena: std.heap.ArenaAllocator,
101101/// This is currently only used for string literals.
102102memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},
103103
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
114104/// We optimize memory usage for a compilation with no compile errors by storing the
115105/// error messages and mapping outside of `Decl`.
116106/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
......@@ -189,7 +179,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
189179}) = .{},
190180
191181panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len,
192panic_func_index: Fn.OptionalIndex = .none,
182/// The panic function body.
183panic_func_index: InternPool.Index = .none,
193184null_stack_trace: InternPool.Index = .none,
194185
195186pub const PanicId = enum {
......@@ -239,50 +230,6 @@ pub const CImportError = struct {
239230 }
240231};
241232
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
286233/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
287234pub const GlobalEmitH = struct {
288235 /// Where to put the output.
......@@ -625,13 +572,6 @@ pub const Decl = struct {
625572 function_body,
626573 };
627574
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
635575 /// This name is relative to the containing namespace of the decl.
636576 /// The memory is owned by the containing File ZIR.
637577 pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {
......@@ -816,14 +756,17 @@ pub const Decl = struct {
816756 return mod.typeToUnion(decl.val.toType());
817757 }
818758
819 /// If the Decl owns its value and it is a function, return it,
820 /// otherwise null.
821 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?*Fn {
822 return mod.funcPtrUnwrap(decl.getOwnedFunctionIndex(mod));
759 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?InternPool.Key.Func {
760 const i = decl.getOwnedFunctionIndex();
761 if (i == .none) return null;
762 return switch (mod.intern_pool.indexToKey(i)) {
763 .func => |func| func,
764 else => null,
765 };
823766 }
824767
825 pub fn getOwnedFunctionIndex(decl: Decl, mod: *Module) Fn.OptionalIndex {
826 return if (decl.owns_tv) decl.val.getFunctionIndex(mod) else .none;
768 pub fn getOwnedFunctionIndex(decl: Decl) InternPool.Index {
769 return if (decl.owns_tv) decl.val.toIntern() else .none;
827770 }
828771
829772 /// If the Decl owns its value and it is an extern function, returns it,
......@@ -1385,71 +1328,39 @@ pub const ExternFn = struct {
13851328 }
13861329};
13871330
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,
1331/// This struct is used to keep track of any dependencies related to functions instances
1332/// that return inferred error sets. Note that a function may be associated to
1333/// multiple different error sets, for example an inferred error set which
1334/// this function returns, but also any inferred error sets of called inline
1335/// or comptime functions.
1336pub const InferredErrorSet = struct {
1337 /// The function from which this error set originates.
1338 func: InternPool.Index,
1339
1340 /// All currently known errors that this error set contains. This includes
1341 /// direct additions via `return error.Foo;`, and possibly also errors that
1342 /// are returned from any dependent functions. When the inferred error set is
1343 /// fully resolved, this map contains all the errors that the function might return.
1344 errors: NameMap = .{},
1345
1346 /// Other inferred error sets which this inferred error set should include.
1347 inferred_error_sets: std.AutoArrayHashMapUnmanaged(InferredErrorSet.Index, void) = .{},
1348
1349 /// Whether the function returned anyerror. This is true if either of
1350 /// the dependent functions returns anyerror.
1351 is_anyerror: bool = false,
1352
1353 /// Whether this error set is already fully resolved. If true, resolving
1354 /// can skip resolving any dependents of this inferred error set.
1355 is_resolved: bool = false,
1356
1357 pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
14471358
14481359 pub const Index = enum(u32) {
14491360 _,
14501361
1451 pub fn toOptional(i: Index) OptionalIndex {
1452 return @as(OptionalIndex, @enumFromInt(@intFromEnum(i)));
1362 pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1363 return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(i)));
14531364 }
14541365 };
14551366
......@@ -1457,159 +1368,37 @@ pub const Fn = struct {
14571368 none = std.math.maxInt(u32),
14581369 _,
14591370
1460 pub fn init(oi: ?Index) OptionalIndex {
1461 return @as(OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none)));
1371 pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1372 return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none)));
14621373 }
14631374
1464 pub fn unwrap(oi: OptionalIndex) ?Index {
1375 pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index {
14651376 if (oi == .none) return null;
1466 return @as(Index, @enumFromInt(@intFromEnum(oi)));
1377 return @as(InferredErrorSet.Index, @enumFromInt(@intFromEnum(oi)));
14671378 }
14681379 };
14691380
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;
1381 pub fn addErrorSet(
1382 self: *InferredErrorSet,
1383 err_set_ty: Type,
1384 ip: *InternPool,
1385 gpa: Allocator,
1386 ) !void {
1387 switch (err_set_ty.toIntern()) {
1388 .anyerror_type => {
1389 self.is_anyerror = true;
1390 },
1391 else => switch (ip.indexToKey(err_set_ty.toIntern())) {
1392 .error_set_type => |error_set_type| {
1393 for (error_set_type.names) |name| {
1394 try self.errors.put(gpa, name, {});
1395 }
15471396 },
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,
1397 .inferred_error_set_type => |ies_index| {
1398 try self.inferred_error_sets.put(gpa, ies_index, {});
15581399 },
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;
1400 else => unreachable,
16111401 },
1612 else => unreachable,
16131402 }
16141403 }
16151404};
......@@ -2468,6 +2257,22 @@ pub const SrcLoc = struct {
24682257 }
24692258 } else unreachable;
24702259 },
2260 .call_arg => |call_arg| {
2261 const tree = try src_loc.file_scope.getTree(gpa);
2262 const node = src_loc.declRelativeToNodeIndex(call_arg.call_node_offset);
2263 var buf: [1]Ast.Node.Index = undefined;
2264 const call_full = tree.fullCall(&buf, node).?;
2265 const src_node = call_full.ast.params[call_arg.arg_index];
2266 return nodeToSpan(tree, src_node);
2267 },
2268 .fn_proto_param => |fn_proto_param| {
2269 const tree = try src_loc.file_scope.getTree(gpa);
2270 const node = src_loc.declRelativeToNodeIndex(fn_proto_param.fn_proto_node_offset);
2271 var buf: [1]Ast.Node.Index = undefined;
2272 const fn_proto_full = tree.fullFnProto(&buf, node).?;
2273 const src_node = fn_proto_full.ast.params[fn_proto_param.param_index];
2274 return nodeToSpan(tree, src_node);
2275 },
24712276 .node_offset_bin_lhs => |node_off| {
24722277 const tree = try src_loc.file_scope.getTree(gpa);
24732278 const node = src_loc.declRelativeToNodeIndex(node_off);
......@@ -3146,6 +2951,20 @@ pub const LazySrcLoc = union(enum) {
31462951 /// Next, navigate to the corresponding capture.
31472952 /// The Decl is determined contextually.
31482953 for_capture_from_input: i32,
2954 /// The source location points to the argument node of a function call.
2955 /// The Decl is determined contextually.
2956 call_arg: struct {
2957 /// Points to the function call AST node.
2958 call_node_offset: i32,
2959 /// The index of the argument the source location points to.
2960 arg_index: u32,
2961 },
2962 fn_proto_param: struct {
2963 /// Points to the function prototype AST node.
2964 fn_proto_node_offset: i32,
2965 /// The index of the parameter the source location points to.
2966 param_index: u32,
2967 },
31492968
31502969 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
31512970
......@@ -3235,6 +3054,8 @@ pub const LazySrcLoc = union(enum) {
32353054 .node_offset_store_operand,
32363055 .for_input,
32373056 .for_capture_from_input,
3057 .call_arg,
3058 .fn_proto_param,
32383059 => .{
32393060 .file_scope = decl.getFileScope(mod),
32403061 .parent_decl_node = decl.src_node,
......@@ -3373,8 +3194,6 @@ pub fn deinit(mod: *Module) void {
33733194 mod.global_error_set.deinit(gpa);
33743195
33753196 mod.test_functions.deinit(gpa);
3376 mod.align_stack_fns.deinit(gpa);
3377 mod.monomorphed_funcs.deinit(gpa);
33783197
33793198 mod.decls_free_list.deinit(gpa);
33803199 mod.allocated_decls.deinit(gpa);
......@@ -3407,7 +3226,6 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
34073226 }
34083227 }
34093228 if (decl.src_scope) |scope| scope.decRef(gpa);
3410 decl.clearValues(mod);
34113229 decl.dependants.deinit(gpa);
34123230 decl.dependencies.deinit(gpa);
34133231 decl.* = undefined;
......@@ -3439,11 +3257,7 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
34393257 return mod.intern_pool.structPtr(index);
34403258}
34413259
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 {
3260pub fn inferredErrorSetPtr(mod: *Module, index: InferredErrorSet.Index) *InferredErrorSet {
34473261 return mod.intern_pool.inferredErrorSetPtr(index);
34483262}
34493263
......@@ -3457,10 +3271,6 @@ pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {
34573271 return mod.structPtr(index.unwrap() orelse return null);
34583272}
34593273
3460pub fn funcPtrUnwrap(mod: *Module, index: Fn.OptionalIndex) ?*Fn {
3461 return mod.funcPtr(index.unwrap() orelse return null);
3462}
3463
34643274/// Returns true if and only if the Decl is the top level struct associated with a File.
34653275pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
34663276 const decl = mod.declPtr(decl_index);
......@@ -3881,6 +3691,8 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
38813691 // to re-generate ZIR for the File.
38823692 try file.outdated_decls.append(gpa, root_decl);
38833693
3694 const ip = &mod.intern_pool;
3695
38843696 while (decl_stack.popOrNull()) |decl_index| {
38853697 const decl = mod.declPtr(decl_index);
38863698 // Anonymous decls and the root decl have this set to 0. We still need
......@@ -3918,7 +3730,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
39183730 }
39193731
39203732 if (decl.getOwnedFunction(mod)) |func| {
3921 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
3733 func.zirBodyInst(ip).* = inst_map.get(func.zir_body_inst) orelse {
39223734 try file.deleted_decls.append(gpa, decl_index);
39233735 continue;
39243736 };
......@@ -4101,11 +3913,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
41013913 // prior to re-analysis.
41023914 try mod.deleteDeclExports(decl_index);
41033915
4104 // Similarly, `@setAlignStack` invocations will be re-discovered.
4105 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
4106 _ = mod.align_stack_fns.remove(func);
4107 }
4108
41093916 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
41103917 for (decl.dependencies.keys()) |dep_index| {
41113918 const dep = mod.declPtr(dep_index);
......@@ -4189,11 +3996,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
41893996 }
41903997}
41913998
4192pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void {
3999pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaError!void {
41934000 const tracy = trace(@src());
41944001 defer tracy.end();
41954002
4196 const func = mod.funcPtr(func_index);
4003 const ip = &mod.intern_pool;
4004 const func = mod.funcInfo(func_index);
41974005 const decl_index = func.owner_decl;
41984006 const decl = mod.declPtr(decl_index);
41994007
......@@ -4211,7 +4019,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42114019 => return error.AnalysisFail,
42124020
42134021 .complete, .codegen_failure_retryable => {
4214 switch (func.state) {
4022 switch (func.analysis(ip).state) {
42154023 .sema_failure, .dependency_failure => return error.AnalysisFail,
42164024 .none, .queued => {},
42174025 .in_progress => unreachable,
......@@ -4227,11 +4035,11 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42274035
42284036 var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
42294037 error.AnalysisFail => {
4230 if (func.state == .in_progress) {
4038 if (func.analysis(ip).state == .in_progress) {
42314039 // If this decl caused the compile error, the analysis field would
42324040 // be changed to indicate it was this Decl's fault. Because this
42334041 // did not happen, we infer here that it was a dependency failure.
4234 func.state = .dependency_failure;
4042 func.analysis(ip).state = .dependency_failure;
42354043 }
42364044 return error.AnalysisFail;
42374045 },
......@@ -4251,14 +4059,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42514059
42524060 if (no_bin_file and !dump_air and !dump_llvm_ir) return;
42534061
4254 var liveness = try Liveness.analyze(gpa, air, &mod.intern_pool);
4062 var liveness = try Liveness.analyze(gpa, air, ip);
42554063 defer liveness.deinit(gpa);
42564064
42574065 if (dump_air) {
42584066 const fqn = try decl.getFullyQualifiedName(mod);
4259 std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(&mod.intern_pool)});
4067 std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});
42604068 @import("print_air.zig").dump(mod, air, liveness);
4261 std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(&mod.intern_pool)});
4069 std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)});
42624070 }
42634071
42644072 if (std.debug.runtime_safety) {
......@@ -4266,7 +4074,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42664074 .gpa = gpa,
42674075 .air = air,
42684076 .liveness = liveness,
4269 .intern_pool = &mod.intern_pool,
4077 .intern_pool = ip,
42704078 };
42714079 defer verify.deinit();
42724080
......@@ -4321,8 +4129,9 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
43214129/// analyzed, and for ensuring it can exist at runtime (see
43224130/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
43234131/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
4324pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
4325 const func = mod.funcPtr(func_index);
4132pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) !void {
4133 const ip = &mod.intern_pool;
4134 const func = mod.funcInfo(func_index);
43264135 const decl_index = func.owner_decl;
43274136 const decl = mod.declPtr(decl_index);
43284137
......@@ -4348,7 +4157,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
43484157
43494158 assert(decl.has_tv);
43504159
4351 switch (func.state) {
4160 switch (func.analysis(ip).state) {
43524161 .none => {},
43534162 .queued => return,
43544163 // As above, we don't need to forward errors here.
......@@ -4366,7 +4175,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
43664175 // since the last update
43674176 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
43684177 }
4369 func.state = .queued;
4178 func.analysis(ip).state = .queued;
43704179}
43714180
43724181pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {
......@@ -4490,10 +4299,8 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
44904299 .code = file.zir,
44914300 .owner_decl = new_decl,
44924301 .owner_decl_index = new_decl_index,
4493 .func = null,
44944302 .func_index = .none,
44954303 .fn_ret_ty = Type.void,
4496 .owner_func = null,
44974304 .owner_func_index = .none,
44984305 .comptime_mutable_decls = &comptime_mutable_decls,
44994306 };
......@@ -4573,10 +4380,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
45734380 .code = zir,
45744381 .owner_decl = decl,
45754382 .owner_decl_index = decl_index,
4576 .func = null,
45774383 .func_index = .none,
45784384 .fn_ret_ty = Type.void,
4579 .owner_func = null,
45804385 .owner_func_index = .none,
45814386 .comptime_mutable_decls = &comptime_mutable_decls,
45824387 };
......@@ -4658,48 +4463,49 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
46584463 return true;
46594464 }
46604465
4661 if (mod.intern_pool.indexToFunc(decl_tv.val.toIntern()).unwrap()) |func_index| {
4662 const func = mod.funcPtr(func_index);
4663 const owns_tv = func.owner_decl == decl_index;
4664 if (owns_tv) {
4665 var prev_type_has_bits = false;
4666 var prev_is_inline = false;
4667 var type_changed = true;
4668
4669 if (decl.has_tv) {
4670 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
4671 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4672 if (decl.getOwnedFunction(mod)) |prev_func| {
4673 prev_is_inline = prev_func.state == .inline_only;
4466 const ip = &mod.intern_pool;
4467 switch (ip.indexToKey(decl_tv.val.toIntern())) {
4468 .func => |func| {
4469 const owns_tv = func.owner_decl == decl_index;
4470 if (owns_tv) {
4471 var prev_type_has_bits = false;
4472 var prev_is_inline = false;
4473 var type_changed = true;
4474
4475 if (decl.has_tv) {
4476 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
4477 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4478 if (decl.getOwnedFunction(mod)) |prev_func| {
4479 prev_is_inline = prev_func.analysis(ip).state == .inline_only;
4480 }
46744481 }
4675 }
4676 decl.clearValues(mod);
4677
4678 decl.ty = decl_tv.ty;
4679 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
4680 // linksection, align, and addrspace were already set by Sema
4681 decl.has_tv = true;
4682 decl.owns_tv = owns_tv;
4683 decl.analysis = .complete;
4684 decl.generation = mod.generation;
4685
4686 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
4687 if (decl.is_exported) {
4688 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
4689 if (is_inline) {
4690 return sema.fail(&block_scope, export_src, "export of inline function", .{});
4482
4483 decl.ty = decl_tv.ty;
4484 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
4485 // linksection, align, and addrspace were already set by Sema
4486 decl.has_tv = true;
4487 decl.owns_tv = owns_tv;
4488 decl.analysis = .complete;
4489 decl.generation = mod.generation;
4490
4491 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
4492 if (decl.is_exported) {
4493 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
4494 if (is_inline) {
4495 return sema.fail(&block_scope, export_src, "export of inline function", .{});
4496 }
4497 // The scope needs to have the decl in it.
4498 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
46914499 }
4692 // The scope needs to have the decl in it.
4693 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
4500 return type_changed or is_inline != prev_is_inline;
46944501 }
4695 return type_changed or is_inline != prev_is_inline;
4696 }
4502 },
4503 else => {},
46974504 }
46984505 var type_changed = true;
46994506 if (decl.has_tv) {
47004507 type_changed = !decl.ty.eql(decl_tv.ty, mod);
47014508 }
4702 decl.clearValues(mod);
47034509
47044510 decl.owns_tv = false;
47054511 var queue_linker_work = false;
......@@ -4707,7 +4513,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47074513 switch (decl_tv.val.toIntern()) {
47084514 .generic_poison => unreachable,
47094515 .unreachable_value => unreachable,
4710 else => switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
4516 else => switch (ip.indexToKey(decl_tv.val.toIntern())) {
47114517 .variable => |variable| if (variable.decl == decl_index) {
47124518 decl.owns_tv = true;
47134519 queue_linker_work = true;
......@@ -4743,11 +4549,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47434549 } else if (bytes.len == 0) {
47444550 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
47454551 }
4746 const section = try mod.intern_pool.getOrPutString(gpa, bytes);
4552 const section = try ip.getOrPutString(gpa, bytes);
47474553 break :blk section.toOptional();
47484554 };
47494555 decl.@"addrspace" = blk: {
4750 const addrspace_ctx: Sema.AddressSpaceContext = switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
4556 const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) {
47514557 .variable => .variable,
47524558 .extern_func, .func => .function,
47534559 else => .constant,
......@@ -5309,7 +5115,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
53095115 decl.has_align = has_align;
53105116 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
53115117 decl.zir_decl_index = @as(u32, @intCast(decl_sub_index));
5312 if (decl.getOwnedFunctionIndex(mod) != .none) {
5118 if (decl.getOwnedFunctionIndex() != .none) {
53135119 switch (comp.bin_file.tag) {
53145120 .coff, .elf, .macho, .plan9 => {
53155121 // TODO Look into detecting when this would be unnecessary by storing enough state
......@@ -5386,7 +5192,6 @@ pub fn clearDecl(
53865192 try namespace.deleteAllDecls(mod, outdated_decls);
53875193 }
53885194 }
5389 decl.clearValues(mod);
53905195
53915196 if (decl.deletion_flag) {
53925197 decl.deletion_flag = false;
......@@ -5497,19 +5302,26 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
54975302 export_owners.deinit(mod.gpa);
54985303}
54995304
5500pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaError!Air {
5305pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocator) SemaError!Air {
55015306 const tracy = trace(@src());
55025307 defer tracy.end();
55035308
55045309 const gpa = mod.gpa;
5505 const func = mod.funcPtr(func_index);
5310 const ip = &mod.intern_pool;
5311 const func = mod.funcInfo(func_index);
55065312 const decl_index = func.owner_decl;
55075313 const decl = mod.declPtr(decl_index);
55085314
55095315 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
55105316 defer comptime_mutable_decls.deinit();
55115317
5318 // In the case of a generic function instance, this is the type of the
5319 // instance, which has comptime parameters elided. In other words, it is
5320 // the runtime-known parameters only, not to be confused with the
5321 // generic_owner function type, which potentially has more parameters,
5322 // including comptime parameters.
55125323 const fn_ty = decl.ty;
5324 const fn_ty_info = mod.typeToFunc(fn_ty).?;
55135325
55145326 var sema: Sema = .{
55155327 .mod = mod,
......@@ -5518,18 +5330,16 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
55185330 .code = decl.getFileScope(mod).zir,
55195331 .owner_decl = decl,
55205332 .owner_decl_index = decl_index,
5521 .func = func,
5522 .func_index = func_index.toOptional(),
5523 .fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(),
5524 .owner_func = func,
5525 .owner_func_index = func_index.toOptional(),
5526 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
5333 .func_index = func_index,
5334 .fn_ret_ty = fn_ty_info.return_type.toType(),
5335 .owner_func_index = func_index,
5336 .branch_quota = @max(func.branchQuota(ip).*, Sema.default_branch_quota),
55275337 .comptime_mutable_decls = &comptime_mutable_decls,
55285338 };
55295339 defer sema.deinit();
55305340
55315341 // reset in case calls to errorable functions are removed.
5532 func.calls_or_awaits_errorable_fn = false;
5342 func.analysis(ip).calls_or_awaits_errorable_fn = false;
55335343
55345344 // First few indexes of extra are reserved and set at the end.
55355345 const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len;
......@@ -5551,8 +5361,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
55515361 };
55525362 defer inner_block.instructions.deinit(gpa);
55535363
5554 const fn_info = sema.code.getFnInfo(func.zir_body_inst);
5555 const zir_tags = sema.code.instructions.items(.tag);
5364 const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*);
55565365
55575366 // Here we are performing "runtime semantic analysis" for a function body, which means
55585367 // we must map the parameter ZIR instructions to `arg` AIR instructions.
......@@ -5560,35 +5369,36 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
55605369 // This could be a generic function instantiation, however, in which case we need to
55615370 // map the comptime parameters to constant values and only emit arg AIR instructions
55625371 // for the runtime ones.
5563 const runtime_params_len = @as(u32, @intCast(mod.typeToFunc(fn_ty).?.param_types.len));
5372 const runtime_params_len = fn_ty_info.param_types.len;
55645373 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`
5374 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len);
55665375 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
55675376
5568 var runtime_param_index: usize = 0;
5569 var total_param_index: usize = 0;
5570 for (fn_info.param_body) |inst| {
5571 switch (zir_tags[inst]) {
5572 .param, .param_comptime, .param_anytype, .param_anytype_comptime => {},
5573 else => continue,
5377 // In the case of a generic function instance, pre-populate all the comptime args.
5378 if (func.comptime_args.len != 0) {
5379 for (
5380 fn_info.param_body[0..func.comptime_args.len],
5381 func.comptime_args.get(ip),
5382 ) |inst, comptime_arg| {
5383 if (comptime_arg == .none) continue;
5384 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.internedToRef(comptime_arg));
55745385 }
5575 const param_ty = if (func.comptime_args) |comptime_args| t: {
5576 const arg_tv = comptime_args[total_param_index];
5577
5578 const arg_val = if (!arg_tv.val.isGenericPoison())
5579 arg_tv.val
5580 else if (try arg_tv.ty.onePossibleValue(mod)) |opv|
5581 opv
5582 else
5583 break :t arg_tv.ty;
5584
5585 const arg = try sema.addConstant(arg_val);
5586 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5587 total_param_index += 1;
5588 continue;
5589 } else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType();
5386 }
5387
5388 const src_params_len = if (func.comptime_args.len != 0)
5389 func.comptime_args.len
5390 else
5391 runtime_params_len;
5392
5393 var runtime_param_index: usize = 0;
5394 for (fn_info.param_body[0..src_params_len], 0..) |inst, src_param_index| {
5395 const gop = sema.inst_map.getOrPutAssumeCapacity(inst);
5396 if (gop.found_existing) continue; // provided above by comptime arg
55905397
5591 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
5398 const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index];
5399 runtime_param_index += 1;
5400
5401 const opt_opv = sema.typeHasOnePossibleValue(param_ty.toType()) catch |err| switch (err) {
55925402 error.NeededSourceLocation => unreachable,
55935403 error.GenericPoison => unreachable,
55945404 error.ComptimeReturn => unreachable,
......@@ -5596,28 +5406,22 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
55965406 else => |e| return e,
55975407 };
55985408 if (opt_opv) |opv| {
5599 const arg = try sema.addConstant(opv);
5600 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5601 total_param_index += 1;
5602 runtime_param_index += 1;
5409 gop.value_ptr.* = Air.internedToRef(opv.toIntern());
56035410 continue;
56045411 }
5605 const air_ty = try sema.addType(param_ty);
5606 const arg_index = @as(u32, @intCast(sema.air_instructions.len));
5412 const arg_index: u32 = @intCast(sema.air_instructions.len);
5413 gop.value_ptr.* = Air.indexToRef(arg_index);
56075414 inner_block.instructions.appendAssumeCapacity(arg_index);
56085415 sema.air_instructions.appendAssumeCapacity(.{
56095416 .tag = .arg,
56105417 .data = .{ .arg = .{
5611 .ty = air_ty,
5612 .src_index = @as(u32, @intCast(total_param_index)),
5418 .ty = Air.internedToRef(param_ty),
5419 .src_index = @intCast(src_param_index),
56135420 } },
56145421 });
5615 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
5616 total_param_index += 1;
5617 runtime_param_index += 1;
56185422 }
56195423
5620 func.state = .in_progress;
5424 func.analysis(ip).state = .in_progress;
56215425
56225426 const last_arg_index = inner_block.instructions.items.len;
56235427
......@@ -5648,7 +5452,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
56485452 }
56495453
56505454 // If we don't get an error return trace from a caller, create our own.
5651 if (func.calls_or_awaits_errorable_fn and
5455 if (func.analysis(ip).calls_or_awaits_errorable_fn and
56525456 mod.comp.bin_file.options.error_return_tracing and
56535457 !sema.fn_ret_ty.isError(mod))
56545458 {
......@@ -5677,7 +5481,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
56775481 sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
56785482 sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;
56795483
5680 func.state = .success;
5484 func.analysis(ip).state = .success;
56815485
56825486 // Finally we must resolve the return type and parameter types so that backends
56835487 // have full access to type information.
......@@ -5716,7 +5520,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
57165520 };
57175521 }
57185522
5719 return Air{
5523 return .{
57205524 .instructions = sema.air_instructions.toOwnedSlice(),
57215525 .extra = try sema.air_extra.toOwnedSlice(gpa),
57225526 };
......@@ -5731,9 +5535,6 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
57315535 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
57325536 for (kv.value) |err| err.deinit(mod.gpa);
57335537 }
5734 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
5735 _ = mod.align_stack_fns.remove(func);
5736 }
57375538 if (mod.emit_h) |emit_h| {
57385539 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
57395540 kv.value.destroy(mod.gpa);
......@@ -5777,14 +5578,6 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {
57775578 return mod.intern_pool.destroyUnion(mod.gpa, index);
57785579}
57795580
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
57885581pub fn allocateNewDecl(
57895582 mod: *Module,
57905583 namespace: Namespace.Index,
......@@ -6578,7 +6371,6 @@ pub fn populateTestFunctions(
65786371
65796372 // Since we are replacing the Decl's value we must perform cleanup on the
65806373 // previous value.
6581 decl.clearValues(mod);
65826374 decl.ty = new_ty;
65836375 decl.val = new_val;
65846376 decl.has_tv = true;
......@@ -6657,7 +6449,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
66576449 switch (mod.intern_pool.indexToKey(val.toIntern())) {
66586450 .variable => |variable| try mod.markDeclIndexAlive(variable.decl),
66596451 .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),
6660 .func => |func| try mod.markDeclIndexAlive(mod.funcPtr(func.index).owner_decl),
6452 .func => |func| try mod.markDeclIndexAlive(func.owner_decl),
66616453 .error_union => |error_union| switch (error_union.val) {
66626454 .err_name => {},
66636455 .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),
......@@ -6851,8 +6643,8 @@ pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator
68516643 return mod.ptrType(info);
68526644}
68536645
6854pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Type {
6855 return (try intern(mod, .{ .func_type = info })).toType();
6646pub fn funcType(mod: *Module, key: InternPool.GetFuncTypeKey) Allocator.Error!Type {
6647 return (try mod.intern_pool.getFuncType(mod.gpa, key)).toType();
68566648}
68576649
68586650/// Use this for `anyframe->T` only.
......@@ -7231,16 +7023,28 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {
72317023 return mod.intern_pool.indexToFuncType(ty.toIntern());
72327024}
72337025
7234pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*Fn.InferredErrorSet {
7026pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*InferredErrorSet {
72357027 const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;
72367028 return mod.inferredErrorSetPtr(index);
72377029}
72387030
7239pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) Fn.InferredErrorSet.OptionalIndex {
7031pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) InferredErrorSet.OptionalIndex {
72407032 if (ty.ip_index == .none) return .none;
72417033 return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern());
72427034}
72437035
7036pub fn funcOwnerDeclPtr(mod: *Module, func_index: InternPool.Index) *Decl {
7037 return mod.declPtr(mod.funcOwnerDeclIndex(func_index));
7038}
7039
7040pub fn funcOwnerDeclIndex(mod: *Module, func_index: InternPool.Index) Decl.Index {
7041 return mod.funcInfo(func_index).owner_decl;
7042}
7043
7044pub fn funcInfo(mod: *Module, func_index: InternPool.Index) InternPool.Key.Func {
7045 return mod.intern_pool.indexToKey(func_index).func;
7046}
7047
72447048pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {
72457049 @setCold(true);
72467050 const owner_decl = mod.declPtr(owner_decl_index);
......@@ -7265,3 +7069,57 @@ pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQu
72657069pub fn toEnum(mod: *Module, comptime E: type, val: Value) E {
72667070 return mod.intern_pool.toEnum(E, val.toIntern());
72677071}
7072
7073pub fn isAnytypeParam(mod: *Module, func: InternPool.Index, index: u32) bool {
7074 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
7075
7076 const tags = file.zir.instructions.items(.tag);
7077
7078 const param_body = file.zir.getParamBody(func.zir_body_inst);
7079 const param = param_body[index];
7080
7081 return switch (tags[param]) {
7082 .param, .param_comptime => false,
7083 .param_anytype, .param_anytype_comptime => true,
7084 else => unreachable,
7085 };
7086}
7087
7088pub fn getParamName(mod: *Module, func_index: InternPool.Index, index: u32) [:0]const u8 {
7089 const func = mod.funcInfo(func_index);
7090 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
7091
7092 const tags = file.zir.instructions.items(.tag);
7093 const data = file.zir.instructions.items(.data);
7094
7095 const param_body = file.zir.getParamBody(func.zir_body_inst);
7096 const param = param_body[index];
7097
7098 return switch (tags[param]) {
7099 .param, .param_comptime => blk: {
7100 const extra = file.zir.extraData(Zir.Inst.Param, data[param].pl_tok.payload_index);
7101 break :blk file.zir.nullTerminatedString(extra.data.name);
7102 },
7103 .param_anytype, .param_anytype_comptime => blk: {
7104 const param_data = data[param].str_tok;
7105 break :blk param_data.get(file.zir);
7106 },
7107 else => unreachable,
7108 };
7109}
7110
7111pub fn hasInferredErrorSet(mod: *Module, func: InternPool.Key.Func) bool {
7112 const owner_decl = mod.declPtr(func.owner_decl);
7113 const zir = owner_decl.getFileScope(mod).zir;
7114 const zir_tags = zir.instructions.items(.tag);
7115 switch (zir_tags[func.zir_body_inst]) {
7116 .func => return false,
7117 .func_inferred => return true,
7118 .func_fancy => {
7119 const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node;
7120 const extra = zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
7121 return extra.data.bits.is_inferred_error;
7122 },
7123 else => unreachable,
7124 }
7125}
src/Sema.zig+621-1046
......@@ -23,13 +23,13 @@ owner_decl: *Decl,
2323owner_decl_index: Decl.Index,
2424/// For an inline or comptime function call, this will be the root parent function
2525/// which contains the callsite. Corresponds to `owner_decl`.
26owner_func: ?*Module.Fn,
27owner_func_index: Module.Fn.OptionalIndex,
26/// This could be `none`, a `func_decl`, or a `func_instance`.
27owner_func_index: InternPool.Index,
2828/// The function this ZIR code is the body of, according to the source code.
29/// This starts out the same as `owner_func` and then diverges in the case of
29/// This starts out the same as `owner_func_index` and then diverges in the case of
3030/// an inline or comptime function call.
31func: ?*Module.Fn,
32func_index: Module.Fn.OptionalIndex,
31/// This could be `none`, a `func_decl`, or a `func_instance`.
32func_index: InternPool.Index,
3333/// Used to restore the error return trace when returning a non-error from a function.
3434error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
3535/// When semantic analysis needs to know the return type of the function whose body
......@@ -49,21 +49,16 @@ comptime_break_inst: Zir.Inst.Index = undefined,
4949/// contain a mapped source location.
5050src: LazySrcLoc = .{ .token_offset = 0 },
5151decl_val_table: std.AutoHashMapUnmanaged(Decl.Index, Air.Inst.Ref) = .{},
52/// When doing a generic function instantiation, this array collects a
53/// `Value` object for each parameter that is comptime-known and thus elided
54/// from the generated function. This memory is allocated by a parent `Sema` and
55/// owned by the values arena of the Sema owner_decl.
56comptime_args: []TypedValue = &.{},
57/// Marks the function instruction that `comptime_args` applies to so that we
58/// don't accidentally apply it to a function prototype which is used in the
59/// type expression of a generic function parameter.
60comptime_args_fn_inst: Zir.Inst.Index = 0,
61/// When `comptime_args` is provided, this field is also provided. It was used as
62/// the key in the `monomorphed_funcs` set. The `func` instruction is supposed
63/// to use this instead of allocating a fresh one. This avoids an unnecessary
64/// extra hash table lookup in the `monomorphed_funcs` set.
65/// Sema will set this to null when it takes ownership.
66preallocated_new_func: Module.Fn.OptionalIndex = .none,
52/// When doing a generic function instantiation, this array collects a value
53/// for each parameter of the generic owner. `none` for non-comptime parameters.
54/// This is a separate array from `block.params` so that it can be passed
55/// directly to `comptime_args` when calling `InternPool.getFuncInstance`.
56/// This memory is allocated by a parent `Sema` in the temporary arena, and is
57/// used only to add a `func_instance` into the `InternPool`.
58comptime_args: []InternPool.Index = &.{},
59/// Used to communicate from a generic function instantiation to the logic that
60/// creates a generic function instantiation value in `funcCommon`.
61generic_owner: InternPool.Index = .none,
6762/// The key is types that must be fully resolved prior to machine code
6863/// generation pass. Types are added to this set when resolving them
6964/// immediately could cause a dependency loop, but they do need to be resolved
......@@ -79,8 +74,6 @@ types_to_resolve: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{},
7974post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
8075/// Populated with the last compile error created.
8176err: ?*Module.ErrorMsg = null,
82/// True when analyzing a generic instantiation. Used to suppress some errors.
83is_generic_instantiation: bool = false,
8477/// Set to true when analyzing a func type instruction so that nested generic
8578/// function types will emit generic poison instead of a partial type.
8679no_partial_func_ty: bool = false,
......@@ -97,6 +90,10 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAll
9790/// involve transitioning comptime-mutable memory away from using Decls at all.
9891comptime_mutable_decls: *std.ArrayList(Decl.Index),
9992
93/// This is populated when `@setAlignStack` occurs so that if there is a duplicate
94/// one encountered, the conflicting source location can be shown.
95prev_stack_alignment_src: ?LazySrcLoc = null,
96
10097const std = @import("std");
10198const math = std.math;
10299const mem = std.mem;
......@@ -243,7 +240,13 @@ pub const Block = struct {
243240 /// The AIR instructions generated for this block.
244241 instructions: std.ArrayListUnmanaged(Air.Inst.Index),
245242 // `param` instructions are collected here to be used by the `func` instruction.
246 params: std.ArrayListUnmanaged(Param) = .{},
243 /// When doing a generic function instantiation, this array collects a type
244 /// for each *runtime-known* parameter. This array corresponds to the instance
245 /// function type, while `Sema.comptime_args` corresponds to the generic owner
246 /// function type.
247 /// This memory is allocated by a parent `Sema` in the temporary arena, and is
248 /// used to add a `func_instance` into the `InternPool`.
249 params: std.MultiArrayList(Param) = .{},
247250
248251 wip_capture_scope: *CaptureScope,
249252
......@@ -323,10 +326,10 @@ pub const Block = struct {
323326 };
324327
325328 const Param = struct {
326 /// `noreturn` means `anytype`.
327 ty: Type,
329 /// `none` means `anytype`.
330 ty: InternPool.Index,
328331 is_comptime: bool,
329 name: []const u8,
332 name: Zir.NullTerminatedString,
330333 };
331334
332335 /// This `Block` maps a block ZIR instruction to the corresponding
......@@ -342,7 +345,8 @@ pub const Block = struct {
342345 /// It is shared among all the blocks in an inline or comptime called
343346 /// function.
344347 pub const Inlining = struct {
345 func: ?*Module.Fn,
348 /// Might be `none`.
349 func: InternPool.Index,
346350 comptime_result: Air.Inst.Ref,
347351 merges: Merges,
348352 };
......@@ -906,7 +910,7 @@ fn analyzeBodyInner(
906910 // We use a while (true) loop here to avoid a redundant way of breaking out of
907911 // the loop. The only way to break out of the loop is with a `noreturn`
908912 // instruction.
909 var i: usize = 0;
913 var i: u32 = 0;
910914 const result = while (true) {
911915 crash_info.setBodyIndex(i);
912916 const inst = body[i];
......@@ -1338,22 +1342,22 @@ fn analyzeBodyInner(
13381342 continue;
13391343 },
13401344 .param => {
1341 try sema.zirParam(block, inst, false);
1345 try sema.zirParam(block, inst, i, false);
13421346 i += 1;
13431347 continue;
13441348 },
13451349 .param_comptime => {
1346 try sema.zirParam(block, inst, true);
1350 try sema.zirParam(block, inst, i, true);
13471351 i += 1;
13481352 continue;
13491353 },
13501354 .param_anytype => {
1351 try sema.zirParamAnytype(block, inst, false);
1355 try sema.zirParamAnytype(block, inst, i, false);
13521356 i += 1;
13531357 continue;
13541358 },
13551359 .param_anytype_comptime => {
1356 try sema.zirParamAnytype(block, inst, true);
1360 try sema.zirParamAnytype(block, inst, i, true);
13571361 i += 1;
13581362 continue;
13591363 },
......@@ -1493,10 +1497,7 @@ fn analyzeBodyInner(
14931497 // Note: this probably needs to be resolved in a more general manner.
14941498 const prev_params = block.params;
14951499 block.params = .{};
1496 defer {
1497 block.params.deinit(sema.gpa);
1498 block.params = prev_params;
1499 }
1500 defer block.params = prev_params;
15001501 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
15011502 break always_noreturn;
15021503 if (inst == break_data.block_inst) {
......@@ -1532,7 +1533,6 @@ fn analyzeBodyInner(
15321533 .merges = undefined,
15331534 };
15341535 child_block.label = &label;
1535 defer child_block.params.deinit(gpa);
15361536
15371537 // Write these instructions directly into the parent block
15381538 child_block.instructions = block.instructions;
......@@ -2363,7 +2363,10 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
23632363 break :blk default_reference_trace_len;
23642364 };
23652365
2366 var referenced_by = if (sema.func) |some| some.owner_decl else sema.owner_decl_index;
2366 var referenced_by = if (sema.func_index != .none)
2367 mod.funcOwnerDeclIndex(sema.func_index)
2368 else
2369 sema.owner_decl_index;
23672370 var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa);
23682371 defer reference_stack.deinit();
23692372
......@@ -2399,14 +2402,15 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
23992402 }
24002403 err_msg.reference_trace = try reference_stack.toOwnedSlice();
24012404 }
2402 if (sema.owner_func) |func| {
2403 func.state = .sema_failure;
2405 const ip = &mod.intern_pool;
2406 if (sema.owner_func_index != .none) {
2407 ip.funcAnalysis(sema.owner_func_index).state = .sema_failure;
24042408 } else {
24052409 sema.owner_decl.analysis = .sema_failure;
24062410 sema.owner_decl.generation = mod.generation;
24072411 }
2408 if (sema.func) |func| {
2409 func.state = .sema_failure;
2412 if (sema.func_index != .none) {
2413 ip.funcAnalysis(sema.func_index).state = .sema_failure;
24102414 }
24112415 const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index);
24122416 if (gop.found_existing) {
......@@ -2866,6 +2870,7 @@ fn createAnonymousDeclTypeNamed(
28662870 inst: ?Zir.Inst.Index,
28672871) !Decl.Index {
28682872 const mod = sema.mod;
2873 const ip = &mod.intern_pool;
28692874 const gpa = sema.gpa;
28702875 const namespace = block.namespace;
28712876 const src_scope = block.wip_capture_scope;
......@@ -2895,7 +2900,7 @@ fn createAnonymousDeclTypeNamed(
28952900 return new_decl_index;
28962901 },
28972902 .func => {
2898 const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst);
2903 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index));
28992904 const zir_tags = sema.code.instructions.items(.tag);
29002905
29012906 var buf = std.ArrayList(u8).init(gpa);
......@@ -3070,18 +3075,12 @@ fn zirEnumDecl(
30703075 sema.owner_decl_index = prev_owner_decl_index;
30713076 }
30723077
3073 const prev_owner_func = sema.owner_func;
30743078 const prev_owner_func_index = sema.owner_func_index;
3075 sema.owner_func = null;
30763079 sema.owner_func_index = .none;
3077 defer sema.owner_func = prev_owner_func;
30783080 defer sema.owner_func_index = prev_owner_func_index;
30793081
3080 const prev_func = sema.func;
30813082 const prev_func_index = sema.func_index;
3082 sema.func = null;
30833083 sema.func_index = .none;
3084 defer sema.func = prev_func;
30853084 defer sema.func_index = prev_func_index;
30863085
30873086 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);
......@@ -3393,7 +3392,7 @@ fn zirErrorSetDecl(
33933392 const src = inst_data.src();
33943393 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
33953394
3396 var names: Module.Fn.InferredErrorSet.NameMap = .{};
3395 var names: Module.InferredErrorSet.NameMap = .{};
33973396 try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len);
33983397
33993398 var extra_index = @as(u32, @intCast(extra.end));
......@@ -5379,7 +5378,10 @@ fn zirCompileLog(
53795378 }
53805379 try writer.print("\n", .{});
53815380
5382 const decl_index = if (sema.func) |some| some.owner_decl else sema.owner_decl_index;
5381 const decl_index = if (sema.func_index != .none)
5382 mod.funcOwnerDeclIndex(sema.func_index)
5383 else
5384 sema.owner_decl_index;
53835385 const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index);
53845386 if (!gop.found_existing) {
53855387 gop.value_ptr.* = src_node;
......@@ -5967,11 +5969,11 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
59675969 alignment.toByteUnitsOptional().?,
59685970 });
59695971 }
5970 const func_index = sema.func_index.unwrap() orelse
5972 if (sema.func_index == .none) {
59715973 return sema.fail(block, src, "@setAlignStack outside function body", .{});
5972 const func = mod.funcPtr(func_index);
5974 }
59735975
5974 const fn_owner_decl = mod.declPtr(func.owner_decl);
5976 const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index);
59755977 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
59765978 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
59775979 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),
......@@ -5980,25 +5982,34 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
59805982 },
59815983 }
59825984
5983 const gop = try mod.align_stack_fns.getOrPut(sema.gpa, func_index);
5984 if (gop.found_existing) {
5985 if (sema.prev_stack_alignment_src) |prev_src| {
59855986 const msg = msg: {
59865987 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});
59875988 errdefer msg.destroy(sema.gpa);
5988 try sema.errNote(block, gop.value_ptr.src, msg, "other instance here", .{});
5989 try sema.errNote(block, prev_src, msg, "other instance here", .{});
59895990 break :msg msg;
59905991 };
59915992 return sema.failWithOwnedErrorMsg(msg);
59925993 }
5993 gop.value_ptr.* = .{ .alignment = alignment, .src = src };
5994
5995 const ip = &mod.intern_pool;
5996 const a = ip.funcAnalysis(sema.func_index);
5997 if (a.stack_alignment != .none) {
5998 a.stack_alignment = @enumFromInt(@max(
5999 @intFromEnum(alignment),
6000 @intFromEnum(a.stack_alignment),
6001 ));
6002 }
59946003}
59956004
59966005fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
6006 const mod = sema.mod;
6007 const ip = &mod.intern_pool;
59976008 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
59986009 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
59996010 const is_cold = try sema.resolveConstBool(block, operand_src, extra.operand, "operand to @setCold must be comptime-known");
6000 const func = sema.func orelse return; // does nothing outside a function
6001 func.is_cold = is_cold;
6011 if (sema.func_index == .none) return; // does nothing outside a function
6012 ip.funcAnalysis(sema.func_index).is_cold = is_cold;
60026013}
60036014
60046015fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
......@@ -6308,7 +6319,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
63086319 if (func_val.isUndef(mod)) return null;
63096320 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
63106321 .extern_func => |extern_func| extern_func.decl,
6311 .func => |func| mod.funcPtr(func.index).owner_decl,
6322 .func => |func| func.owner_decl,
63126323 .ptr => |ptr| switch (ptr.addr) {
63136324 .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl,
63146325 else => return null,
......@@ -6445,6 +6456,7 @@ fn zirCall(
64456456 defer tracy.end();
64466457
64476458 const mod = sema.mod;
6459 const ip = &mod.intern_pool;
64486460 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
64496461 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
64506462 const call_src = inst_data.src();
......@@ -6493,9 +6505,10 @@ fn zirCall(
64936505 const args_body = sema.code.extra[extra.end..];
64946506
64956507 var input_is_error = false;
6496 const block_index = @as(Air.Inst.Index, @intCast(block.instructions.items.len));
6508 const block_index: Air.Inst.Index = @intCast(block.instructions.items.len);
64976509
6498 const fn_params_len = mod.typeToFunc(func_ty).?.param_types.len;
6510 const func_ty_info = mod.typeToFunc(func_ty).?;
6511 const fn_params_len = func_ty_info.param_types.len;
64996512 const parent_comptime = block.is_comptime;
65006513 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
65016514 var extra_index: usize = 0;
......@@ -6504,13 +6517,12 @@ fn zirCall(
65046517 extra_index += 1;
65056518 arg_index += 1;
65066519 }) {
6507 const func_ty_info = mod.typeToFunc(func_ty).?;
65086520 const arg_end = sema.code.extra[extra.end + extra_index];
65096521 defer arg_start = arg_end;
65106522
65116523 // Generate args to comptime params in comptime block.
65126524 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)))) {
6525 if (arg_index < @min(fn_params_len, 32) and func_ty_info.paramIsComptime(@intCast(arg_index))) {
65146526 block.is_comptime = true;
65156527 // TODO set comptime_reason
65166528 }
......@@ -6519,10 +6531,10 @@ fn zirCall(
65196531 if (arg_index >= fn_params_len)
65206532 break :inst Air.Inst.Ref.var_args_param_type;
65216533
6522 if (func_ty_info.param_types[arg_index] == .generic_poison_type)
6534 if (func_ty_info.param_types.get(ip)[arg_index] == .generic_poison_type)
65236535 break :inst Air.Inst.Ref.generic_poison_type;
65246536
6525 break :inst try sema.addType(func_ty_info.param_types[arg_index].toType());
6537 break :inst try sema.addType(func_ty_info.param_types.get(ip)[arg_index].toType());
65266538 });
65276539
65286540 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
......@@ -6535,7 +6547,9 @@ fn zirCall(
65356547 }
65366548 resolved_args[arg_index] = resolved;
65376549 }
6538 if (sema.owner_func == null or !sema.owner_func.?.calls_or_awaits_errorable_fn) {
6550 if (sema.owner_func_index == .none or
6551 !ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn)
6552 {
65396553 input_is_error = false; // input was an error type, but no errorable fn's were actually called
65406554 }
65416555
......@@ -6702,6 +6716,7 @@ fn analyzeCall(
67026716 call_dbg_node: ?Zir.Inst.Index,
67036717) CompileError!Air.Inst.Ref {
67046718 const mod = sema.mod;
6719 const ip = &mod.intern_pool;
67056720
67066721 const callee_ty = sema.typeOf(func);
67076722 const func_ty_info = mod.typeToFunc(func_ty).?;
......@@ -6749,20 +6764,17 @@ fn analyzeCall(
67496764
67506765 var is_generic_call = func_ty_info.is_generic;
67516766 var is_comptime_call = block.is_comptime or modifier == .compile_time;
6752 var comptime_reason_buf: Block.ComptimeReason = undefined;
67536767 var comptime_reason: ?*const Block.ComptimeReason = null;
67546768 if (!is_comptime_call) {
67556769 if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| {
67566770 is_comptime_call = ct;
67576771 if (ct) {
6758 // stage1 can't handle doing this directly
6759 comptime_reason_buf = .{ .comptime_ret_ty = .{
6772 comptime_reason = &.{ .comptime_ret_ty = .{
67606773 .block = block,
67616774 .func = func,
67626775 .func_src = func_src,
67636776 .return_ty = func_ty_info.return_type.toType(),
67646777 } };
6765 comptime_reason = &comptime_reason_buf;
67666778 }
67676779 } else |err| switch (err) {
67686780 error.GenericPoison => is_generic_call = true,
......@@ -6778,7 +6790,6 @@ fn analyzeCall(
67786790 func,
67796791 func_src,
67806792 call_src,
6781 func_ty,
67826793 ensure_result_used,
67836794 uncasted_args,
67846795 call_tag,
......@@ -6793,14 +6804,12 @@ fn analyzeCall(
67936804 error.ComptimeReturn => {
67946805 is_inline_call = true;
67956806 is_comptime_call = true;
6796 // stage1 can't handle doing this directly
6797 comptime_reason_buf = .{ .comptime_ret_ty = .{
6807 comptime_reason = &.{ .comptime_ret_ty = .{
67986808 .block = block,
67996809 .func = func,
68006810 .func_src = func_src,
68016811 .return_ty = func_ty_info.return_type.toType(),
68026812 } };
6803 comptime_reason = &comptime_reason_buf;
68046813 },
68056814 else => |e| return e,
68066815 }
......@@ -6819,9 +6828,9 @@ fn analyzeCall(
68196828 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
68206829 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
68216830 }),
6822 .func => |function| function.index,
6831 .func => func_val.toIntern(),
68236832 .ptr => |ptr| switch (ptr.addr) {
6824 .decl => |decl| mod.declPtr(decl).val.getFunctionIndex(mod).unwrap().?,
6833 .decl => |decl| mod.declPtr(decl).val.toIntern(),
68256834 else => {
68266835 assert(callee_ty.isPtrAtRuntime(mod));
68276836 return sema.fail(block, call_src, "{s} call of function pointer", .{
......@@ -6850,7 +6859,7 @@ fn analyzeCall(
68506859 // This one is shared among sub-blocks within the same callee, but not
68516860 // shared among the entire inline/comptime call stack.
68526861 var inlining: Block.Inlining = .{
6853 .func = null,
6862 .func = .none,
68546863 .comptime_result = undefined,
68556864 .merges = .{
68566865 .src_locs = .{},
......@@ -6862,7 +6871,7 @@ fn analyzeCall(
68626871 // In order to save a bit of stack space, directly modify Sema rather
68636872 // than create a child one.
68646873 const parent_zir = sema.code;
6865 const module_fn = mod.funcPtr(module_fn_index);
6874 const module_fn = mod.funcInfo(module_fn_index);
68666875 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
68676876 sema.code = fn_owner_decl.getFileScope(mod).zir;
68686877 defer sema.code = parent_zir;
......@@ -6877,11 +6886,8 @@ fn analyzeCall(
68776886 sema.inst_map = parent_inst_map;
68786887 }
68796888
6880 const parent_func = sema.func;
68816889 const parent_func_index = sema.func_index;
6882 sema.func = module_fn;
6883 sema.func_index = module_fn_index.toOptional();
6884 defer sema.func = parent_func;
6890 sema.func_index = module_fn_index;
68856891 defer sema.func_index = parent_func_index;
68866892
68876893 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
......@@ -6913,16 +6919,30 @@ fn analyzeCall(
69136919
69146920 try sema.emitBackwardBranch(block, call_src);
69156921
6916 // Whether this call should be memoized, set to false if the call can mutate comptime state.
6922 // Whether this call should be memoized, set to false if the call can
6923 // mutate comptime state.
69176924 var should_memoize = true;
69186925
69196926 // If it's a comptime function call, we need to memoize it as long as no external
69206927 // comptime memory is mutated.
69216928 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
69226929
6923 var new_fn_info = mod.typeToFunc(fn_owner_decl.ty).?;
6924 new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len);
6925 new_fn_info.comptime_bits = 0;
6930 const owner_info = mod.typeToFunc(fn_owner_decl.ty).?;
6931 var new_fn_info: InternPool.GetFuncTypeKey = .{
6932 .param_types = try sema.arena.alloc(InternPool.Index, owner_info.param_types.len),
6933 .return_type = owner_info.return_type,
6934 .comptime_bits = 0,
6935 .noalias_bits = owner_info.noalias_bits,
6936 .alignment = owner_info.alignment,
6937 .cc = owner_info.cc,
6938 .is_var_args = owner_info.is_var_args,
6939 .is_noinline = owner_info.is_noinline,
6940 .align_is_generic = owner_info.align_is_generic,
6941 .cc_is_generic = owner_info.cc_is_generic,
6942 .section_is_generic = owner_info.section_is_generic,
6943 .addrspace_is_generic = owner_info.addrspace_is_generic,
6944 .is_generic = owner_info.is_generic,
6945 };
69266946
69276947 // This will have return instructions analyzed as break instructions to
69286948 // the block_inst above. Here we are performing "comptime/inline semantic analysis"
......@@ -6934,59 +6954,42 @@ fn analyzeCall(
69346954 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body);
69356955
69366956 var has_comptime_args = false;
6937 var arg_i: usize = 0;
6957 var arg_i: u32 = 0;
69386958 for (fn_info.param_body) |inst| {
6939 sema.analyzeInlineCallArg(
6959 const arg_src: LazySrcLoc = .{ .call_arg = .{
6960 .call_node_offset = call_src.node_offset.x,
6961 .arg_index = arg_i,
6962 } };
6963 try sema.analyzeInlineCallArg(
69406964 block,
69416965 &child_block,
6942 .unneeded,
6966 arg_src,
69436967 inst,
6944 &new_fn_info,
6968 new_fn_info.param_types,
69456969 &arg_i,
69466970 uncasted_args,
69476971 is_comptime_call,
69486972 &should_memoize,
69496973 memoized_arg_values,
6950 mod.typeToFunc(func_ty).?.param_types,
6974 func_ty_info.param_types,
69516975 func,
69526976 &has_comptime_args,
6953 ) catch |err| switch (err) {
6954 error.NeededSourceLocation => {
6955 _ = sema.inst_map.remove(inst);
6956 const decl = mod.declPtr(block.src_decl);
6957 try sema.analyzeInlineCallArg(
6958 block,
6959 &child_block,
6960 mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src),
6961 inst,
6962 &new_fn_info,
6963 &arg_i,
6964 uncasted_args,
6965 is_comptime_call,
6966 &should_memoize,
6967 memoized_arg_values,
6968 mod.typeToFunc(func_ty).?.param_types,
6969 func,
6970 &has_comptime_args,
6971 );
6972 unreachable;
6973 },
6974 else => |e| return e,
6975 };
6977 );
69766978 }
69776979
6978 if (!has_comptime_args and module_fn.state == .sema_failure) return error.AnalysisFail;
6980 if (!has_comptime_args and module_fn.analysis(ip).state == .sema_failure)
6981 return error.AnalysisFail;
69796982
69806983 const recursive_msg = "inline call is recursive";
69816984 var head = if (!has_comptime_args) block else null;
69826985 while (head) |some| {
69836986 const parent_inlining = some.inlining orelse break;
6984 if (parent_inlining.func == module_fn) {
6987 if (parent_inlining.func == module_fn_index) {
69856988 return sema.fail(block, call_src, recursive_msg, .{});
69866989 }
69876990 head = some.parent;
69886991 }
6989 if (!has_comptime_args) inlining.func = module_fn;
6992 if (!has_comptime_args) inlining.func = module_fn_index;
69906993
69916994 // In case it is a generic function with an expression for the return type that depends
69926995 // on parameters, we must now do the same for the return type as we just did with
......@@ -7000,7 +7003,7 @@ fn analyzeCall(
70007003 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
70017004 // Create a fresh inferred error set type for inline/comptime calls.
70027005 const fn_ret_ty = blk: {
7003 if (module_fn.hasInferredErrorSet(mod)) {
7006 if (mod.hasInferredErrorSet(module_fn)) {
70047007 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
70057008 .func = module_fn_index,
70067009 });
......@@ -7032,7 +7035,7 @@ fn analyzeCall(
70327035
70337036 const new_func_resolved_ty = try mod.funcType(new_fn_info);
70347037 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);
7038 try sema.emitDbgInline(block, parent_func_index, module_fn_index, new_func_resolved_ty, .dbg_inline_begin);
70367039
70377040 const zir_tags = sema.code.instructions.items(.tag);
70387041 for (fn_info.param_body) |param| switch (zir_tags[param]) {
......@@ -7078,21 +7081,22 @@ fn analyzeCall(
70787081 try sema.emitDbgInline(
70797082 block,
70807083 module_fn_index,
7081 parent_func_index.unwrap().?,
7082 mod.declPtr(parent_func.?.owner_decl).ty,
7084 parent_func_index,
7085 mod.funcOwnerDeclPtr(parent_func_index).ty,
70837086 .dbg_inline_end,
70847087 );
70857088 }
70867089
70877090 if (should_memoize and is_comptime_call) {
70887091 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");
7092 const result_interned = try result_val.intern(fn_ret_ty, mod);
70897093
70907094 // TODO: check whether any external comptime memory was mutated by the
70917095 // comptime function call. If so, then do not memoize the call here.
70927096 _ = try mod.intern(.{ .memoized_call = .{
70937097 .func = module_fn_index,
70947098 .arg_values = memoized_arg_values,
7095 .result = try result_val.intern(fn_ret_ty, mod),
7099 .result = result_interned,
70967100 } });
70977101 }
70987102
......@@ -7112,7 +7116,7 @@ fn analyzeCall(
71127116 .func_inst = func,
71137117 .param_i = @as(u32, @intCast(i)),
71147118 } };
7115 const param_ty = mod.typeToFunc(func_ty).?.param_types[i].toType();
7119 const param_ty = func_ty_info.param_types.get(ip)[i].toType();
71167120 args[i] = sema.analyzeCallArg(
71177121 block,
71187122 .unneeded,
......@@ -7152,13 +7156,13 @@ fn analyzeCall(
71527156 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
71537157
71547158 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7155 if (sema.owner_func != null and func_ty_info.return_type.toType().isError(mod)) {
7156 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
7159 if (sema.owner_func_index != .none and func_ty_info.return_type.toType().isError(mod)) {
7160 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
71577161 }
71587162
71597163 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7160 if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| {
7161 try mod.ensureFuncBodyAnalysisQueued(func_index);
7164 if (mod.intern_pool.isFuncBody(func_val.toIntern())) {
7165 try mod.ensureFuncBodyAnalysisQueued(func_val.toIntern());
71627166 }
71637167 }
71647168
......@@ -7219,7 +7223,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
72197223 @tagName(backend), @tagName(target.cpu.arch),
72207224 });
72217225 }
7222 const func_decl = mod.declPtr(sema.owner_func.?.owner_decl);
7226 const func_decl = mod.funcOwnerDeclPtr(sema.owner_func_index);
72237227 if (!func_ty.eql(func_decl.ty, mod)) {
72247228 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{
72257229 func_ty.fmt(mod), func_decl.ty.fmt(mod),
......@@ -7235,17 +7239,18 @@ fn analyzeInlineCallArg(
72357239 param_block: *Block,
72367240 arg_src: LazySrcLoc,
72377241 inst: Zir.Inst.Index,
7238 new_fn_info: *InternPool.Key.FuncType,
7239 arg_i: *usize,
7242 new_param_types: []InternPool.Index,
7243 arg_i: *u32,
72407244 uncasted_args: []const Air.Inst.Ref,
72417245 is_comptime_call: bool,
72427246 should_memoize: *bool,
72437247 memoized_arg_values: []InternPool.Index,
7244 raw_param_types: []const InternPool.Index,
7248 raw_param_types: InternPool.Index.Slice,
72457249 func_inst: Air.Inst.Ref,
72467250 has_comptime_args: *bool,
72477251) !void {
72487252 const mod = sema.mod;
7253 const ip = &mod.intern_pool;
72497254 const zir_tags = sema.code.instructions.items(.tag);
72507255 switch (zir_tags[inst]) {
72517256 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
......@@ -7260,13 +7265,13 @@ fn analyzeInlineCallArg(
72607265 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);
72617266 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
72627267 const param_ty = param_ty: {
7263 const raw_param_ty = raw_param_types[arg_i.*];
7268 const raw_param_ty = raw_param_types.get(ip)[arg_i.*];
72647269 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;
72657270 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
72667271 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
72677272 break :param_ty param_ty.toIntern();
72687273 };
7269 new_fn_info.param_types[arg_i.*] = param_ty;
7274 new_param_types[arg_i.*] = param_ty;
72707275 const uncasted_arg = uncasted_args[arg_i.*];
72717276 if (try sema.typeRequiresComptime(param_ty.toType())) {
72727277 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {
......@@ -7317,7 +7322,7 @@ fn analyzeInlineCallArg(
73177322 .param_anytype, .param_anytype_comptime => {
73187323 // No coercion needed.
73197324 const uncasted_arg = uncasted_args[arg_i.*];
7320 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern();
7325 new_param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern();
73217326
73227327 if (is_comptime_call) {
73237328 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
......@@ -7371,50 +7376,12 @@ fn analyzeCallArg(
73717376 };
73727377}
73737378
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
74117379fn instantiateGenericCall(
74127380 sema: *Sema,
74137381 block: *Block,
74147382 func: Air.Inst.Ref,
74157383 func_src: LazySrcLoc,
74167384 call_src: LazySrcLoc,
7417 generic_func_ty: Type,
74187385 ensure_result_used: bool,
74197386 uncasted_args: []const Air.Inst.Ref,
74207387 call_tag: Air.Inst.Tag,
......@@ -7423,248 +7390,132 @@ fn instantiateGenericCall(
74237390) CompileError!Air.Inst.Ref {
74247391 const mod = sema.mod;
74257392 const gpa = sema.gpa;
7393 const ip = &mod.intern_pool;
74267394
74277395 const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");
7428 const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7429 .func => |function| function.index,
7430 .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.getFunctionIndex(mod).unwrap().?,
7396 const module_fn = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7397 .func => |x| x,
7398 .ptr => |ptr| mod.intern_pool.indexToKey(mod.declPtr(ptr.addr.decl).val.toIntern()).func,
74317399 else => unreachable,
74327400 };
7433 const module_fn = mod.funcPtr(module_fn_index);
7434 // Check the Module's generic function map with an adapted context, so that we
7435 // can match against `uncasted_args` rather than doing the work below to create a
7436 // generic Scope only to junk it if it matches an existing instantiation.
7401
7402 // Even though there may already be a generic instantiation corresponding
7403 // to this callsite, we must evaluate the expressions of the generic
7404 // function signature with the values of the callsite plugged in.
7405 // Importantly, this may include type coercions that determine whether the
7406 // instantiation is a match of a previous instantiation.
7407 // The actual monomorphization happens via adding `func_instance` to
7408 // `InternPool`.
7409
74377410 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
74387411 const namespace_index = fn_owner_decl.src_namespace;
74397412 const namespace = mod.namespacePtr(namespace_index);
74407413 const fn_zir = namespace.file_scope.zir;
74417414 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
7442 const zir_tags = fn_zir.instructions.items(.tag);
7443
7444 const monomorphed_args = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(generic_func_ty).?.param_types.len);
7445 const callee_index = callee: {
7446 var arg_i: usize = 0;
7447 var monomorphed_arg_i: u32 = 0;
7448 var known_unique = false;
7449 for (fn_info.param_body) |inst| {
7450 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
7451 var is_comptime = false;
7452 var is_anytype = false;
7453 switch (zir_tags[inst]) {
7454 .param => {
7455 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7456 },
7457 .param_comptime => {
7458 is_comptime = true;
7459 },
7460 .param_anytype => {
7461 is_anytype = true;
7462 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7463 },
7464 .param_anytype_comptime => {
7465 is_anytype = true;
7466 is_comptime = true;
7467 },
7468 else => continue,
7469 }
7470
7471 defer arg_i += 1;
7472 const param_ty = generic_func_ty_info.param_types[arg_i];
7473 const is_generic = !is_anytype and param_ty == .generic_poison_type;
7474
7475 if (known_unique) {
7476 if (is_comptime or is_anytype or is_generic) {
7477 monomorphed_arg_i += 1;
7478 }
7479 continue;
7480 }
7481
7482 const uncasted_arg = uncasted_args[arg_i];
7483 const arg_ty = if (is_generic) mod.monomorphed_funcs.getAdapted(
7484 Module.MonomorphedFuncAdaptedKey{
7485 .func = module_fn_index,
7486 .args = monomorphed_args[0..monomorphed_arg_i],
7487 },
7488 Module.MonomorphedFuncsAdaptedContext{ .mod = mod },
7489 ) orelse {
7490 known_unique = true;
7491 monomorphed_arg_i += 1;
7492 continue;
7493 } else if (is_anytype) sema.typeOf(uncasted_arg).toIntern() else param_ty;
7494 const was_comptime = is_comptime;
7495 if (!is_comptime and try sema.typeRequiresComptime(arg_ty.toType())) is_comptime = true;
7496 if (is_comptime or is_anytype) {
7497 // Tuple default values are a part of the type and need to be
7498 // resolved to hash the type.
7499 try sema.resolveTupleLazyValues(block, call_src, arg_ty.toType());
7500 }
7501
7502 if (is_comptime) {
7503 const casted_arg = sema.analyzeGenericCallArgVal(block, .unneeded, arg_ty.toType(), uncasted_arg, "") catch |err| switch (err) {
7504 error.NeededSourceLocation => {
7505 const decl = mod.declPtr(block.src_decl);
7506 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7507 _ = try sema.analyzeGenericCallArgVal(
7508 block,
7509 arg_src,
7510 arg_ty.toType(),
7511 uncasted_arg,
7512 if (was_comptime)
7513 "parameter is comptime"
7514 else
7515 "argument to parameter with comptime-only type must be comptime-known",
7516 );
7517 unreachable;
7518 },
7519 else => |e| return e,
7520 };
7521 monomorphed_args[monomorphed_arg_i] = casted_arg.toIntern();
7522 monomorphed_arg_i += 1;
7523 } else if (is_anytype or is_generic) {
7524 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty });
7525 monomorphed_arg_i += 1;
7526 }
7527 }
7528
7529 if (!known_unique) {
7530 if (mod.monomorphed_funcs.getAdapted(
7531 Module.MonomorphedFuncAdaptedKey{
7532 .func = module_fn_index,
7533 .args = monomorphed_args[0..monomorphed_arg_i],
7534 },
7535 Module.MonomorphedFuncsAdaptedContext{ .mod = mod },
7536 )) |callee_func| break :callee mod.intern_pool.indexToKey(callee_func).func.index;
7537 }
7538
7539 const new_module_func_index = try mod.createFunc(undefined);
7540 const new_module_func = mod.funcPtr(new_module_func_index);
75417415
7542 new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();
7543 new_module_func.comptime_args = null;
7416 const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len);
7417 @memset(comptime_args, .none);
75447418
7545 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
7419 // Re-run the block that creates the function, with the comptime parameters
7420 // pre-populated inside `inst_map`. This causes `param_comptime` and
7421 // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a
7422 // new, monomorphized function, with the comptime parameters elided.
7423 var child_sema: Sema = .{
7424 .mod = mod,
7425 .gpa = gpa,
7426 .arena = sema.arena,
7427 .code = fn_zir,
7428 // We pass the generic callsite's owner decl here because whatever `Decl`
7429 // dependencies are chased at this point should be attached to the
7430 // callsite, not the `Decl` associated with the `func_instance`.
7431 .owner_decl = sema.owner_decl,
7432 .owner_decl_index = sema.owner_decl_index,
7433 .func_index = sema.owner_func_index,
7434 .fn_ret_ty = Type.void,
7435 .owner_func_index = .none,
7436 .comptime_args = comptime_args,
7437 .generic_owner = module_fn.generic_owner,
7438 .branch_quota = sema.branch_quota,
7439 .branch_count = sema.branch_count,
7440 .comptime_mutable_decls = sema.comptime_mutable_decls,
7441 };
7442 defer child_sema.deinit();
75467443
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;
7444 var child_block: Block = .{
7445 .parent = null,
7446 .sema = &child_sema,
7447 .src_decl = module_fn.owner_decl,
7448 .namespace = namespace_index,
7449 .wip_capture_scope = block.wip_capture_scope,
7450 .instructions = .{},
7451 .inlining = null,
7452 .is_comptime = true,
7453 };
7454 defer child_block.instructions.deinit(gpa);
75687455
7569 namespace.anon_decls.putAssumeCapacityNoClobber(new_decl_index, {});
7456 try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
75707457
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);
7458 for (fn_info.param_body[0..uncasted_args.len], uncasted_args, 0..) |inst, arg, i| {
7459 // `child_sema` will use a different `inst_map` which means we have to
7460 // convert from parent-relative `Air.Inst.Ref` to child-relative here.
7461 // Constants are simple; runtime-known values need a new instruction.
7462 child_sema.inst_map.putAssumeCapacityNoClobber(inst, if (try sema.resolveMaybeUndefVal(arg)) |val|
7463 Air.internedToRef(val.toIntern())
7464 else
7465 // We insert into the map an instruction which is runtime-known
7466 // but has the type of the argument.
7467 try child_block.addInst(.{
7468 .tag = .arg,
7469 .data = .{ .arg = .{
7470 .ty = Air.internedToRef(sema.typeOf(arg).toIntern()),
7471 .src_index = @intCast(i),
7472 } },
7473 }));
7474 }
75757475
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 };
7476 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
7477 const callee_index = (child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern();
76137478
7614 break :callee new_func;
7615 };
7616 const callee = mod.funcPtr(callee_index);
7617 callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);
7479 const callee = mod.funcInfo(callee_index);
7480 callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota);
76187481
76197482 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);
76207483
76217484 // 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));
7485 const func_ty = callee.ty.toType();
7486 const func_ty_info = mod.typeToFunc(func_ty).?;
7487 const runtime_args_len: u32 = func_ty_info.param_types.len;
76257488 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
76267489 {
76277490 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,
7491 for (uncasted_args, 0..) |uncasted_arg, total_i| {
7492 const arg_src: LazySrcLoc = if (total_i == 0 and bound_arg_src != null)
7493 bound_arg_src.?
7494 else
7495 .{ .call_arg = .{
7496 .call_node_offset = call_src.node_offset.x,
7497 .arg_index = @intCast(total_i),
7498 } };
7499
7500 const comptime_arg = callee.comptime_args.get(ip)[total_i];
7501 if (comptime_arg == .none) {
7502 const param_ty = func_ty_info.param_types.get(ip)[runtime_i].toType();
7503 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
7504 try sema.queueFullTypeResolution(param_ty);
7505 runtime_args[runtime_i] = casted_arg;
7506 runtime_i += 1;
76337507 }
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;
76597508 }
76607509
7661 try sema.queueFullTypeResolution(mod.typeToFunc(func_ty).?.return_type.toType());
7510 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
76627511 }
76637512
76647513 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
76657514
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;
7515 if (sema.owner_func_index != .none and
7516 func_ty_info.return_type.toType().isError(mod))
7517 {
7518 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
76687519 }
76697520
76707521 try mod.ensureFuncBodyAnalysisQueued(callee_index);
......@@ -7695,238 +7546,6 @@ fn instantiateGenericCall(
76957546 return result;
76967547}
76977548
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);
7719
7720 // Re-run the block that creates the function, with the comptime parameters
7721 // pre-populated inside `inst_map`. This causes `param_comptime` and
7722 // `param_anytype_comptime` ZIR instructions to be ignored, resulting in a
7723 // new, monomorphized function, with the comptime parameters elided.
7724 var child_sema: Sema = .{
7725 .mod = mod,
7726 .gpa = gpa,
7727 .arena = sema.arena,
7728 .code = fn_zir,
7729 .owner_decl = new_decl,
7730 .owner_decl_index = new_decl_index,
7731 .func = null,
7732 .func_index = .none,
7733 .fn_ret_ty = Type.void,
7734 .owner_func = null,
7735 .owner_func_index = .none,
7736 // TODO: fully migrate functions into InternPool
7737 .comptime_args = try mod.tmp_hack_arena.allocator().alloc(TypedValue, uncasted_args.len),
7738 .comptime_args_fn_inst = module_fn.zir_body_inst,
7739 .preallocated_new_func = new_module_func.toOptional(),
7740 .is_generic_instantiation = true,
7741 .branch_quota = sema.branch_quota,
7742 .branch_count = sema.branch_count,
7743 .comptime_mutable_decls = sema.comptime_mutable_decls,
7744 };
7745 defer child_sema.deinit();
7746
7747 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);
7748 defer wip_captures.deinit();
7749
7750 var child_block: Block = .{
7751 .parent = null,
7752 .sema = &child_sema,
7753 .src_decl = new_decl_index,
7754 .namespace = namespace,
7755 .wip_capture_scope = wip_captures.scope,
7756 .instructions = .{},
7757 .inlining = null,
7758 .is_comptime = true,
7759 };
7760 defer {
7761 child_block.instructions.deinit(gpa);
7762 child_block.params.deinit(gpa);
7763 }
7764
7765 try child_sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
7766
7767 var arg_i: usize = 0;
7768 for (fn_info.param_body) |inst| {
7769 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
7770 var is_comptime = false;
7771 var is_anytype = false;
7772 switch (zir_tags[inst]) {
7773 .param => {
7774 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7775 },
7776 .param_comptime => {
7777 is_comptime = true;
7778 },
7779 .param_anytype => {
7780 is_anytype = true;
7781 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7782 },
7783 .param_anytype_comptime => {
7784 is_anytype = true;
7785 is_comptime = true;
7786 },
7787 else => continue,
7788 }
7789 const arg = uncasted_args[arg_i];
7790 if (is_comptime) {
7791 const arg_val = (try sema.resolveMaybeUndefVal(arg)).?;
7792 const child_arg = try child_sema.addConstant(arg_val);
7793 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7794 } else if (is_anytype) {
7795 const arg_ty = sema.typeOf(arg);
7796 if (try sema.typeRequiresComptime(arg_ty)) {
7797 const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) {
7798 error.NeededSourceLocation => {
7799 const decl = mod.declPtr(block.src_decl);
7800 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7801 _ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known");
7802 unreachable;
7803 },
7804 else => |e| return e,
7805 };
7806 const child_arg = try child_sema.addConstant(arg_val);
7807 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7808 } else {
7809 // We insert into the map an instruction which is runtime-known
7810 // but has the type of the argument.
7811 const child_arg = try child_block.addInst(.{
7812 .tag = .arg,
7813 .data = .{ .arg = .{
7814 .ty = try child_sema.addType(arg_ty),
7815 .src_index = @as(u32, @intCast(arg_i)),
7816 } },
7817 });
7818 child_sema.inst_map.putAssumeCapacityNoClobber(inst, child_arg);
7819 }
7820 }
7821 arg_i += 1;
7822 }
7823
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);
7831 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;
7832 const new_func = new_func_val.getFunctionIndex(mod).unwrap().?;
7833 assert(new_func == new_module_func);
7834
7835 const monomorphed_args_index = @as(u32, @intCast(mod.monomorphed_func_keys.items.len));
7836 const monomorphed_args = try mod.monomorphed_func_keys.addManyAsSlice(gpa, monomorphed_args_len);
7837 var monomorphed_arg_i: u32 = 0;
7838 try mod.monomorphed_funcs.ensureUnusedCapacityContext(gpa, monomorphed_args_len + 1, .{ .mod = mod });
7839
7840 arg_i = 0;
7841 for (fn_info.param_body) |inst| {
7842 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
7843 var is_comptime = false;
7844 var is_anytype = false;
7845 switch (zir_tags[inst]) {
7846 .param => {
7847 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7848 },
7849 .param_comptime => {
7850 is_comptime = true;
7851 },
7852 .param_anytype => {
7853 is_anytype = true;
7854 is_comptime = generic_func_ty_info.paramIsComptime(@as(u5, @intCast(arg_i)));
7855 },
7856 .param_anytype_comptime => {
7857 is_anytype = true;
7858 is_comptime = true;
7859 },
7860 else => continue,
7861 }
7862
7863 const param_ty = generic_func_ty_info.param_types[arg_i];
7864 const is_generic = !is_anytype and param_ty == .generic_poison_type;
7865
7866 const arg = child_sema.inst_map.get(inst).?;
7867 const arg_ty = child_sema.typeOf(arg);
7868
7869 if (is_generic) if (mod.monomorphed_funcs.fetchPutAssumeCapacityContext(.{
7870 .func = module_fn_index,
7871 .args_index = monomorphed_args_index,
7872 .args_len = monomorphed_arg_i,
7873 }, arg_ty.toIntern(), .{ .mod = mod })) |kv| assert(kv.value == arg_ty.toIntern());
7874 if (!is_comptime and try sema.typeRequiresComptime(arg_ty)) is_comptime = true;
7875
7876 if (is_comptime) {
7877 const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?;
7878 monomorphed_args[monomorphed_arg_i] = arg_val.toIntern();
7879 monomorphed_arg_i += 1;
7880 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = arg_val };
7881 } else {
7882 if (is_anytype or is_generic) {
7883 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty.toIntern() });
7884 monomorphed_arg_i += 1;
7885 }
7886 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = Value.generic_poison };
7887 }
7888
7889 arg_i += 1;
7890 }
7891
7892 try wip_captures.finalize();
7893
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 mind
7897 // our generic instantiation. Instead we need to perform a comptime call.
7898 const new_fn_info = mod.typeToFunc(new_decl.ty).?;
7899 if (try sema.typeRequiresComptime(new_fn_info.return_type.toType())) {
7900 return error.ComptimeReturn;
7901 }
7902 // Similarly, if the call evaluated to a generic type we need to instead
7903 // call it inline.
7904 if (new_fn_info.is_generic or new_fn_info.cc == .Inline) {
7905 return error.GenericPoison;
7906 }
7907
7908 new_decl.val = (try mod.intern(.{ .func = .{
7909 .ty = new_decl.ty.toIntern(),
7910 .index = new_func,
7911 } })).toValue();
7912 new_decl.alignment = .none;
7913 new_decl.has_tv = true;
7914 new_decl.owns_tv = true;
7915 new_decl.analysis = .complete;
7916
7917 mod.monomorphed_funcs.putAssumeCapacityNoClobberContext(.{
7918 .func = module_fn_index,
7919 .args_index = monomorphed_args_index,
7920 .args_len = monomorphed_arg_i,
7921 }, new_decl.val.toIntern(), .{ .mod = mod });
7922
7923 // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field
7924 // will be populated, ensuring it will have `analyzeBody` called with the ZIR
7925 // parameters mapped appropriately.
7926 try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func });
7927 return new_func;
7928}
7929
79307549fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
79317550 const mod = sema.mod;
79327551 const tuple = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
......@@ -7944,8 +7563,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
79447563fn emitDbgInline(
79457564 sema: *Sema,
79467565 block: *Block,
7947 old_func: Module.Fn.Index,
7948 new_func: Module.Fn.Index,
7566 old_func: InternPool.Index,
7567 new_func: InternPool.Index,
79497568 new_func_ty: Type,
79507569 tag: Air.Inst.Tag,
79517570) CompileError!void {
......@@ -8802,7 +8421,7 @@ fn zirFunc(
88028421 inst,
88038422 .none,
88048423 target_util.defaultAddressSpace(target, .function),
8805 FuncLinkSection.default,
8424 .default,
88068425 cc,
88078426 ret_ty,
88088427 false,
......@@ -8831,10 +8450,7 @@ fn resolveGenericBody(
88318450 // Make sure any nested param instructions don't clobber our work.
88328451 const prev_params = block.params;
88338452 block.params = .{};
8834 defer {
8835 block.params.deinit(sema.gpa);
8836 block.params = prev_params;
8837 }
8453 defer block.params = prev_params;
88388454
88398455 const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err;
88408456 const result = sema.coerce(block, dest_ty, uncasted, src) catch |err| break :err err;
......@@ -8952,12 +8568,6 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
89528568 }
89538569}
89548570
8955const FuncLinkSection = union(enum) {
8956 generic,
8957 default,
8958 explicit: InternPool.NullTerminatedString,
8959};
8960
89618571fn funcCommon(
89628572 sema: *Sema,
89638573 block: *Block,
......@@ -8967,8 +8577,7 @@ fn funcCommon(
89678577 alignment: ?Alignment,
89688578 /// null means generic poison
89698579 address_space: ?std.builtin.AddressSpace,
8970 /// outer null means generic poison; inner null means default link section
8971 section: FuncLinkSection,
8580 section: InternPool.GetFuncDeclKey.Section,
89728581 /// null means generic poison
89738582 cc: ?std.builtin.CallingConvention,
89748583 /// this might be Type.generic_poison
......@@ -8984,6 +8593,8 @@ fn funcCommon(
89848593) CompileError!Air.Inst.Ref {
89858594 const mod = sema.mod;
89868595 const gpa = sema.gpa;
8596 const target = mod.getTarget();
8597 const ip = &mod.intern_pool;
89878598 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
89888599 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };
89898600 const func_src = LazySrcLoc.nodeOffset(src_node_offset);
......@@ -9001,367 +8612,323 @@ fn funcCommon(
90018612 try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?);
90028613 }
90038614
9004 var destroy_fn_on_error = false;
9005 const new_func_index = new_func: {
9006 if (!has_body) break :new_func undefined;
9007 if (sema.comptime_args_fn_inst == func_inst) {
9008 const new_func_index = sema.preallocated_new_func.unwrap().?;
9009 sema.preallocated_new_func = .none; // take ownership
9010 break :new_func new_func_index;
9011 }
9012 destroy_fn_on_error = true;
9013 var new_func: Module.Fn = undefined;
9014 // Set this here so that the inferred return type can be printed correctly if it appears in an error.
9015 new_func.owner_decl = sema.owner_decl_index;
9016 const new_func_index = try mod.createFunc(new_func);
9017 break :new_func new_func_index;
9018 };
9019 errdefer if (destroy_fn_on_error) mod.destroyFunc(new_func_index);
9020
9021 const target = mod.getTarget();
9022 const fn_ty: Type = fn_ty: {
9023 // In the case of generic calling convention, or generic alignment, we use
9024 // default values which are only meaningful for the generic function, *not*
9025 // the instantiation, which can depend on comptime parameters.
9026 // Related proposal: https://github.com/ziglang/zig/issues/11834
9027 const cc_resolved = cc orelse .Unspecified;
9028 const param_types = try sema.arena.alloc(InternPool.Index, block.params.items.len);
9029 var comptime_bits: u32 = 0;
9030 for (param_types, block.params.items, 0..) |*dest_param_ty, param, i| {
9031 const is_noalias = blk: {
9032 const index = std.math.cast(u5, i) orelse break :blk false;
9033 break :blk @as(u1, @truncate(noalias_bits >> index)) != 0;
9034 };
9035 dest_param_ty.* = param.ty.toIntern();
9036 sema.analyzeParameter(
9037 block,
9038 .unneeded,
9039 param,
9040 &comptime_bits,
9041 i,
9042 &is_generic,
9043 cc_resolved,
9044 has_body,
9045 is_noalias,
9046 ) catch |err| switch (err) {
9047 error.NeededSourceLocation => {
9048 const decl = mod.declPtr(block.src_decl);
9049 try sema.analyzeParameter(
9050 block,
9051 Module.paramSrc(src_node_offset, mod, decl, i),
9052 param,
9053 &comptime_bits,
9054 i,
9055 &is_generic,
9056 cc_resolved,
9057 has_body,
9058 is_noalias,
9059 );
9060 unreachable;
9061 },
9062 else => |e| return e,
9063 };
9064 }
9065
9066 var ret_ty_requires_comptime = false;
9067 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
9068 ret_ty_requires_comptime = ret_comptime;
9069 break :rp bare_return_type.isGenericPoison();
9070 } else |err| switch (err) {
9071 error.GenericPoison => rp: {
9072 is_generic = true;
9073 break :rp true;
9074 },
9075 else => |e| return e,
9076 };
8615 const is_source_decl = sema.generic_owner == .none;
90778616
9078 const return_type: Type = if (!inferred_error_set or ret_poison)
9079 bare_return_type
9080 else blk: {
9081 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
9082 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
9083 .func = new_func_index,
9084 });
9085 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
9086 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
8617 // In the case of generic calling convention, or generic alignment, we use
8618 // default values which are only meaningful for the generic function, *not*
8619 // the instantiation, which can depend on comptime parameters.
8620 // Related proposal: https://github.com/ziglang/zig/issues/11834
8621 const cc_resolved = cc orelse .Unspecified;
8622 var comptime_bits: u32 = 0;
8623 for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| {
8624 const param_ty = param_ty_ip.toType();
8625 const is_noalias = blk: {
8626 const index = std.math.cast(u5, i) orelse break :blk false;
8627 break :blk @as(u1, @truncate(noalias_bits >> index)) != 0;
90878628 };
9088
9089 if (!return_type.isValidReturnType(mod)) {
9090 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";
8629 const param_src: LazySrcLoc = .{ .fn_proto_param = .{
8630 .fn_proto_node_offset = src_node_offset,
8631 .param_index = @intCast(i),
8632 } };
8633 const requires_comptime = try sema.typeRequiresComptime(param_ty);
8634 if (param_is_comptime or requires_comptime) {
8635 comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error
8636 }
8637 const this_generic = param_ty.isGenericPoison();
8638 is_generic = is_generic or this_generic;
8639 if (param_is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) {
8640 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});
8641 }
8642 if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved)) {
8643 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc_resolved)});
8644 }
8645 if (!param_ty.isValidParamType(mod)) {
8646 const opaque_str = if (param_ty.zigTypeTag(mod) == .Opaque) "opaque " else "";
90918647 const msg = msg: {
9092 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{
9093 opaque_str, return_type.fmt(mod),
8648 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{
8649 opaque_str, param_ty.fmt(mod),
90948650 });
9095 errdefer msg.destroy(gpa);
8651 errdefer msg.destroy(sema.gpa);
90968652
9097 try sema.addDeclaredHereNote(msg, return_type);
8653 try sema.addDeclaredHereNote(msg, param_ty);
90988654 break :msg msg;
90998655 };
91008656 return sema.failWithOwnedErrorMsg(msg);
91018657 }
9102 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and
9103 !try sema.validateExternType(return_type, .ret_ty))
9104 {
8658 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) {
91058659 const msg = msg: {
9106 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
9107 return_type.fmt(mod), @tagName(cc_resolved),
8660 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
8661 param_ty.fmt(mod), @tagName(cc_resolved),
91088662 });
9109 errdefer msg.destroy(gpa);
8663 errdefer msg.destroy(sema.gpa);
91108664
91118665 const src_decl = mod.declPtr(block.src_decl);
9112 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl, mod), return_type, .ret_ty);
8666 try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl, mod), param_ty, .param_ty);
91138667
9114 try sema.addDeclaredHereNote(msg, return_type);
8668 try sema.addDeclaredHereNote(msg, param_ty);
91158669 break :msg msg;
91168670 };
91178671 return sema.failWithOwnedErrorMsg(msg);
91188672 }
8673 if (is_source_decl and requires_comptime and !param_is_comptime and has_body) {
8674 const msg = msg: {
8675 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{
8676 param_ty.fmt(mod),
8677 });
8678 errdefer msg.destroy(sema.gpa);
91198679
9120 // If the return type is comptime-only but not dependent on parameters then all parameter types also need to be comptime
9121 if (!sema.is_generic_instantiation and has_body and ret_ty_requires_comptime) comptime_check: {
9122 for (block.params.items) |param| {
9123 if (!param.is_comptime) break;
9124 } else break :comptime_check;
8680 const src_decl = mod.declPtr(block.src_decl);
8681 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param_ty);
91258682
9126 const msg = try sema.errMsg(
9127 block,
9128 ret_ty_src,
9129 "function with comptime-only return type '{}' requires all parameters to be comptime",
9130 .{return_type.fmt(mod)},
9131 );
9132 try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl, mod), return_type);
9133
9134 const tags = sema.code.instructions.items(.tag);
9135 const data = sema.code.instructions.items(.data);
9136 const param_body = sema.code.getParamBody(func_inst);
9137 for (block.params.items, 0..) |param, i| {
9138 if (!param.is_comptime) {
9139 const param_index = param_body[i];
9140 const param_src = switch (tags[param_index]) {
9141 .param => data[param_index].pl_tok.src(),
9142 .param_anytype => data[param_index].str_tok.src(),
9143 else => unreachable,
9144 };
9145 if (param.name.len != 0) {
9146 try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{param.name});
9147 } else {
9148 try sema.errNote(block, param_src, msg, "param is required to be comptime", .{});
9149 }
9150 }
9151 }
8683 try sema.addDeclaredHereNote(msg, param_ty);
8684 break :msg msg;
8685 };
91528686 return sema.failWithOwnedErrorMsg(msg);
91538687 }
8688 if (is_source_decl and !this_generic and is_noalias and
8689 !(param_ty.zigTypeTag(mod) == .Pointer or param_ty.isPtrLikeOptional(mod)))
8690 {
8691 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
8692 }
8693 }
91548694
9155 const arch = mod.getTarget().cpu.arch;
9156 if (switch (cc_resolved) {
9157 .Unspecified, .C, .Naked, .Async, .Inline => null,
9158 .Interrupt => switch (arch) {
9159 .x86, .x86_64, .avr, .msp430 => null,
9160 else => @as([]const u8, "x86, x86_64, AVR, and MSP430"),
9161 },
9162 .Signal => switch (arch) {
9163 .avr => null,
9164 else => @as([]const u8, "AVR"),
9165 },
9166 .Stdcall, .Fastcall, .Thiscall => switch (arch) {
9167 .x86 => null,
9168 else => @as([]const u8, "x86"),
9169 },
9170 .Vectorcall => switch (arch) {
9171 .x86, .aarch64, .aarch64_be, .aarch64_32 => null,
9172 else => @as([]const u8, "x86 and AArch64"),
9173 },
9174 .APCS, .AAPCS, .AAPCSVFP => switch (arch) {
9175 .arm, .armeb, .aarch64, .aarch64_be, .aarch64_32, .thumb, .thumbeb => null,
9176 else => @as([]const u8, "ARM"),
9177 },
9178 .SysV, .Win64 => switch (arch) {
9179 .x86_64 => null,
9180 else => @as([]const u8, "x86_64"),
9181 },
9182 .Kernel => switch (arch) {
9183 .nvptx, .nvptx64, .amdgcn, .spirv32, .spirv64 => null,
9184 else => @as([]const u8, "nvptx, amdgcn and SPIR-V"),
9185 },
9186 }) |allowed_platform| {
9187 return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{
9188 @tagName(cc_resolved),
9189 allowed_platform,
9190 @tagName(arch),
8695 var ret_ty_requires_comptime = false;
8696 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
8697 ret_ty_requires_comptime = ret_comptime;
8698 break :rp bare_return_type.isGenericPoison();
8699 } else |err| switch (err) {
8700 error.GenericPoison => rp: {
8701 is_generic = true;
8702 break :rp true;
8703 },
8704 else => |e| return e,
8705 };
8706 const final_is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
8707
8708 const param_types = block.params.items(.ty);
8709
8710 const opt_func_index: InternPool.Index = i: {
8711 if (is_extern) {
8712 assert(comptime_bits == 0);
8713 assert(cc != null);
8714 assert(section != .generic);
8715 assert(address_space != null);
8716 assert(!is_generic);
8717 break :i try ip.getExternFunc(gpa, .{
8718 .param_types = param_types,
8719 .noalias_bits = noalias_bits,
8720 .return_type = bare_return_type.toIntern(),
8721 .cc = cc_resolved,
8722 .alignment = alignment.?,
8723 .is_var_args = var_args,
8724 .decl = sema.owner_decl_index,
8725 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
8726 gpa,
8727 try sema.handleExternLibName(block, .{
8728 .node_offset_lib_name = src_node_offset,
8729 }, lib_name),
8730 )).toOptional() else .none,
91918731 });
91928732 }
91938733
9194 if (cc_resolved == .Inline and is_noinline) {
9195 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
9196 }
9197 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
9198 is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
8734 if (!has_body) break :i .none;
91998735
9200 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {
9201 // Make sure that StackTrace's fields are resolved so that the backend can
9202 // lower this fn type.
9203 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
9204 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
8736 if (is_source_decl) {
8737 if (inferred_error_set)
8738 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
8739
8740 break :i try ip.getFuncDecl(gpa, .{
8741 .param_types = param_types,
8742 .noalias_bits = noalias_bits,
8743 .comptime_bits = comptime_bits,
8744 .return_type = bare_return_type.toIntern(),
8745 .inferred_error_set = inferred_error_set,
8746 .cc = cc,
8747 .alignment = alignment,
8748 .section = section,
8749 .address_space = address_space,
8750 .is_var_args = var_args,
8751 .is_generic = final_is_generic,
8752 .is_noinline = is_noinline,
8753
8754 .zir_body_inst = func_inst,
8755 .lbrace_line = src_locs.lbrace_line,
8756 .rbrace_line = src_locs.rbrace_line,
8757 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
8758 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
8759 });
92058760 }
92068761
9207 break :fn_ty try mod.funcType(.{
8762 assert(!is_generic);
8763 assert(comptime_bits == 0);
8764 assert(cc != null);
8765 assert(section != .generic);
8766 assert(address_space != null);
8767 assert(!var_args);
8768
8769 break :i try ip.getFuncInstance(gpa, .{
92088770 .param_types = param_types,
92098771 .noalias_bits = noalias_bits,
9210 .comptime_bits = comptime_bits,
9211 .return_type = return_type.toIntern(),
8772 .return_type = bare_return_type.toIntern(),
92128773 .cc = cc_resolved,
9213 .cc_is_generic = cc == null,
9214 .alignment = alignment orelse .none,
9215 .align_is_generic = alignment == null,
9216 .section_is_generic = section == .generic,
9217 .addrspace_is_generic = address_space == null,
9218 .is_var_args = var_args,
9219 .is_generic = is_generic,
8774 .alignment = alignment.?,
92208775 .is_noinline = is_noinline,
9221 });
9222 };
92238776
9224 sema.owner_decl.@"linksection" = switch (section) {
9225 .generic => .none,
9226 .default => .none,
9227 .explicit => |section_name| section_name.toOptional(),
8777 .generic_owner = sema.generic_owner,
8778 });
92288779 };
9229 sema.owner_decl.alignment = alignment orelse .none;
9230 sema.owner_decl.@"addrspace" = address_space orelse .generic;
92318780
9232 if (is_extern) {
9233 return sema.addConstant((try mod.intern(.{ .extern_func = .{
9234 .ty = fn_ty.toIntern(),
9235 .decl = sema.owner_decl_index,
9236 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
9237 gpa,
9238 try sema.handleExternLibName(block, .{
9239 .node_offset_lib_name = src_node_offset,
9240 }, lib_name),
9241 )).toOptional() else .none,
9242 } })).toValue());
9243 }
9244
9245 if (!has_body) {
9246 return sema.addType(fn_ty);
9247 }
9248
9249 const is_inline = fn_ty.fnCallingConvention(mod) == .Inline;
9250 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;
9251
9252 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {
9253 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
9254 } else null;
9255
9256 const new_func = mod.funcPtr(new_func_index);
9257 const hash = new_func.hash;
9258 const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;
9259 new_func.* = .{
9260 .state = anal_state,
9261 .zir_body_inst = func_inst,
9262 .owner_decl = sema.owner_decl_index,
9263 .generic_owner_decl = generic_owner_decl,
9264 .comptime_args = comptime_args,
9265 .hash = hash,
9266 .lbrace_line = src_locs.lbrace_line,
9267 .rbrace_line = src_locs.rbrace_line,
9268 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9269 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9270 .branch_quota = default_branch_quota,
9271 .is_noinline = is_noinline,
9272 };
9273 return sema.addConstant((try mod.intern(.{ .func = .{
9274 .ty = fn_ty.toIntern(),
9275 .index = new_func_index,
9276 } })).toValue());
9277}
8781 const return_type: Type = if (opt_func_index == .none or ret_poison)
8782 bare_return_type
8783 else
8784 ip.funcReturnType(ip.typeOf(opt_func_index)).toType();
92788785
9279fn analyzeParameter(
9280 sema: *Sema,
9281 block: *Block,
9282 param_src: LazySrcLoc,
9283 param: Block.Param,
9284 comptime_bits: *u32,
9285 i: usize,
9286 is_generic: *bool,
9287 cc: std.builtin.CallingConvention,
9288 has_body: bool,
9289 is_noalias: bool,
9290) !void {
9291 const mod = sema.mod;
9292 const requires_comptime = try sema.typeRequiresComptime(param.ty);
9293 if (param.is_comptime or requires_comptime) {
9294 comptime_bits.* |= @as(u32, 1) << @as(u5, @intCast(i)); // TODO: handle cast error
9295 }
9296 const this_generic = param.ty.isGenericPoison();
9297 is_generic.* = is_generic.* or this_generic;
9298 const target = mod.getTarget();
9299 if (param.is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc)) {
9300 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9301 }
9302 if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc)) {
9303 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9304 }
9305 if (!param.ty.isValidParamType(mod)) {
9306 const opaque_str = if (param.ty.zigTypeTag(mod) == .Opaque) "opaque " else "";
8786 if (!return_type.isValidReturnType(mod)) {
8787 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";
93078788 const msg = msg: {
9308 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{
9309 opaque_str, param.ty.fmt(mod),
8789 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{
8790 opaque_str, return_type.fmt(mod),
93108791 });
9311 errdefer msg.destroy(sema.gpa);
8792 errdefer msg.destroy(gpa);
93128793
9313 try sema.addDeclaredHereNote(msg, param.ty);
8794 try sema.addDeclaredHereNote(msg, return_type);
93148795 break :msg msg;
93158796 };
93168797 return sema.failWithOwnedErrorMsg(msg);
93178798 }
9318 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) {
8799 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and
8800 !try sema.validateExternType(return_type, .ret_ty))
8801 {
93198802 const msg = msg: {
9320 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
9321 param.ty.fmt(mod), @tagName(cc),
8803 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
8804 return_type.fmt(mod), @tagName(cc_resolved),
93228805 });
9323 errdefer msg.destroy(sema.gpa);
8806 errdefer msg.destroy(gpa);
93248807
93258808 const src_decl = mod.declPtr(block.src_decl);
9326 try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl, mod), param.ty, .param_ty);
8809 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl, mod), return_type, .ret_ty);
93278810
9328 try sema.addDeclaredHereNote(msg, param.ty);
8811 try sema.addDeclaredHereNote(msg, return_type);
93298812 break :msg msg;
93308813 };
93318814 return sema.failWithOwnedErrorMsg(msg);
93328815 }
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);
93398816
9340 const src_decl = mod.declPtr(block.src_decl);
9341 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param.ty);
8817 // If the return type is comptime-only but not dependent on parameters then
8818 // all parameter types also need to be comptime.
8819 if (is_source_decl and opt_func_index != .none and ret_ty_requires_comptime) comptime_check: {
8820 for (block.params.items(.is_comptime)) |is_comptime| {
8821 if (!is_comptime) break;
8822 } else break :comptime_check;
93428823
9343 try sema.addDeclaredHereNote(msg, param.ty);
9344 break :msg msg;
9345 };
8824 const msg = try sema.errMsg(
8825 block,
8826 ret_ty_src,
8827 "function with comptime-only return type '{}' requires all parameters to be comptime",
8828 .{return_type.fmt(mod)},
8829 );
8830 try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl, mod), return_type);
8831
8832 const tags = sema.code.instructions.items(.tag);
8833 const data = sema.code.instructions.items(.data);
8834 const param_body = sema.code.getParamBody(func_inst);
8835 for (block.params.items(.is_comptime), block.params.items(.name), param_body) |is_comptime, name_nts, param_index| {
8836 if (!is_comptime) {
8837 const param_src = switch (tags[param_index]) {
8838 .param => data[param_index].pl_tok.src(),
8839 .param_anytype => data[param_index].str_tok.src(),
8840 else => unreachable,
8841 };
8842 const name = sema.code.nullTerminatedString2(name_nts);
8843 if (name.len != 0) {
8844 try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{name});
8845 } else {
8846 try sema.errNote(block, param_src, msg, "param is required to be comptime", .{});
8847 }
8848 }
8849 }
93468850 return sema.failWithOwnedErrorMsg(msg);
93478851 }
9348 if (!sema.is_generic_instantiation and !this_generic and is_noalias and
9349 !(param.ty.zigTypeTag(mod) == .Pointer or param.ty.isPtrLikeOptional(mod)))
9350 {
9351 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
8852
8853 const arch = target.cpu.arch;
8854 if (switch (cc_resolved) {
8855 .Unspecified, .C, .Naked, .Async, .Inline => null,
8856 .Interrupt => switch (arch) {
8857 .x86, .x86_64, .avr, .msp430 => null,
8858 else => @as([]const u8, "x86, x86_64, AVR, and MSP430"),
8859 },
8860 .Signal => switch (arch) {
8861 .avr => null,
8862 else => @as([]const u8, "AVR"),
8863 },
8864 .Stdcall, .Fastcall, .Thiscall => switch (arch) {
8865 .x86 => null,
8866 else => @as([]const u8, "x86"),
8867 },
8868 .Vectorcall => switch (arch) {
8869 .x86, .aarch64, .aarch64_be, .aarch64_32 => null,
8870 else => @as([]const u8, "x86 and AArch64"),
8871 },
8872 .APCS, .AAPCS, .AAPCSVFP => switch (arch) {
8873 .arm, .armeb, .aarch64, .aarch64_be, .aarch64_32, .thumb, .thumbeb => null,
8874 else => @as([]const u8, "ARM"),
8875 },
8876 .SysV, .Win64 => switch (arch) {
8877 .x86_64 => null,
8878 else => @as([]const u8, "x86_64"),
8879 },
8880 .Kernel => switch (arch) {
8881 .nvptx, .nvptx64, .amdgcn, .spirv32, .spirv64 => null,
8882 else => @as([]const u8, "nvptx, amdgcn and SPIR-V"),
8883 },
8884 }) |allowed_platform| {
8885 return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{
8886 @tagName(cc_resolved),
8887 allowed_platform,
8888 @tagName(arch),
8889 });
93528890 }
8891
8892 if (cc_resolved == .Inline and is_noinline) {
8893 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
8894 }
8895 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
8896
8897 if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) {
8898 // Make sure that StackTrace's fields are resolved so that the backend can
8899 // lower this fn type.
8900 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
8901 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
8902 }
8903
8904 return Air.internedToRef(if (opt_func_index == .none) try ip.getFuncType(gpa, .{
8905 .param_types = param_types,
8906 .noalias_bits = noalias_bits,
8907 .comptime_bits = comptime_bits,
8908 .return_type = return_type.toIntern(),
8909 .cc = cc_resolved,
8910 .cc_is_generic = cc == null,
8911 .alignment = alignment orelse .none,
8912 .align_is_generic = alignment == null,
8913 .section_is_generic = section == .generic,
8914 .addrspace_is_generic = address_space == null,
8915 .is_var_args = var_args,
8916 .is_generic = final_is_generic,
8917 .is_noinline = is_noinline,
8918 }) else opt_func_index);
93538919}
93548920
93558921fn zirParam(
93568922 sema: *Sema,
93578923 block: *Block,
93588924 inst: Zir.Inst.Index,
8925 param_index: u32,
93598926 comptime_syntax: bool,
93608927) CompileError!void {
93618928 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
93628929 const src = inst_data.src();
93638930 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);
9364 const param_name = sema.code.nullTerminatedString(extra.data.name);
8931 const param_name: Zir.NullTerminatedString = @enumFromInt(extra.data.name);
93658932 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
93668933
93678934 // We could be in a generic function instantiation, or we could be evaluating a generic
......@@ -9370,15 +8937,11 @@ fn zirParam(
93708937 const err = err: {
93718938 // Make sure any nested param instructions don't clobber our work.
93728939 const prev_params = block.params;
9373 const prev_preallocated_new_func = sema.preallocated_new_func;
93748940 const prev_no_partial_func_type = sema.no_partial_func_ty;
93758941 block.params = .{};
9376 sema.preallocated_new_func = .none;
93778942 sema.no_partial_func_ty = true;
93788943 defer {
9379 block.params.deinit(sema.gpa);
93808944 block.params = prev_params;
9381 sema.preallocated_new_func = prev_preallocated_new_func;
93828945 sema.no_partial_func_ty = prev_no_partial_func_type;
93838946 }
93848947
......@@ -9390,7 +8953,7 @@ fn zirParam(
93908953 };
93918954 switch (err) {
93928955 error.GenericPoison => {
9393 if (sema.inst_map.get(inst)) |_| {
8956 if (sema.inst_map.contains(inst)) {
93948957 // A generic function is about to evaluate to another generic function.
93958958 // Return an error instead.
93968959 return error.GenericPoison;
......@@ -9398,8 +8961,8 @@ fn zirParam(
93988961 // The type is not available until the generic instantiation.
93998962 // We result the param instruction with a poison value and
94008963 // insert an anytype parameter.
9401 try block.params.append(sema.gpa, .{
9402 .ty = Type.generic_poison,
8964 try block.params.append(sema.arena, .{
8965 .ty = .generic_poison_type,
94038966 .is_comptime = comptime_syntax,
94048967 .name = param_name,
94058968 });
......@@ -9409,9 +8972,10 @@ fn zirParam(
94098972 else => |e| return e,
94108973 }
94118974 };
8975
94128976 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {
94138977 error.GenericPoison => {
9414 if (sema.inst_map.get(inst)) |_| {
8978 if (sema.inst_map.contains(inst)) {
94158979 // A generic function is about to evaluate to another generic function.
94168980 // Return an error instead.
94178981 return error.GenericPoison;
......@@ -9419,8 +8983,8 @@ fn zirParam(
94198983 // The type is not available until the generic instantiation.
94208984 // We result the param instruction with a poison value and
94218985 // insert an anytype parameter.
9422 try block.params.append(sema.gpa, .{
9423 .ty = Type.generic_poison,
8986 try block.params.append(sema.arena, .{
8987 .ty = .generic_poison_type,
94248988 .is_comptime = comptime_syntax,
94258989 .name = param_name,
94268990 });
......@@ -9429,8 +8993,9 @@ fn zirParam(
94298993 },
94308994 else => |e| return e,
94318995 } or comptime_syntax;
8996
94328997 if (sema.inst_map.get(inst)) |arg| {
9433 if (is_comptime and sema.preallocated_new_func != .none) {
8998 if (is_comptime and sema.generic_owner != .none) {
94348999 // We have a comptime value for this parameter so it should be elided from the
94359000 // function type of the function instruction in this block.
94369001 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
......@@ -9440,12 +9005,13 @@ fn zirParam(
94409005 // have the callee source location return `GenericPoison`
94419006 // so that the instantiation is failed and the coercion
94429007 // is handled by comptime call logic instead.
9443 assert(sema.is_generic_instantiation);
9008 assert(sema.generic_owner != .none);
94449009 return error.GenericPoison;
94459010 },
9446 else => return err,
9011 else => |e| return e,
94479012 };
94489013 sema.inst_map.putAssumeCapacity(inst, coerced_arg);
9014 sema.comptime_args[param_index] = (try sema.resolveConstMaybeUndefVal(block, src, coerced_arg, "parameter is declared comptime")).toIntern();
94499015 return;
94509016 }
94519017 // Even though a comptime argument is provided, the generic function wants to treat
......@@ -9453,19 +9019,19 @@ fn zirParam(
94539019 assert(sema.inst_map.remove(inst));
94549020 }
94559021
9456 if (sema.preallocated_new_func != .none) {
9022 if (sema.generic_owner != .none) {
94579023 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
94589024 // In this case we are instantiating a generic function call with a non-comptime
94599025 // non-anytype parameter that ended up being a one-possible-type.
94609026 // We don't want the parameter to be part of the instantiated function type.
9461 const result = try sema.addConstant(opv);
9462 sema.inst_map.putAssumeCapacity(inst, result);
9027 sema.inst_map.putAssumeCapacity(inst, Air.internedToRef(opv.toIntern()));
9028 sema.comptime_args[param_index] = opv.toIntern();
94639029 return;
94649030 }
94659031 }
94669032
9467 try block.params.append(sema.gpa, .{
9468 .ty = param_ty,
9033 try block.params.append(sema.arena, .{
9034 .ty = param_ty.toIntern(),
94699035 .is_comptime = comptime_syntax,
94709036 .name = param_name,
94719037 });
......@@ -9473,17 +9039,15 @@ fn zirParam(
94739039 if (is_comptime) {
94749040 // If this is a comptime parameter we can add a constant generic_poison
94759041 // since this is also a generic parameter.
9476 const result = try sema.addConstant(Value.generic_poison);
9477 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
9042 sema.inst_map.putAssumeCapacityNoClobber(inst, .generic_poison);
94789043 } else {
94799044 // Otherwise we need a dummy runtime instruction.
9480 const result_index = @as(Air.Inst.Index, @intCast(sema.air_instructions.len));
9045 const result_index: Air.Inst.Index = @intCast(sema.air_instructions.len);
94819046 try sema.air_instructions.append(sema.gpa, .{
94829047 .tag = .alloc,
94839048 .data = .{ .ty = param_ty },
94849049 });
9485 const result = Air.indexToRef(result_index);
9486 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
9050 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(result_index));
94879051 }
94889052}
94899053
......@@ -9491,24 +9055,34 @@ fn zirParamAnytype(
94919055 sema: *Sema,
94929056 block: *Block,
94939057 inst: Zir.Inst.Index,
9058 param_index: u32,
94949059 comptime_syntax: bool,
94959060) CompileError!void {
94969061 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
9497 const param_name = inst_data.get(sema.code);
9062 const param_name: Zir.NullTerminatedString = @enumFromInt(inst_data.start);
9063 const src = inst_data.src();
94989064
94999065 if (sema.inst_map.get(inst)) |air_ref| {
95009066 const param_ty = sema.typeOf(air_ref);
9501 if (comptime_syntax or try sema.typeRequiresComptime(param_ty)) {
9502 // We have a comptime value for this parameter so it should be elided from the
9503 // function type of the function instruction in this block.
9067 // If we have a comptime value for this parameter, it should be elided
9068 // from the function type of the function instruction in this block.
9069 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
9070 sema.comptime_args[param_index] = opv.toIntern();
95049071 return;
95059072 }
9506 if (null != try sema.typeHasOnePossibleValue(param_ty)) {
9073 if (comptime_syntax) {
9074 sema.comptime_args[param_index] = (try sema.resolveConstMaybeUndefVal(block, src, air_ref, "parameter is declared comptime")).toIntern();
95079075 return;
95089076 }
9077 if (try sema.typeRequiresComptime(param_ty)) {
9078 sema.comptime_args[param_index] = (try sema.resolveConstMaybeUndefVal(block, src, air_ref, "parameter type requires comptime")).toIntern();
9079 return;
9080 }
9081
9082 // The parameter is runtime-known.
95099083 // The map is already populated but we do need to add a runtime parameter.
9510 try block.params.append(sema.gpa, .{
9511 .ty = param_ty,
9084 try block.params.append(sema.arena, .{
9085 .ty = param_ty.toIntern(),
95129086 .is_comptime = false,
95139087 .name = param_name,
95149088 });
......@@ -9517,8 +9091,8 @@ fn zirParamAnytype(
95179091
95189092 // We are evaluating a generic function without any comptime args provided.
95199093
9520 try block.params.append(sema.gpa, .{
9521 .ty = Type.generic_poison,
9094 try block.params.append(sema.arena, .{
9095 .ty = .generic_poison_type,
95229096 .is_comptime = comptime_syntax,
95239097 .name = param_name,
95249098 });
......@@ -10673,7 +10247,7 @@ const SwitchProngAnalysis = struct {
1067310247 return sema.bitCast(block, item_ty, spa.operand, operand_src, null);
1067410248 }
1067510249
10676 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10250 var names: Module.InferredErrorSet.NameMap = .{};
1067710251 try names.ensureUnusedCapacity(sema.arena, case_vals.len);
1067810252 for (case_vals) |err| {
1067910253 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;
......@@ -11122,7 +10696,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
1112210696 }
1112310697
1112410698 const error_names = operand_ty.errorSetNames(mod);
11125 var names: Module.Fn.InferredErrorSet.NameMap = .{};
10699 var names: Module.InferredErrorSet.NameMap = .{};
1112610700 try names.ensureUnusedCapacity(sema.arena, error_names.len);
1112710701 for (error_names) |error_name| {
1112810702 if (seen_errors.contains(error_name)) continue;
......@@ -16295,6 +15869,7 @@ fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
1629515869
1629615870fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1629715871 const mod = sema.mod;
15872 const ip = &mod.intern_pool;
1629815873 const inst_data = sema.code.instructions.items(.data)[inst].inst_node;
1629915874 var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?;
1630015875 // Note: The target closure must be in this scope list.
......@@ -16305,8 +15880,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1630515880
1630615881 // Fail this decl if a scope it depended on failed.
1630715882 if (scope.failed()) {
16308 if (sema.owner_func) |owner_func| {
16309 owner_func.state = .dependency_failure;
15883 if (sema.owner_func_index != .none) {
15884 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
1631015885 } else {
1631115886 sema.owner_decl.analysis = .dependency_failure;
1631215887 }
......@@ -16423,8 +15998,8 @@ fn zirBuiltinSrc(
1642315998 const mod = sema.mod;
1642415999 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;
1642516000 const src = LazySrcLoc.nodeOffset(extra.node);
16426 const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{});
16427 const fn_owner_decl = mod.declPtr(func.owner_decl);
16001 if (sema.func_index == .none) return sema.fail(block, src, "@src outside function", .{});
16002 const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index);
1642816003
1642916004 const func_name_val = blk: {
1643016005 var anon_decl = try block.startAnonDecl();
......@@ -16548,10 +16123,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1654816123 const param_info_decl = mod.declPtr(param_info_decl_index);
1654916124 const param_info_ty = param_info_decl.val.toType();
1655016125
16551 const param_vals = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(ty).?.param_types.len);
16126 const func_ty_info = mod.typeToFunc(ty).?;
16127 const param_vals = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
1655216128 for (param_vals, 0..) |*param_val, i| {
16553 const info = mod.typeToFunc(ty).?;
16554 const param_ty = info.param_types[i];
16129 const param_ty = func_ty_info.param_types.get(ip)[i];
1655516130 const is_generic = param_ty == .generic_poison_type;
1655616131 const param_ty_val = try ip.get(gpa, .{ .opt = .{
1655716132 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),
......@@ -16560,7 +16135,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1656016135
1656116136 const is_noalias = blk: {
1656216137 const index = std.math.cast(u5, i) orelse break :blk false;
16563 break :blk @as(u1, @truncate(info.noalias_bits >> index)) != 0;
16138 break :blk @as(u1, @truncate(func_ty_info.noalias_bits >> index)) != 0;
1656416139 };
1656516140
1656616141 const param_fields = .{
......@@ -16603,23 +16178,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1660316178 } });
1660416179 };
1660516180
16606 const info = mod.typeToFunc(ty).?;
1660716181 const ret_ty_opt = try mod.intern(.{ .opt = .{
1660816182 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),
16609 .val = if (info.return_type == .generic_poison_type) .none else info.return_type,
16183 .val = if (func_ty_info.return_type == .generic_poison_type)
16184 .none
16185 else
16186 func_ty_info.return_type,
1661016187 } });
1661116188
1661216189 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1661316190
1661416191 const field_values = .{
1661516192 // calling_convention: CallingConvention,
16616 (try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(info.cc))).toIntern(),
16193 (try mod.enumValueFieldIndex(callconv_ty, @intFromEnum(func_ty_info.cc))).toIntern(),
1661716194 // alignment: comptime_int,
1661816195 (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).toIntern(),
1661916196 // is_generic: bool,
16620 Value.makeBool(info.is_generic).toIntern(),
16197 Value.makeBool(func_ty_info.is_generic).toIntern(),
1662116198 // is_var_args: bool,
16622 Value.makeBool(info.is_var_args).toIntern(),
16199 Value.makeBool(func_ty_info.is_var_args).toIntern(),
1662316200 // return_type: ?type,
1662416201 ret_ty_opt,
1662516202 // args: []const Fn.Param,
......@@ -18425,9 +18002,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
1842518002 // This is only relevant at runtime.
1842618003 if (start_block.is_comptime or start_block.is_typeof) return;
1842718004
18428 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
18429 if (!sema.owner_func.?.calls_or_awaits_errorable_fn) return;
18430 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;
18005 const mod = sema.mod;
18006 const ip = &mod.intern_pool;
18007
18008 if (!mod.backendSupportsFeature(.error_return_trace)) return;
18009 if (!ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn) return;
18010 if (!mod.comp.bin_file.options.error_return_tracing) return;
1843118011
1843218012 const tracy = trace(@src());
1843318013 defer tracy.end();
......@@ -19461,13 +19041,14 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
1946119041
1946219042fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
1946319043 const mod = sema.mod;
19044 const ip = &mod.intern_pool;
1946419045 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
1946519046 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
1946619047 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
1946719048 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
1946819049
19469 if (sema.owner_func != null and
19470 sema.owner_func.?.calls_or_awaits_errorable_fn and
19050 if (sema.owner_func_index != .none and
19051 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and
1947119052 mod.comp.bin_file.options.error_return_tracing and
1947219053 mod.backendSupportsFeature(.error_return_trace))
1947319054 {
......@@ -19920,7 +19501,7 @@ fn zirReify(
1992019501 return sema.addType(Type.anyerror);
1992119502
1992219503 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));
19923 var names: Module.Fn.InferredErrorSet.NameMap = .{};
19504 var names: Module.InferredErrorSet.NameMap = .{};
1992419505 try names.ensureUnusedCapacity(sema.arena, len);
1992519506 for (0..len) |i| {
1992619507 const elem_val = try payload_val.elemValue(mod, i);
......@@ -23917,7 +23498,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2391723498 break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);
2391823499 } else target_util.defaultAddressSpace(target, .function);
2391923500
23920 const @"linksection": FuncLinkSection = if (extra.data.bits.has_section_body) blk: {
23501 const section: InternPool.GetFuncDeclKey.Section = if (extra.data.bits.has_section_body) blk: {
2392123502 const body_len = sema.code.extra[extra_index];
2392223503 extra_index += 1;
2392323504 const body = sema.code.extra[extra_index..][0..body_len];
......@@ -23926,20 +23507,20 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2392623507 const ty = Type.slice_const_u8;
2392723508 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");
2392823509 if (val.isGenericPoison()) {
23929 break :blk FuncLinkSection{ .generic = {} };
23510 break :blk .generic;
2393023511 }
23931 break :blk FuncLinkSection{ .explicit = try val.toIpString(ty, mod) };
23512 break :blk .{ .explicit = try val.toIpString(ty, mod) };
2393223513 } else if (extra.data.bits.has_section_ref) blk: {
2393323514 const section_ref = @as(Zir.Inst.Ref, @enumFromInt(sema.code.extra[extra_index]));
2393423515 extra_index += 1;
2393523516 const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) {
2393623517 error.GenericPoison => {
23937 break :blk FuncLinkSection{ .generic = {} };
23518 break :blk .generic;
2393823519 },
2393923520 else => |e| return e,
2394023521 };
23941 break :blk FuncLinkSection{ .explicit = section_name };
23942 } else FuncLinkSection{ .default = {} };
23522 break :blk .{ .explicit = section_name };
23523 } else .default;
2394323524
2394423525 const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
2394523526 const body_len = sema.code.extra[extra_index];
......@@ -24013,7 +23594,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2401323594 inst,
2401423595 @"align",
2401523596 @"addrspace",
24016 @"linksection",
23597 section,
2401723598 cc,
2401823599 ret_ty,
2401923600 is_var_args,
......@@ -24846,9 +24427,9 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {
2484624427 const tv = try mod.declPtr(decl_index).typedValue();
2484724428 assert(tv.ty.zigTypeTag(mod) == .Fn);
2484824429 assert(try sema.fnHasRuntimeBits(tv.ty));
24849 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap().?;
24430 const func_index = tv.val.toIntern();
2485024431 try mod.ensureFuncBodyAnalysisQueued(func_index);
24851 mod.panic_func_index = func_index.toOptional();
24432 mod.panic_func_index = func_index;
2485224433 }
2485324434
2485424435 if (mod.null_stack_trace == .none) {
......@@ -24982,7 +24563,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, msg_inst: Air.Inst.Ref) !void {
2498224563
2498324564 try sema.prepareSimplePanic(block);
2498424565
24985 const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?;
24566 const panic_func = mod.funcInfo(mod.panic_func_index);
2498624567 const panic_fn = try sema.analyzeDeclVal(block, .unneeded, panic_func.owner_decl);
2498724568 const null_stack_trace = try sema.addConstant(mod.null_stack_trace.toValue());
2498824569
......@@ -25688,7 +25269,7 @@ fn fieldCallBind(
2568825269 if (mod.typeToFunc(decl_type)) |func_type| f: {
2568925270 if (func_type.param_types.len == 0) break :f;
2569025271
25691 const first_param_type = func_type.param_types[0].toType();
25272 const first_param_type = func_type.param_types.get(ip)[0].toType();
2569225273 // zig fmt: off
2569325274 if (first_param_type.isGenericPoison() or (
2569425275 first_param_type.zigTypeTag(mod) == .Pointer and
......@@ -27526,7 +27107,7 @@ fn coerceExtra(
2752627107 errdefer msg.destroy(sema.gpa);
2752727108
2752827109 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
27529 const src_decl = mod.declPtr(sema.func.?.owner_decl);
27110 const src_decl = mod.funcOwnerDeclPtr(sema.func_index);
2753027111 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});
2753127112 break :msg msg;
2753227113 };
......@@ -27556,9 +27137,11 @@ fn coerceExtra(
2755627137 try in_memory_result.report(sema, block, inst_src, msg);
2755727138
2755827139 // Add notes about function return type
27559 if (opts.is_ret and mod.test_functions.get(sema.func.?.owner_decl) == null) {
27140 if (opts.is_ret and
27141 mod.test_functions.get(mod.funcOwnerDeclIndex(sema.func_index)) == null)
27142 {
2756027143 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
27561 const src_decl = mod.declPtr(sema.func.?.owner_decl);
27144 const src_decl = mod.funcOwnerDeclPtr(sema.func_index);
2756227145 if (inst_ty.isError(mod) and !dest_ty.isError(mod)) {
2756327146 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});
2756427147 } else {
......@@ -28185,7 +27768,7 @@ fn coerceInMemoryAllowedErrorSets(
2818527768 },
2818627769 }
2818727770
28188 if (dst_ies.func == sema.owner_func_index.unwrap()) {
27771 if (dst_ies.func == sema.owner_func_index) {
2818927772 // We are trying to coerce an error set to the current function's
2819027773 // inferred error set.
2819127774 try dst_ies.addErrorSet(src_ty, ip, gpa);
......@@ -28264,11 +27847,12 @@ fn coerceInMemoryAllowedFns(
2826427847 src_src: LazySrcLoc,
2826527848) !InMemoryCoercionResult {
2826627849 const mod = sema.mod;
27850 const ip = &mod.intern_pool;
2826727851
28268 {
28269 const dest_info = mod.typeToFunc(dest_ty).?;
28270 const src_info = mod.typeToFunc(src_ty).?;
27852 const dest_info = mod.typeToFunc(dest_ty).?;
27853 const src_info = mod.typeToFunc(src_ty).?;
2827127854
27855 {
2827227856 if (dest_info.is_var_args != src_info.is_var_args) {
2827327857 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
2827427858 }
......@@ -28302,9 +27886,6 @@ fn coerceInMemoryAllowedFns(
2830227886 }
2830327887
2830427888 const params_len = params_len: {
28305 const dest_info = mod.typeToFunc(dest_ty).?;
28306 const src_info = mod.typeToFunc(src_ty).?;
28307
2830827889 if (dest_info.param_types.len != src_info.param_types.len) {
2830927890 return InMemoryCoercionResult{ .fn_param_count = .{
2831027891 .actual = src_info.param_types.len,
......@@ -28323,13 +27904,10 @@ fn coerceInMemoryAllowedFns(
2832327904 };
2832427905
2832527906 for (0..params_len) |param_i| {
28326 const dest_info = mod.typeToFunc(dest_ty).?;
28327 const src_info = mod.typeToFunc(src_ty).?;
28328
28329 const dest_param_ty = dest_info.param_types[param_i].toType();
28330 const src_param_ty = src_info.param_types[param_i].toType();
27907 const dest_param_ty = dest_info.param_types.get(ip)[param_i].toType();
27908 const src_param_ty = src_info.param_types.get(ip)[param_i].toType();
2833127909
28332 const param_i_small = @as(u5, @intCast(param_i));
27910 const param_i_small: u5 = @intCast(param_i);
2833327911 if (dest_info.paramIsComptime(param_i_small) != src_info.paramIsComptime(param_i_small)) {
2833427912 return InMemoryCoercionResult{ .fn_param_comptime = .{
2833527913 .index = param_i,
......@@ -30471,6 +30049,7 @@ fn addReferencedBy(
3047130049
3047230050fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
3047330051 const mod = sema.mod;
30052 const ip = &mod.intern_pool;
3047430053 const decl = mod.declPtr(decl_index);
3047530054 if (decl.analysis == .in_progress) {
3047630055 const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(mod), "dependency loop detected", .{});
......@@ -30478,8 +30057,8 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
3047830057 }
3047930058
3048030059 mod.ensureDeclAnalyzed(decl_index) catch |err| {
30481 if (sema.owner_func) |owner_func| {
30482 owner_func.state = .dependency_failure;
30060 if (sema.owner_func_index != .none) {
30061 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
3048330062 } else {
3048430063 sema.owner_decl.analysis = .dependency_failure;
3048530064 }
......@@ -30487,10 +30066,12 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
3048730066 };
3048830067}
3048930068
30490fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void {
30491 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
30492 if (sema.owner_func) |owner_func| {
30493 owner_func.state = .dependency_failure;
30069fn ensureFuncBodyAnalyzed(sema: *Sema, func: InternPool.Index) CompileError!void {
30070 const mod = sema.mod;
30071 const ip = &mod.intern_pool;
30072 mod.ensureFuncBodyAnalyzed(func) catch |err| {
30073 if (sema.owner_func_index != .none) {
30074 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
3049430075 } else {
3049530076 sema.owner_decl.analysis = .dependency_failure;
3049630077 }
......@@ -30566,7 +30147,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {
3056630147 const tv = try decl.typedValue();
3056730148 if (tv.ty.zigTypeTag(mod) != .Fn) return;
3056830149 if (!try sema.fnHasRuntimeBits(tv.ty)) return;
30569 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn
30150 const func_index = tv.val.toIntern();
30151 if (!mod.intern_pool.isFuncBody(func_index)) return; // undef or extern function
3057030152 try mod.ensureFuncBodyAnalysisQueued(func_index);
3057130153}
3057230154
......@@ -30582,7 +30164,7 @@ fn analyzeRef(
3058230164 if (try sema.resolveMaybeUndefVal(operand)) |val| {
3058330165 switch (mod.intern_pool.indexToKey(val.toIntern())) {
3058430166 .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),
30585 .func => |func| return sema.analyzeDeclRef(mod.funcPtr(func.index).owner_decl),
30167 .func => |func| return sema.analyzeDeclRef(func.owner_decl),
3058630168 else => {},
3058730169 }
3058830170 var anon_decl = try block.startAnonDecl();
......@@ -30810,7 +30392,7 @@ fn analyzeIsNonErrComptimeOnly(
3081030392
3081130393 if (other_ies.errors.count() != 0) break :blk;
3081230394 }
30813 if (ies.func == sema.owner_func_index.unwrap()) {
30395 if (ies.func == sema.owner_func_index) {
3081430396 // We're checking the inferred errorset of the current function and none of
3081530397 // its child inferred error sets contained any errors meaning that any value
3081630398 // so far with this type can't contain errors either.
......@@ -33275,15 +32857,17 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike {
3327532857
3327632858pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
3327732859 const mod = sema.mod;
33278 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.return_type.toType());
32860 const ip = &mod.intern_pool;
32861 const fn_ty_info = mod.typeToFunc(fn_ty).?;
32862 try sema.resolveTypeFully(fn_ty_info.return_type.toType());
3327932863
33280 if (mod.comp.bin_file.options.error_return_tracing and mod.typeToFunc(fn_ty).?.return_type.toType().isError(mod)) {
32864 if (mod.comp.bin_file.options.error_return_tracing and fn_ty_info.return_type.toType().isError(mod)) {
3328132865 // Ensure the type exists so that backends can assume that.
3328232866 _ = try sema.getBuiltinType("StackTrace");
3328332867 }
3328432868
33285 for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| {
33286 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType());
32869 for (0..fn_ty_info.param_types.len) |i| {
32870 try sema.resolveTypeFully(fn_ty_info.param_types.get(ip)[i].toType());
3328732871 }
3328832872}
3328932873
......@@ -33448,7 +33032,9 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
3344833032 // the function is instantiated.
3344933033 return;
3345033034 }
33451 for (info.param_types) |param_ty| {
33035 const ip = &mod.intern_pool;
33036 for (0..info.param_types.len) |i| {
33037 const param_ty = info.param_types.get(ip)[i];
3345233038 try sema.resolveTypeLayout(param_ty.toType());
3345333039 }
3345433040 try sema.resolveTypeLayout(info.return_type.toType());
......@@ -33578,10 +33164,8 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3357833164 .code = zir,
3357933165 .owner_decl = decl,
3358033166 .owner_decl_index = decl_index,
33581 .func = null,
3358233167 .func_index = .none,
3358333168 .fn_ret_ty = Type.void,
33584 .owner_func = null,
3358533169 .owner_func_index = .none,
3358633170 .comptime_mutable_decls = &comptime_mutable_decls,
3358733171 };
......@@ -33600,10 +33184,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3360033184 .inlining = null,
3360133185 .is_comptime = true,
3360233186 };
33603 defer {
33604 assert(block.instructions.items.len == 0);
33605 block.params.deinit(gpa);
33606 }
33187 defer assert(block.instructions.items.len == 0);
3360733188
3360833189 const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 };
3360933190 const backing_int_ty = blk: {
......@@ -33633,10 +33214,8 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3363333214 .code = zir,
3363433215 .owner_decl = decl,
3363533216 .owner_decl_index = decl_index,
33636 .func = null,
3363733217 .func_index = .none,
3363833218 .fn_ret_ty = Type.void,
33639 .owner_func = null,
3364033219 .owner_func_index = .none,
3364133220 .comptime_mutable_decls = undefined,
3364233221 };
......@@ -33943,7 +33522,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
3394333522 // the function is instantiated.
3394433523 return;
3394533524 }
33946 for (info.param_types) |param_ty| {
33525 const ip = &mod.intern_pool;
33526 for (0..info.param_types.len) |i| {
33527 const param_ty = info.param_types.get(ip)[i];
3394733528 try sema.resolveTypeFully(param_ty.toType());
3394833529 }
3394933530 try sema.resolveTypeFully(info.return_type.toType());
......@@ -34213,15 +33794,16 @@ fn resolveInferredErrorSet(
3421333794 sema: *Sema,
3421433795 block: *Block,
3421533796 src: LazySrcLoc,
34216 ies_index: Module.Fn.InferredErrorSet.Index,
33797 ies_index: Module.InferredErrorSet.Index,
3421733798) CompileError!void {
3421833799 const mod = sema.mod;
33800 const ip = &mod.intern_pool;
3421933801 const ies = mod.inferredErrorSetPtr(ies_index);
3422033802
3422133803 if (ies.is_resolved) return;
3422233804
34223 const func = mod.funcPtr(ies.func);
34224 if (func.state == .in_progress) {
33805 const func = mod.funcInfo(ies.func);
33806 if (func.analysis(ip).state == .in_progress) {
3422533807 return sema.fail(block, src, "unable to resolve inferred error set", .{});
3422633808 }
3422733809
......@@ -34229,7 +33811,7 @@ fn resolveInferredErrorSet(
3422933811 // need to ensure the function body is analyzed of the inferred error set.
3423033812 // However, in the case of comptime/inline function calls with inferred error sets,
3423133813 // each call gets a new InferredErrorSet object, which contains the same
34232 // `Module.Fn.Index`. Not only is the function not relevant to the inferred error set
33814 // `InternPool.Index`. Not only is the function not relevant to the inferred error set
3423333815 // in this case, it may be a generic function which would cause an assertion failure
3423433816 // if we called `ensureFuncBodyAnalyzed` on it here.
3423533817 const ies_func_owner_decl = mod.declPtr(func.owner_decl);
......@@ -34346,10 +33928,8 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3434633928 .code = zir,
3434733929 .owner_decl = decl,
3434833930 .owner_decl_index = decl_index,
34349 .func = null,
3435033931 .func_index = .none,
3435133932 .fn_ret_ty = Type.void,
34352 .owner_func = null,
3435333933 .owner_func_index = .none,
3435433934 .comptime_mutable_decls = &comptime_mutable_decls,
3435533935 };
......@@ -34693,10 +34273,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3469334273 .code = zir,
3469434274 .owner_decl = decl,
3469534275 .owner_decl_index = decl_index,
34696 .func = null,
3469734276 .func_index = .none,
3469834277 .fn_ret_ty = Type.void,
34699 .owner_func = null,
3470034278 .owner_func_index = .none,
3470134279 .comptime_mutable_decls = &comptime_mutable_decls,
3470234280 };
......@@ -35148,10 +34726,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
3514834726 .inlining = null,
3514934727 .is_comptime = true,
3515034728 };
35151 defer {
35152 block.instructions.deinit(gpa);
35153 block.params.deinit(gpa);
35154 }
34729 defer block.instructions.deinit(gpa);
3515534730
3515634731 const decl_index = try getBuiltinDecl(sema, &block, name);
3515734732 return sema.analyzeDeclVal(&block, src, decl_index);
......@@ -35202,10 +34777,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
3520234777 .inlining = null,
3520334778 .is_comptime = true,
3520434779 };
35205 defer {
35206 block.instructions.deinit(sema.gpa);
35207 block.params.deinit(sema.gpa);
35208 }
34780 defer block.instructions.deinit(sema.gpa);
3520934781 const src = LazySrcLoc.nodeOffset(0);
3521034782
3521134783 const result_ty = sema.analyzeAsType(&block, src, ty_inst) catch |err| switch (err) {
......@@ -35327,6 +34899,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3532734899 .type_opaque,
3532834900 .type_function,
3532934901 => null,
34902
3533034903 .simple_type, // handled above
3533134904 // values, not types
3533234905 .undef,
......@@ -35370,7 +34943,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3537034943 .float_comptime_float,
3537134944 .variable,
3537234945 .extern_func,
35373 .func,
34946 .func_decl,
34947 .func_instance,
3537434948 .only_possible_value,
3537534949 .union_value,
3537634950 .bytes,
......@@ -35379,6 +34953,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3537934953 // memoized value, not types
3538034954 .memoized_call,
3538134955 => unreachable,
34956
3538234957 .type_array_big,
3538334958 .type_array_small,
3538434959 .type_vector,
......@@ -36772,7 +36347,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {
3677236347 const arena = sema.arena;
3677336348 const lhs_names = lhs.errorSetNames(mod);
3677436349 const rhs_names = rhs.errorSetNames(mod);
36775 var names: Module.Fn.InferredErrorSet.NameMap = .{};
36350 var names: Module.InferredErrorSet.NameMap = .{};
3677636351 try names.ensureUnusedCapacity(arena, lhs_names.len);
3677736352
3677836353 for (lhs_names) |name| {
src/TypedValue.zig+1-1
......@@ -205,7 +205,7 @@ pub fn print(
205205 mod.declPtr(extern_func.decl).name.fmt(ip),
206206 }),
207207 .func => |func| return writer.print("(function '{}')", .{
208 mod.declPtr(mod.funcPtr(func.index).owner_decl).name.fmt(ip),
208 mod.declPtr(func.owner_decl).name.fmt(ip),
209209 }),
210210 .int => |int| switch (int.storage) {
211211 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
src/Zir.zig+14-3
......@@ -90,13 +90,24 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
9090 };
9191}
9292
93/// Given an index into `string_bytes` returns the null-terminated string found there.
93/// TODO migrate to use this for type safety
94pub const NullTerminatedString = enum(u32) {
95 _,
96};
97
98/// TODO: migrate to nullTerminatedString2 for type safety
9499pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {
95 var end: usize = index;
100 return nullTerminatedString2(code, @enumFromInt(index));
101}
102
103/// Given an index into `string_bytes` returns the null-terminated string found there.
104pub fn nullTerminatedString2(code: Zir, index: NullTerminatedString) [:0]const u8 {
105 const start = @intFromEnum(index);
106 var end: u32 = start;
96107 while (code.string_bytes[end] != 0) {
97108 end += 1;
98109 }
99 return code.string_bytes[index..end :0];
110 return code.string_bytes[start..end :0];
100111}
101112
102113pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {
src/arch/aarch64/CodeGen.zig+36-31
......@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
1313const TypedValue = @import("../../TypedValue.zig");
1414const link = @import("../../link.zig");
1515const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");
1617const Compilation = @import("../../Compilation.zig");
1718const ErrorMsg = Module.ErrorMsg;
1819const Target = std.Target;
......@@ -49,7 +50,8 @@ liveness: Liveness,
4950bin_file: *link.File,
5051debug_output: DebugInfoOutput,
5152target: *const std.Target,
52mod_fn: *const Module.Fn,
53func_index: InternPool.Index,
54owner_decl: Module.Decl.Index,
5355err_msg: ?*ErrorMsg,
5456args: []MCValue,
5557ret_mcv: MCValue,
......@@ -199,7 +201,7 @@ const DbgInfoReloc = struct {
199201 else => unreachable, // not a possible argument
200202
201203 };
202 try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc);
204 try dw.genArgDbgInfo(reloc.name, reloc.ty, function.owner_decl, loc);
203205 },
204206 .plan9 => {},
205207 .none => {},
......@@ -245,7 +247,7 @@ const DbgInfoReloc = struct {
245247 break :blk .nop;
246248 },
247249 };
248 try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc);
250 try dw.genVarDbgInfo(reloc.name, reloc.ty, function.owner_decl, is_ptr, loc);
249251 },
250252 .plan9 => {},
251253 .none => {},
......@@ -328,7 +330,7 @@ const Self = @This();
328330pub fn generate(
329331 bin_file: *link.File,
330332 src_loc: Module.SrcLoc,
331 module_fn_index: Module.Fn.Index,
333 func_index: InternPool.Index,
332334 air: Air,
333335 liveness: Liveness,
334336 code: *std.ArrayList(u8),
......@@ -339,8 +341,8 @@ pub fn generate(
339341 }
340342
341343 const mod = bin_file.options.module.?;
342 const module_fn = mod.funcPtr(module_fn_index);
343 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
344 const func = mod.funcInfo(func_index);
345 const fn_owner_decl = mod.declPtr(func.owner_decl);
344346 assert(fn_owner_decl.has_tv);
345347 const fn_type = fn_owner_decl.ty;
346348
......@@ -359,7 +361,8 @@ pub fn generate(
359361 .debug_output = debug_output,
360362 .target = &bin_file.options.target,
361363 .bin_file = bin_file,
362 .mod_fn = module_fn,
364 .func_index = func_index,
365 .owner_decl = func.owner_decl,
363366 .err_msg = null,
364367 .args = undefined, // populated after `resolveCallingConventionValues`
365368 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
......@@ -368,8 +371,8 @@ pub fn generate(
368371 .branch_stack = &branch_stack,
369372 .src_loc = src_loc,
370373 .stack_align = undefined,
371 .end_di_line = module_fn.rbrace_line,
372 .end_di_column = module_fn.rbrace_column,
374 .end_di_line = func.rbrace_line,
375 .end_di_column = func.rbrace_column,
373376 };
374377 defer function.stack.deinit(bin_file.allocator);
375378 defer function.blocks.deinit(bin_file.allocator);
......@@ -416,8 +419,8 @@ pub fn generate(
416419 .src_loc = src_loc,
417420 .code = code,
418421 .prev_di_pc = 0,
419 .prev_di_line = module_fn.lbrace_line,
420 .prev_di_column = module_fn.lbrace_column,
422 .prev_di_line = func.lbrace_line,
423 .prev_di_column = func.lbrace_column,
421424 .stack_size = function.max_end_stack,
422425 .saved_regs_stack_space = function.saved_regs_stack_space,
423426 };
......@@ -4011,12 +4014,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
40114014 const atom_index = switch (self.bin_file.tag) {
40124015 .macho => blk: {
40134016 const macho_file = self.bin_file.cast(link.File.MachO).?;
4014 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4017 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
40154018 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
40164019 },
40174020 .coff => blk: {
40184021 const coff_file = self.bin_file.cast(link.File.Coff).?;
4019 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4022 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
40204023 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
40214024 },
40224025 else => unreachable, // unsupported target format
......@@ -4190,10 +4193,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
41904193 while (self.args[arg_index] == .none) arg_index += 1;
41914194 self.arg_index = arg_index + 1;
41924195
4196 const mod = self.bin_file.options.module.?;
41934197 const ty = self.typeOfIndex(inst);
41944198 const tag = self.air.instructions.items(.tag)[inst];
41954199 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4196 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
4200 const name = mod.getParamName(self.func_index, src_index);
41974201
41984202 try self.dbg_info_relocs.append(self.gpa, .{
41994203 .tag = tag,
......@@ -4348,7 +4352,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43484352 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
43494353 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
43504354 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
4351 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4355 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
43524356 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
43534357 _ = try self.addInst(.{
43544358 .tag = .call_extern,
......@@ -4617,9 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
46174621fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
46184622 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
46194623 const mod = self.bin_file.options.module.?;
4620 const function = mod.funcPtr(ty_fn.func);
4624 const func = mod.funcInfo(ty_fn.func);
46214625 // TODO emit debug info for function change
4622 _ = function;
4626 _ = func;
46234627 return self.finishAir(inst, .dead, .{ .none, .none, .none });
46244628}
46254629
......@@ -5529,12 +5533,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
55295533 const atom_index = switch (self.bin_file.tag) {
55305534 .macho => blk: {
55315535 const macho_file = self.bin_file.cast(link.File.MachO).?;
5532 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5536 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
55335537 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
55345538 },
55355539 .coff => blk: {
55365540 const coff_file = self.bin_file.cast(link.File.Coff).?;
5537 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5541 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
55385542 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
55395543 },
55405544 else => unreachable, // unsupported target format
......@@ -5650,12 +5654,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56505654 const atom_index = switch (self.bin_file.tag) {
56515655 .macho => blk: {
56525656 const macho_file = self.bin_file.cast(link.File.MachO).?;
5653 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5657 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
56545658 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
56555659 },
56565660 .coff => blk: {
56575661 const coff_file = self.bin_file.cast(link.File.Coff).?;
5658 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5662 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
56595663 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
56605664 },
56615665 else => unreachable, // unsupported target format
......@@ -5847,12 +5851,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
58475851 const atom_index = switch (self.bin_file.tag) {
58485852 .macho => blk: {
58495853 const macho_file = self.bin_file.cast(link.File.MachO).?;
5850 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5854 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
58515855 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
58525856 },
58535857 .coff => blk: {
58545858 const coff_file = self.bin_file.cast(link.File.Coff).?;
5855 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5859 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
58565860 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
58575861 },
58585862 else => unreachable, // unsupported target format
......@@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
61646168 self.bin_file,
61656169 self.src_loc,
61666170 arg_tv,
6167 self.mod_fn.owner_decl,
6171 self.owner_decl,
61686172 )) {
61696173 .mcv => |mcv| switch (mcv) {
61706174 .none => .none,
......@@ -6198,6 +6202,7 @@ const CallMCValues = struct {
61986202/// Caller must call `CallMCValues.deinit`.
61996203fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62006204 const mod = self.bin_file.options.module.?;
6205 const ip = &mod.intern_pool;
62016206 const fn_info = mod.typeToFunc(fn_ty).?;
62026207 const cc = fn_info.cc;
62036208 var result: CallMCValues = .{
......@@ -6240,10 +6245,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62406245 }
62416246 }
62426247
6243 for (fn_info.param_types, 0..) |ty, i| {
6248 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
62446249 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
62456250 if (param_size == 0) {
6246 result.args[i] = .{ .none = {} };
6251 result_arg.* = .{ .none = {} };
62476252 continue;
62486253 }
62496254
......@@ -6256,7 +6261,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62566261
62576262 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
62586263 if (param_size <= 8) {
6259 result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };
6264 result_arg.* = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };
62606265 ncrn += 1;
62616266 } else {
62626267 return self.fail("TODO MCValues with multiple registers", .{});
......@@ -6273,7 +6278,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62736278 }
62746279 }
62756280
6276 result.args[i] = .{ .stack_argument_offset = nsaa };
6281 result_arg.* = .{ .stack_argument_offset = nsaa };
62776282 nsaa += param_size;
62786283 }
62796284 }
......@@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
63056310
63066311 var stack_offset: u32 = 0;
63076312
6308 for (fn_info.param_types, 0..) |ty, i| {
6313 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
63096314 if (ty.toType().abiSize(mod) > 0) {
63106315 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
63116316 const param_alignment = ty.toType().abiAlignment(mod);
63126317
63136318 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
6314 result.args[i] = .{ .stack_argument_offset = stack_offset };
6319 result_arg.* = .{ .stack_argument_offset = stack_offset };
63156320 stack_offset += param_size;
63166321 } else {
6317 result.args[i] = .{ .none = {} };
6322 result_arg.* = .{ .none = {} };
63186323 }
63196324 }
63206325
src/arch/arm/CodeGen.zig+27-21
......@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
1313const TypedValue = @import("../../TypedValue.zig");
1414const link = @import("../../link.zig");
1515const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");
1617const Compilation = @import("../../Compilation.zig");
1718const ErrorMsg = Module.ErrorMsg;
1819const Target = std.Target;
......@@ -50,7 +51,7 @@ liveness: Liveness,
5051bin_file: *link.File,
5152debug_output: DebugInfoOutput,
5253target: *const std.Target,
53mod_fn: *const Module.Fn,
54func_index: InternPool.Index,
5455err_msg: ?*ErrorMsg,
5556args: []MCValue,
5657ret_mcv: MCValue,
......@@ -258,6 +259,7 @@ const DbgInfoReloc = struct {
258259 }
259260
260261 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
262 const mod = function.bin_file.options.module.?;
261263 switch (function.debug_output) {
262264 .dwarf => |dw| {
263265 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {
......@@ -278,7 +280,7 @@ const DbgInfoReloc = struct {
278280 else => unreachable, // not a possible argument
279281 };
280282
281 try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc);
283 try dw.genArgDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), loc);
282284 },
283285 .plan9 => {},
284286 .none => {},
......@@ -286,6 +288,7 @@ const DbgInfoReloc = struct {
286288 }
287289
288290 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
291 const mod = function.bin_file.options.module.?;
289292 const is_ptr = switch (reloc.tag) {
290293 .dbg_var_ptr => true,
291294 .dbg_var_val => false,
......@@ -321,7 +324,7 @@ const DbgInfoReloc = struct {
321324 break :blk .nop;
322325 },
323326 };
324 try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc);
327 try dw.genVarDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), is_ptr, loc);
325328 },
326329 .plan9 => {},
327330 .none => {},
......@@ -334,7 +337,7 @@ const Self = @This();
334337pub fn generate(
335338 bin_file: *link.File,
336339 src_loc: Module.SrcLoc,
337 module_fn_index: Module.Fn.Index,
340 func_index: InternPool.Index,
338341 air: Air,
339342 liveness: Liveness,
340343 code: *std.ArrayList(u8),
......@@ -345,8 +348,8 @@ pub fn generate(
345348 }
346349
347350 const mod = bin_file.options.module.?;
348 const module_fn = mod.funcPtr(module_fn_index);
349 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
351 const func = mod.funcInfo(func_index);
352 const fn_owner_decl = mod.declPtr(func.owner_decl);
350353 assert(fn_owner_decl.has_tv);
351354 const fn_type = fn_owner_decl.ty;
352355
......@@ -365,7 +368,7 @@ pub fn generate(
365368 .target = &bin_file.options.target,
366369 .bin_file = bin_file,
367370 .debug_output = debug_output,
368 .mod_fn = module_fn,
371 .func_index = func_index,
369372 .err_msg = null,
370373 .args = undefined, // populated after `resolveCallingConventionValues`
371374 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
......@@ -374,8 +377,8 @@ pub fn generate(
374377 .branch_stack = &branch_stack,
375378 .src_loc = src_loc,
376379 .stack_align = undefined,
377 .end_di_line = module_fn.rbrace_line,
378 .end_di_column = module_fn.rbrace_column,
380 .end_di_line = func.rbrace_line,
381 .end_di_column = func.rbrace_column,
379382 };
380383 defer function.stack.deinit(bin_file.allocator);
381384 defer function.blocks.deinit(bin_file.allocator);
......@@ -422,8 +425,8 @@ pub fn generate(
422425 .src_loc = src_loc,
423426 .code = code,
424427 .prev_di_pc = 0,
425 .prev_di_line = module_fn.lbrace_line,
426 .prev_di_column = module_fn.lbrace_column,
428 .prev_di_line = func.lbrace_line,
429 .prev_di_column = func.lbrace_column,
427430 .stack_size = function.max_end_stack,
428431 .saved_regs_stack_space = function.saved_regs_stack_space,
429432 };
......@@ -4163,10 +4166,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
41634166 while (self.args[arg_index] == .none) arg_index += 1;
41644167 self.arg_index = arg_index + 1;
41654168
4169 const mod = self.bin_file.options.module.?;
41664170 const ty = self.typeOfIndex(inst);
41674171 const tag = self.air.instructions.items(.tag)[inst];
41684172 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4169 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
4173 const name = mod.getParamName(self.func_index, src_index);
41704174
41714175 try self.dbg_info_relocs.append(self.gpa, .{
41724176 .tag = tag,
......@@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
45694573fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
45704574 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
45714575 const mod = self.bin_file.options.module.?;
4572 const function = mod.funcPtr(ty_fn.func);
4576 const func = mod.funcInfo(ty_fn.func);
45734577 // TODO emit debug info for function change
4574 _ = function;
4578 _ = func;
45754579 return self.finishAir(inst, .dead, .{ .none, .none, .none });
45764580}
45774581
......@@ -6113,11 +6117,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
61136117}
61146118
61156119fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6120 const mod = self.bin_file.options.module.?;
61166121 const mcv: MCValue = switch (try codegen.genTypedValue(
61176122 self.bin_file,
61186123 self.src_loc,
61196124 arg_tv,
6120 self.mod_fn.owner_decl,
6125 mod.funcOwnerDeclIndex(self.func_index),
61216126 )) {
61226127 .mcv => |mcv| switch (mcv) {
61236128 .none => .none,
......@@ -6149,6 +6154,7 @@ const CallMCValues = struct {
61496154/// Caller must call `CallMCValues.deinit`.
61506155fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
61516156 const mod = self.bin_file.options.module.?;
6157 const ip = &mod.intern_pool;
61526158 const fn_info = mod.typeToFunc(fn_ty).?;
61536159 const cc = fn_info.cc;
61546160 var result: CallMCValues = .{
......@@ -6194,14 +6200,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
61946200 }
61956201 }
61966202
6197 for (fn_info.param_types, 0..) |ty, i| {
6203 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
61986204 if (ty.toType().abiAlignment(mod) == 8)
61996205 ncrn = std.mem.alignForward(usize, ncrn, 2);
62006206
62016207 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
62026208 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
62036209 if (param_size <= 4) {
6204 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };
6210 result_arg.* = .{ .register = c_abi_int_param_regs[ncrn] };
62056211 ncrn += 1;
62066212 } else {
62076213 return self.fail("TODO MCValues with multiple registers", .{});
......@@ -6213,7 +6219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62136219 if (ty.toType().abiAlignment(mod) == 8)
62146220 nsaa = std.mem.alignForward(u32, nsaa, 8);
62156221
6216 result.args[i] = .{ .stack_argument_offset = nsaa };
6222 result_arg.* = .{ .stack_argument_offset = nsaa };
62176223 nsaa += param_size;
62186224 }
62196225 }
......@@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62446250
62456251 var stack_offset: u32 = 0;
62466252
6247 for (fn_info.param_types, 0..) |ty, i| {
6253 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
62486254 if (ty.toType().abiSize(mod) > 0) {
62496255 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
62506256 const param_alignment = ty.toType().abiAlignment(mod);
62516257
62526258 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
6253 result.args[i] = .{ .stack_argument_offset = stack_offset };
6259 result_arg.* = .{ .stack_argument_offset = stack_offset };
62546260 stack_offset += param_size;
62556261 } else {
6256 result.args[i] = .{ .none = {} };
6262 result_arg.* = .{ .none = {} };
62576263 }
62586264 }
62596265
src/arch/riscv64/CodeGen.zig+46-37
......@@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value;
1212const TypedValue = @import("../../TypedValue.zig");
1313const link = @import("../../link.zig");
1414const Module = @import("../../Module.zig");
15const InternPool = @import("../../InternPool.zig");
1516const Compilation = @import("../../Compilation.zig");
1617const ErrorMsg = Module.ErrorMsg;
1718const Target = std.Target;
......@@ -43,7 +44,7 @@ air: Air,
4344liveness: Liveness,
4445bin_file: *link.File,
4546target: *const std.Target,
46mod_fn: *const Module.Fn,
47func_index: InternPool.Index,
4748code: *std.ArrayList(u8),
4849debug_output: DebugInfoOutput,
4950err_msg: ?*ErrorMsg,
......@@ -217,7 +218,7 @@ const Self = @This();
217218pub fn generate(
218219 bin_file: *link.File,
219220 src_loc: Module.SrcLoc,
220 module_fn_index: Module.Fn.Index,
221 func_index: InternPool.Index,
221222 air: Air,
222223 liveness: Liveness,
223224 code: *std.ArrayList(u8),
......@@ -228,8 +229,8 @@ pub fn generate(
228229 }
229230
230231 const mod = bin_file.options.module.?;
231 const module_fn = mod.funcPtr(module_fn_index);
232 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
232 const func = mod.funcInfo(func_index);
233 const fn_owner_decl = mod.declPtr(func.owner_decl);
233234 assert(fn_owner_decl.has_tv);
234235 const fn_type = fn_owner_decl.ty;
235236
......@@ -247,7 +248,7 @@ pub fn generate(
247248 .liveness = liveness,
248249 .target = &bin_file.options.target,
249250 .bin_file = bin_file,
250 .mod_fn = module_fn,
251 .func_index = func_index,
251252 .code = code,
252253 .debug_output = debug_output,
253254 .err_msg = null,
......@@ -258,8 +259,8 @@ pub fn generate(
258259 .branch_stack = &branch_stack,
259260 .src_loc = src_loc,
260261 .stack_align = undefined,
261 .end_di_line = module_fn.rbrace_line,
262 .end_di_column = module_fn.rbrace_column,
262 .end_di_line = func.rbrace_line,
263 .end_di_column = func.rbrace_column,
263264 };
264265 defer function.stack.deinit(bin_file.allocator);
265266 defer function.blocks.deinit(bin_file.allocator);
......@@ -301,8 +302,8 @@ pub fn generate(
301302 .src_loc = src_loc,
302303 .code = code,
303304 .prev_di_pc = 0,
304 .prev_di_line = module_fn.lbrace_line,
305 .prev_di_column = module_fn.lbrace_column,
305 .prev_di_line = func.lbrace_line,
306 .prev_di_column = func.lbrace_column,
306307 };
307308 defer emit.deinit();
308309
......@@ -1627,13 +1628,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
16271628}
16281629
16291630fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
1631 const mod = self.bin_file.options.module.?;
16301632 const arg = self.air.instructions.items(.data)[inst].arg;
16311633 const ty = self.air.getRefType(arg.ty);
1632 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
1634 const owner_decl = mod.funcOwnerDeclIndex(self.func_index);
1635 const name = mod.getParamName(self.func_index, arg.src_index);
16331636
16341637 switch (self.debug_output) {
16351638 .dwarf => |dw| switch (mcv) {
1636 .register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{
1639 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
16371640 .register = reg.dwarfLocOp(),
16381641 }),
16391642 .stack_offset => {},
......@@ -1742,24 +1745,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
17421745 }
17431746
17441747 if (try self.air.value(callee, mod)) |func_value| {
1745 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
1746 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1747 const atom = elf_file.getAtom(atom_index);
1748 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1749 const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1750 try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
1751 _ = try self.addInst(.{
1752 .tag = .jalr,
1753 .data = .{ .i_type = .{
1754 .rd = .ra,
1755 .rs1 = .ra,
1756 .imm12 = 0,
1757 } },
1758 });
1759 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
1760 return self.fail("TODO implement calling extern functions", .{});
1761 } else {
1762 return self.fail("TODO implement calling bitcasted functions", .{});
1748 switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
1749 .func => |func| {
1750 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1751 const atom = elf_file.getAtom(atom_index);
1752 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1753 const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1754 try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
1755 _ = try self.addInst(.{
1756 .tag = .jalr,
1757 .data = .{ .i_type = .{
1758 .rd = .ra,
1759 .rs1 = .ra,
1760 .imm12 = 0,
1761 } },
1762 });
1763 },
1764 .extern_func => {
1765 return self.fail("TODO implement calling extern functions", .{});
1766 },
1767 else => {
1768 return self.fail("TODO implement calling bitcasted functions", .{});
1769 },
17631770 }
17641771 } else {
17651772 return self.fail("TODO implement calling runtime-known function pointer", .{});
......@@ -1876,9 +1883,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
18761883fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
18771884 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
18781885 const mod = self.bin_file.options.module.?;
1879 const function = mod.funcPtr(ty_fn.func);
1886 const func = mod.funcInfo(ty_fn.func);
18801887 // TODO emit debug info for function change
1881 _ = function;
1888 _ = func;
18821889 return self.finishAir(inst, .dead, .{ .none, .none, .none });
18831890}
18841891
......@@ -2569,11 +2576,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
25692576}
25702577
25712578fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
2579 const mod = self.bin_file.options.module.?;
25722580 const mcv: MCValue = switch (try codegen.genTypedValue(
25732581 self.bin_file,
25742582 self.src_loc,
25752583 typed_value,
2576 self.mod_fn.owner_decl,
2584 mod.funcOwnerDeclIndex(self.func_index),
25772585 )) {
25782586 .mcv => |mcv| switch (mcv) {
25792587 .none => .none,
......@@ -2605,6 +2613,7 @@ const CallMCValues = struct {
26052613/// Caller must call `CallMCValues.deinit`.
26062614fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26072615 const mod = self.bin_file.options.module.?;
2616 const ip = &mod.intern_pool;
26082617 const fn_info = mod.typeToFunc(fn_ty).?;
26092618 const cc = fn_info.cc;
26102619 var result: CallMCValues = .{
......@@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26362645 var next_stack_offset: u32 = 0;
26372646 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
26382647
2639 for (fn_info.param_types, 0..) |ty, i| {
2648 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
26402649 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
26412650 if (param_size <= 8) {
26422651 if (next_register < argument_registers.len) {
2643 result.args[i] = .{ .register = argument_registers[next_register] };
2652 result_arg.* = .{ .register = argument_registers[next_register] };
26442653 next_register += 1;
26452654 } else {
2646 result.args[i] = .{ .stack_offset = next_stack_offset };
2655 result_arg.* = .{ .stack_offset = next_stack_offset };
26472656 next_register += next_stack_offset;
26482657 }
26492658 } else if (param_size <= 16) {
......@@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26522661 } else if (next_register < argument_registers.len) {
26532662 return self.fail("TODO MCValues split register + stack", .{});
26542663 } else {
2655 result.args[i] = .{ .stack_offset = next_stack_offset };
2664 result_arg.* = .{ .stack_offset = next_stack_offset };
26562665 next_register += next_stack_offset;
26572666 }
26582667 } else {
2659 result.args[i] = .{ .stack_offset = next_stack_offset };
2668 result_arg.* = .{ .stack_offset = next_stack_offset };
26602669 next_register += next_stack_offset;
26612670 }
26622671 }
src/arch/sparc64/CodeGen.zig+55-46
......@@ -11,6 +11,7 @@ const Allocator = mem.Allocator;
1111const builtin = @import("builtin");
1212const link = @import("../../link.zig");
1313const Module = @import("../../Module.zig");
14const InternPool = @import("../../InternPool.zig");
1415const TypedValue = @import("../../TypedValue.zig");
1516const ErrorMsg = Module.ErrorMsg;
1617const codegen = @import("../../codegen.zig");
......@@ -52,7 +53,7 @@ air: Air,
5253liveness: Liveness,
5354bin_file: *link.File,
5455target: *const std.Target,
55mod_fn: *const Module.Fn,
56func_index: InternPool.Index,
5657code: *std.ArrayList(u8),
5758debug_output: DebugInfoOutput,
5859err_msg: ?*ErrorMsg,
......@@ -260,7 +261,7 @@ const BigTomb = struct {
260261pub fn generate(
261262 bin_file: *link.File,
262263 src_loc: Module.SrcLoc,
263 module_fn_index: Module.Fn.Index,
264 func_index: InternPool.Index,
264265 air: Air,
265266 liveness: Liveness,
266267 code: *std.ArrayList(u8),
......@@ -271,8 +272,8 @@ pub fn generate(
271272 }
272273
273274 const mod = bin_file.options.module.?;
274 const module_fn = mod.funcPtr(module_fn_index);
275 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
275 const func = mod.funcInfo(func_index);
276 const fn_owner_decl = mod.declPtr(func.owner_decl);
276277 assert(fn_owner_decl.has_tv);
277278 const fn_type = fn_owner_decl.ty;
278279
......@@ -289,8 +290,8 @@ pub fn generate(
289290 .air = air,
290291 .liveness = liveness,
291292 .target = &bin_file.options.target,
293 .func_index = func_index,
292294 .bin_file = bin_file,
293 .mod_fn = module_fn,
294295 .code = code,
295296 .debug_output = debug_output,
296297 .err_msg = null,
......@@ -301,8 +302,8 @@ pub fn generate(
301302 .branch_stack = &branch_stack,
302303 .src_loc = src_loc,
303304 .stack_align = undefined,
304 .end_di_line = module_fn.rbrace_line,
305 .end_di_column = module_fn.rbrace_column,
305 .end_di_line = func.rbrace_line,
306 .end_di_column = func.rbrace_column,
306307 };
307308 defer function.stack.deinit(bin_file.allocator);
308309 defer function.blocks.deinit(bin_file.allocator);
......@@ -344,8 +345,8 @@ pub fn generate(
344345 .src_loc = src_loc,
345346 .code = code,
346347 .prev_di_pc = 0,
347 .prev_di_line = module_fn.lbrace_line,
348 .prev_di_column = module_fn.lbrace_column,
348 .prev_di_line = func.lbrace_line,
349 .prev_di_column = func.lbrace_column,
349350 };
350351 defer emit.deinit();
351352
......@@ -1345,37 +1346,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13451346 // on linking.
13461347 if (try self.air.value(callee, mod)) |func_value| {
13471348 if (self.bin_file.tag == link.File.Elf.base_tag) {
1348 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
1349 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1350 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1351 const atom = elf_file.getAtom(atom_index);
1352 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1353 break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1354 } else unreachable;
1349 switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
1350 .func => |func| {
1351 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1352 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1353 const atom = elf_file.getAtom(atom_index);
1354 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1355 break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1356 } else unreachable;
13551357
1356 try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });
1358 try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });
13571359
1358 _ = try self.addInst(.{
1359 .tag = .jmpl,
1360 .data = .{
1361 .arithmetic_3op = .{
1362 .is_imm = false,
1363 .rd = .o7,
1364 .rs1 = .o7,
1365 .rs2_or_imm = .{ .rs2 = .g0 },
1360 _ = try self.addInst(.{
1361 .tag = .jmpl,
1362 .data = .{
1363 .arithmetic_3op = .{
1364 .is_imm = false,
1365 .rd = .o7,
1366 .rs1 = .o7,
1367 .rs2_or_imm = .{ .rs2 = .g0 },
1368 },
13661369 },
1367 },
1368 });
1370 });
13691371
1370 // TODO Find a way to fill this delay slot
1371 _ = try self.addInst(.{
1372 .tag = .nop,
1373 .data = .{ .nop = {} },
1374 });
1375 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
1376 return self.fail("TODO implement calling extern functions", .{});
1377 } else {
1378 return self.fail("TODO implement calling bitcasted functions", .{});
1372 // TODO Find a way to fill this delay slot
1373 _ = try self.addInst(.{
1374 .tag = .nop,
1375 .data = .{ .nop = {} },
1376 });
1377 },
1378 .extern_func => {
1379 return self.fail("TODO implement calling extern functions", .{});
1380 },
1381 else => {
1382 return self.fail("TODO implement calling bitcasted functions", .{});
1383 },
13791384 }
13801385 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
13811386 } else {
......@@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
16601665fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
16611666 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
16621667 const mod = self.bin_file.options.module.?;
1663 const function = mod.funcPtr(ty_fn.func);
1668 const func = mod.funcInfo(ty_fn.func);
16641669 // TODO emit debug info for function change
1665 _ = function;
1670 _ = func;
16661671 return self.finishAir(inst, .dead, .{ .none, .none, .none });
16671672}
16681673
......@@ -3595,13 +3600,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
35953600}
35963601
35973602fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
3603 const mod = self.bin_file.options.module.?;
35983604 const arg = self.air.instructions.items(.data)[inst].arg;
35993605 const ty = self.air.getRefType(arg.ty);
3600 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);
3606 const owner_decl = mod.funcOwnerDeclIndex(self.func_index);
3607 const name = mod.getParamName(self.func_index, arg.src_index);
36013608
36023609 switch (self.debug_output) {
36033610 .dwarf => |dw| switch (mcv) {
3604 .register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{
3611 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
36053612 .register = reg.dwarfLocOp(),
36063613 }),
36073614 else => {},
......@@ -4127,11 +4134,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re
41274134}
41284135
41294136fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
4137 const mod = self.bin_file.options.module.?;
41304138 const mcv: MCValue = switch (try codegen.genTypedValue(
41314139 self.bin_file,
41324140 self.src_loc,
41334141 typed_value,
4134 self.mod_fn.owner_decl,
4142 mod.funcOwnerDeclIndex(self.func_index),
41354143 )) {
41364144 .mcv => |mcv| switch (mcv) {
41374145 .none => .none,
......@@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 {
44524460/// Caller must call `CallMCValues.deinit`.
44534461fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
44544462 const mod = self.bin_file.options.module.?;
4463 const ip = &mod.intern_pool;
44554464 const fn_info = mod.typeToFunc(fn_ty).?;
44564465 const cc = fn_info.cc;
44574466 var result: CallMCValues = .{
......@@ -4486,14 +4495,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
44864495 .callee => abi.c_abi_int_param_regs_callee_view,
44874496 };
44884497
4489 for (fn_info.param_types, 0..) |ty, i| {
4498 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
44904499 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
44914500 if (param_size <= 8) {
44924501 if (next_register < argument_registers.len) {
4493 result.args[i] = .{ .register = argument_registers[next_register] };
4502 result_arg.* = .{ .register = argument_registers[next_register] };
44944503 next_register += 1;
44954504 } else {
4496 result.args[i] = .{ .stack_offset = next_stack_offset };
4505 result_arg.* = .{ .stack_offset = next_stack_offset };
44974506 next_register += next_stack_offset;
44984507 }
44994508 } else if (param_size <= 16) {
......@@ -4502,11 +4511,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
45024511 } else if (next_register < argument_registers.len) {
45034512 return self.fail("TODO MCValues split register + stack", .{});
45044513 } else {
4505 result.args[i] = .{ .stack_offset = next_stack_offset };
4514 result_arg.* = .{ .stack_offset = next_stack_offset };
45064515 next_register += next_stack_offset;
45074516 }
45084517 } else {
4509 result.args[i] = .{ .stack_offset = next_stack_offset };
4518 result_arg.* = .{ .stack_offset = next_stack_offset };
45104519 next_register += next_stack_offset;
45114520 }
45124521 }
src/arch/wasm/CodeGen.zig+16-12
......@@ -650,7 +650,7 @@ air: Air,
650650liveness: Liveness,
651651gpa: mem.Allocator,
652652debug_output: codegen.DebugInfoOutput,
653mod_fn: *const Module.Fn,
653func_index: InternPool.Index,
654654/// Contains a list of current branches.
655655/// When we return from a branch, the branch will be popped from this list,
656656/// which means branches can only contain references from within its own branch,
......@@ -1202,7 +1202,7 @@ fn genFunctype(
12021202pub fn generate(
12031203 bin_file: *link.File,
12041204 src_loc: Module.SrcLoc,
1205 func_index: Module.Fn.Index,
1205 func_index: InternPool.Index,
12061206 air: Air,
12071207 liveness: Liveness,
12081208 code: *std.ArrayList(u8),
......@@ -1210,7 +1210,7 @@ pub fn generate(
12101210) codegen.CodeGenError!codegen.Result {
12111211 _ = src_loc;
12121212 const mod = bin_file.options.module.?;
1213 const func = mod.funcPtr(func_index);
1213 const func = mod.funcInfo(func_index);
12141214 var code_gen: CodeGen = .{
12151215 .gpa = bin_file.allocator,
12161216 .air = air,
......@@ -1223,7 +1223,7 @@ pub fn generate(
12231223 .target = bin_file.options.target,
12241224 .bin_file = bin_file.cast(link.File.Wasm).?,
12251225 .debug_output = debug_output,
1226 .mod_fn = func,
1226 .func_index = func_index,
12271227 };
12281228 defer code_gen.deinit();
12291229
......@@ -1237,8 +1237,9 @@ pub fn generate(
12371237
12381238fn genFunc(func: *CodeGen) InnerError!void {
12391239 const mod = func.bin_file.base.options.module.?;
1240 const ip = &mod.intern_pool;
12401241 const fn_info = mod.typeToFunc(func.decl.ty).?;
1241 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
1242 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod);
12421243 defer func_type.deinit(func.gpa);
12431244 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);
12441245
......@@ -1347,6 +1348,7 @@ const CallWValues = struct {
13471348
13481349fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
13491350 const mod = func.bin_file.base.options.module.?;
1351 const ip = &mod.intern_pool;
13501352 const fn_info = mod.typeToFunc(fn_ty).?;
13511353 const cc = fn_info.cc;
13521354 var result: CallWValues = .{
......@@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13691371
13701372 switch (cc) {
13711373 .Unspecified => {
1372 for (fn_info.param_types) |ty| {
1374 for (fn_info.param_types.get(ip)) |ty| {
13731375 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
13741376 continue;
13751377 }
......@@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13791381 }
13801382 },
13811383 .C => {
1382 for (fn_info.param_types) |ty| {
1384 for (fn_info.param_types.get(ip)) |ty| {
13831385 const ty_classes = abi.classifyType(ty.toType(), mod);
13841386 for (ty_classes) |class| {
13851387 if (class == .none) continue;
......@@ -2185,6 +2187,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
21852187 const ty = func.typeOf(pl_op.operand);
21862188
21872189 const mod = func.bin_file.base.options.module.?;
2190 const ip = &mod.intern_pool;
21882191 const fn_ty = switch (ty.zigTypeTag(mod)) {
21892192 .Fn => ty,
21902193 .Pointer => ty.childType(mod),
......@@ -2203,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22032206 } else if (func_val.getExternFunc(mod)) |extern_func| {
22042207 const ext_decl = mod.declPtr(extern_func.decl);
22052208 const ext_info = mod.typeToFunc(ext_decl.ty).?;
2206 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);
2209 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types.get(ip), ext_info.return_type.toType(), mod);
22072210 defer func_type.deinit(func.gpa);
22082211 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
22092212 const atom = func.bin_file.getAtomPtr(atom_index);
......@@ -2253,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22532256 const operand = try func.resolveInst(pl_op.operand);
22542257 try func.emitWValue(operand);
22552258
2256 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
2259 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod);
22572260 defer fn_type.deinit(func.gpa);
22582261
22592262 const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);
......@@ -2564,8 +2567,8 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
25642567 switch (func.debug_output) {
25652568 .dwarf => |dwarf| {
25662569 const src_index = func.air.instructions.items(.data)[inst].arg.src_index;
2567 const name = func.mod_fn.getParamName(func.bin_file.base.options.module.?, src_index);
2568 try dwarf.genArgDbgInfo(name, arg_ty, func.mod_fn.owner_decl, .{
2570 const name = mod.getParamName(func.func_index, src_index);
2571 try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{
25692572 .wasm_local = arg.local.value,
25702573 });
25712574 },
......@@ -6198,6 +6201,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
61986201fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
61996202 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
62006203
6204 const mod = func.bin_file.base.options.module.?;
62016205 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
62026206 const ty = func.typeOf(pl_op.operand);
62036207 const operand = try func.resolveInst(pl_op.operand);
......@@ -6214,7 +6218,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
62146218 break :blk .nop;
62156219 },
62166220 };
6217 try func.debug_output.dwarf.genVarDbgInfo(name, ty, func.mod_fn.owner_decl, is_ptr, loc);
6221 try func.debug_output.dwarf.genVarDbgInfo(name, ty, mod.funcOwnerDeclIndex(func.func_index), is_ptr, loc);
62186222
62196223 func.finishAir(inst, .none, &.{});
62206224}
src/arch/x86_64/CodeGen.zig+23-22
......@@ -110,20 +110,21 @@ const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
110110const RegisterOffset = struct { reg: Register, off: i32 = 0 };
111111
112112const Owner = union(enum) {
113 mod_fn: *const Module.Fn,
113 func_index: InternPool.Index,
114114 lazy_sym: link.File.LazySymbol,
115115
116116 fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {
117117 return switch (owner) {
118 .mod_fn => |mod_fn| mod_fn.owner_decl,
118 .func_index => |func_index| mod.funcOwnerDeclIndex(func_index),
119119 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod),
120120 };
121121 }
122122
123123 fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 {
124124 switch (owner) {
125 .mod_fn => |mod_fn| {
126 const decl_index = mod_fn.owner_decl;
125 .func_index => |func_index| {
126 const mod = ctx.bin_file.options.module.?;
127 const decl_index = mod.funcOwnerDeclIndex(func_index);
127128 if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
128129 const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
129130 return macho_file.getAtom(atom).getSymbolIndex().?;
......@@ -638,7 +639,7 @@ const Self = @This();
638639pub fn generate(
639640 bin_file: *link.File,
640641 src_loc: Module.SrcLoc,
641 module_fn_index: Module.Fn.Index,
642 func_index: InternPool.Index,
642643 air: Air,
643644 liveness: Liveness,
644645 code: *std.ArrayList(u8),
......@@ -649,8 +650,8 @@ pub fn generate(
649650 }
650651
651652 const mod = bin_file.options.module.?;
652 const module_fn = mod.funcPtr(module_fn_index);
653 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
653 const func = mod.funcInfo(func_index);
654 const fn_owner_decl = mod.declPtr(func.owner_decl);
654655 assert(fn_owner_decl.has_tv);
655656 const fn_type = fn_owner_decl.ty;
656657
......@@ -662,15 +663,15 @@ pub fn generate(
662663 .target = &bin_file.options.target,
663664 .bin_file = bin_file,
664665 .debug_output = debug_output,
665 .owner = .{ .mod_fn = module_fn },
666 .owner = .{ .func_index = func_index },
666667 .err_msg = null,
667668 .args = undefined, // populated after `resolveCallingConventionValues`
668669 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
669670 .fn_type = fn_type,
670671 .arg_index = 0,
671672 .src_loc = src_loc,
672 .end_di_line = module_fn.rbrace_line,
673 .end_di_column = module_fn.rbrace_column,
673 .end_di_line = func.rbrace_line,
674 .end_di_column = func.rbrace_column,
674675 };
675676 defer {
676677 function.frame_allocs.deinit(gpa);
......@@ -687,17 +688,16 @@ pub fn generate(
687688 if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa);
688689 }
689690
690 wip_mir_log.debug("{}:", .{function.fmtDecl(module_fn.owner_decl)});
691 wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)});
692
693 const ip = &mod.intern_pool;
691694
692695 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
693696 function.frame_allocs.set(
694697 @intFromEnum(FrameIndex.stack_frame),
695698 FrameAlloc.init(.{
696699 .size = 0,
697 .alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack|
698 @intCast(set_align_stack.alignment.toByteUnitsOptional().?)
699 else
700 1,
700 .alignment = @intCast(func.analysis(ip).stack_alignment.toByteUnitsOptional() orelse 1),
701701 }),
702702 );
703703 function.frame_allocs.set(
......@@ -761,8 +761,8 @@ pub fn generate(
761761 .debug_output = debug_output,
762762 .code = code,
763763 .prev_di_pc = 0,
764 .prev_di_line = module_fn.lbrace_line,
765 .prev_di_column = module_fn.lbrace_column,
764 .prev_di_line = func.lbrace_line,
765 .prev_di_column = func.lbrace_column,
766766 };
767767 defer emit.deinit();
768768 emit.emitMir() catch |err| switch (err) {
......@@ -7942,7 +7942,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
79427942
79437943 const ty = self.typeOfIndex(inst);
79447944 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
7945 const name = self.owner.mod_fn.getParamName(mod, src_index);
7945 const name = mod.getParamName(self.owner.func_index, src_index);
79467946 try self.genArgDbgInfo(ty, name, dst_mcv);
79477947
79487948 break :result dst_mcv;
......@@ -8139,7 +8139,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81398139 if (try self.air.value(callee, mod)) |func_value| {
81408140 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
81418141 if (switch (func_key) {
8142 .func => |func| mod.funcPtr(func.index).owner_decl,
8142 .func => |func| func.owner_decl,
81438143 .ptr => |ptr| switch (ptr.addr) {
81448144 .decl => |decl| decl,
81458145 else => null,
......@@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
85828582fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
85838583 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
85848584 const mod = self.bin_file.options.module.?;
8585 const function = mod.funcPtr(ty_fn.func);
8585 const func = mod.funcInfo(ty_fn.func);
85868586 // TODO emit debug info for function change
8587 _ = function;
8587 _ = func;
85888588 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
85898589}
85908590
......@@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues(
1171911719 stack_frame_base: FrameIndex,
1172011720) !CallMCValues {
1172111721 const mod = self.bin_file.options.module.?;
11722 const ip = &mod.intern_pool;
1172211723 const cc = fn_info.cc;
1172311724 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
1172411725 defer self.gpa.free(param_types);
1172511726
11726 for (param_types[0..fn_info.param_types.len], fn_info.param_types) |*dest, src| {
11727 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {
1172711728 dest.* = src.toType();
1172811729 }
1172911730 // TODO: promote var arg types
src/codegen.zig+1-1
......@@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
6767pub fn generateFunction(
6868 bin_file: *link.File,
6969 src_loc: Module.SrcLoc,
70 func_index: Module.Fn.Index,
70 func_index: InternPool.Index,
7171 air: Air,
7272 liveness: Liveness,
7373 code: *std.ArrayList(u8),
src/codegen/c.zig+9-7
......@@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
257257 return .{ .data = ident };
258258}
259259
260/// This data is available when outputting .c code for a `Module.Fn.Index`.
260/// This data is available when outputting .c code for a `InternPool.Index`
261/// that corresponds to `func`.
261262/// It is not available when generating .h file.
262263pub const Function = struct {
263264 air: Air,
......@@ -268,7 +269,7 @@ pub const Function = struct {
268269 next_block_index: usize = 0,
269270 object: Object,
270271 lazy_fns: LazyFnMap,
271 func_index: Module.Fn.Index,
272 func_index: InternPool.Index,
272273 /// All the locals, to be emitted at the top of the function.
273274 locals: std.ArrayListUnmanaged(Local) = .{},
274275 /// Which locals are available for reuse, based on Type.
......@@ -1487,6 +1488,7 @@ pub const DeclGen = struct {
14871488 ) !void {
14881489 const store = &dg.ctypes.set;
14891490 const mod = dg.module;
1491 const ip = &mod.intern_pool;
14901492
14911493 const fn_decl = mod.declPtr(fn_decl_index);
14921494 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);
......@@ -1499,7 +1501,7 @@ pub const DeclGen = struct {
14991501 else => unreachable,
15001502 }
15011503 }
1502 if (fn_decl.val.getFunction(mod)) |func| if (func.is_cold) try w.writeAll("zig_cold ");
1504 if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold) try w.writeAll("zig_cold ");
15031505 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
15041506
15051507 const trailing = try renderTypePrefix(
......@@ -1744,7 +1746,7 @@ pub const DeclGen = struct {
17441746 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
17451747 .variable => |variable| mod.decl_exports.contains(variable.decl),
17461748 .extern_func => true,
1747 .func => |func| mod.decl_exports.contains(mod.funcPtr(func.index).owner_decl),
1749 .func => |func| mod.decl_exports.contains(func.owner_decl),
17481750 else => unreachable,
17491751 };
17501752 }
......@@ -4161,7 +4163,7 @@ fn airCall(
41614163 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
41624164 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
41634165 .extern_func => |extern_func| extern_func.decl,
4164 .func => |func| mod.funcPtr(func.index).owner_decl,
4166 .func => |func| func.owner_decl,
41654167 .ptr => |ptr| switch (ptr.addr) {
41664168 .decl => |decl| decl,
41674169 else => break :known,
......@@ -4238,9 +4240,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
42384240 const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;
42394241 const mod = f.object.dg.module;
42404242 const writer = f.object.writer();
4241 const function = mod.funcPtr(ty_fn.func);
4243 const owner_decl = mod.funcOwnerDeclPtr(ty_fn.func);
42424244 try writer.print("/* dbg func:{s} */\n", .{
4243 mod.intern_pool.stringToSlice(mod.declPtr(function.owner_decl).name),
4245 mod.intern_pool.stringToSlice(owner_decl.name),
42444246 });
42454247 return .none;
42464248}
src/codegen/c/type.zig+9-5
......@@ -1722,6 +1722,7 @@ pub const CType = extern union {
17221722
17231723 .Fn => {
17241724 const info = mod.typeToFunc(ty).?;
1725 const ip = &mod.intern_pool;
17251726 if (!info.is_generic) {
17261727 if (lookup.isMutable()) {
17271728 const param_kind: Kind = switch (kind) {
......@@ -1730,7 +1731,7 @@ pub const CType = extern union {
17301731 .payload => unreachable,
17311732 };
17321733 _ = try lookup.typeToIndex(info.return_type.toType(), param_kind);
1733 for (info.param_types) |param_type| {
1734 for (info.param_types.get(ip)) |param_type| {
17341735 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
17351736 _ = try lookup.typeToIndex(param_type.toType(), param_kind);
17361737 }
......@@ -2014,6 +2015,7 @@ pub const CType = extern union {
20142015 .function,
20152016 .varargs_function,
20162017 => {
2018 const ip = &mod.intern_pool;
20172019 const info = mod.typeToFunc(ty).?;
20182020 assert(!info.is_generic);
20192021 const param_kind: Kind = switch (kind) {
......@@ -2023,14 +2025,14 @@ pub const CType = extern union {
20232025 };
20242026
20252027 var c_params_len: usize = 0;
2026 for (info.param_types) |param_type| {
2028 for (info.param_types.get(ip)) |param_type| {
20272029 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
20282030 c_params_len += 1;
20292031 }
20302032
20312033 const params_pl = try arena.alloc(Index, c_params_len);
20322034 var c_param_i: usize = 0;
2033 for (info.param_types) |param_type| {
2035 for (info.param_types.get(ip)) |param_type| {
20342036 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
20352037 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
20362038 c_param_i += 1;
......@@ -2147,6 +2149,7 @@ pub const CType = extern union {
21472149 => {
21482150 if (ty.zigTypeTag(mod) != .Fn) return false;
21492151
2152 const ip = &mod.intern_pool;
21502153 const info = mod.typeToFunc(ty).?;
21512154 assert(!info.is_generic);
21522155 const data = cty.cast(Payload.Function).?.data;
......@@ -2160,7 +2163,7 @@ pub const CType = extern union {
21602163 return false;
21612164
21622165 var c_param_i: usize = 0;
2163 for (info.param_types) |param_type| {
2166 for (info.param_types.get(ip)) |param_type| {
21642167 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
21652168
21662169 if (c_param_i >= data.param_types.len) return false;
......@@ -2202,6 +2205,7 @@ pub const CType = extern union {
22022205 autoHash(hasher, t);
22032206
22042207 const mod = self.lookup.getModule();
2208 const ip = &mod.intern_pool;
22052209 switch (t) {
22062210 .fwd_anon_struct,
22072211 .fwd_anon_union,
......@@ -2270,7 +2274,7 @@ pub const CType = extern union {
22702274 };
22712275
22722276 self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);
2273 for (info.param_types) |param_type| {
2277 for (info.param_types.get(ip)) |param_type| {
22742278 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
22752279 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
22762280 }
src/codegen/llvm.zig+63-55
......@@ -867,14 +867,15 @@ pub const Object = struct {
867867 pub fn updateFunc(
868868 o: *Object,
869869 mod: *Module,
870 func_index: Module.Fn.Index,
870 func_index: InternPool.Index,
871871 air: Air,
872872 liveness: Liveness,
873873 ) !void {
874 const func = mod.funcPtr(func_index);
874 const func = mod.funcInfo(func_index);
875875 const decl_index = func.owner_decl;
876876 const decl = mod.declPtr(decl_index);
877877 const target = mod.getTarget();
878 const ip = &mod.intern_pool;
878879
879880 var dg: DeclGen = .{
880881 .object = o,
......@@ -885,24 +886,23 @@ pub const Object = struct {
885886
886887 const llvm_func = try o.resolveLlvmFunction(decl_index);
887888
888 if (mod.align_stack_fns.get(func_index)) |align_info| {
889 o.addFnAttrInt(llvm_func, "alignstack", align_info.alignment.toByteUnitsOptional().?);
889 if (func.analysis(ip).is_noinline) {
890890 o.addFnAttr(llvm_func, "noinline");
891891 } else {
892 Object.removeFnAttr(llvm_func, "alignstack");
893 if (!func.is_noinline) Object.removeFnAttr(llvm_func, "noinline");
892 Object.removeFnAttr(llvm_func, "noinline");
894893 }
895894
896 if (func.is_cold) {
897 o.addFnAttr(llvm_func, "cold");
895 if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {
896 o.addFnAttrInt(llvm_func, "alignstack", alignment);
897 o.addFnAttr(llvm_func, "noinline");
898898 } else {
899 Object.removeFnAttr(llvm_func, "cold");
899 Object.removeFnAttr(llvm_func, "alignstack");
900900 }
901901
902 if (func.is_noinline) {
903 o.addFnAttr(llvm_func, "noinline");
902 if (func.analysis(ip).is_cold) {
903 o.addFnAttr(llvm_func, "cold");
904904 } else {
905 Object.removeFnAttr(llvm_func, "noinline");
905 Object.removeFnAttr(llvm_func, "cold");
906906 }
907907
908908 // TODO: disable this if safety is off for the function scope
......@@ -921,7 +921,7 @@ pub const Object = struct {
921921 o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
922922 }
923923
924 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
924 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
925925 llvm_func.setSection(section);
926926
927927 // Remove all the basic blocks of a function in order to start over, generating
......@@ -968,7 +968,7 @@ pub const Object = struct {
968968 .byval => {
969969 assert(!it.byval_attr);
970970 const param_index = it.zig_index - 1;
971 const param_ty = fn_info.param_types[param_index].toType();
971 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
972972 const param = llvm_func.getParam(llvm_arg_i);
973973 try args.ensureUnusedCapacity(1);
974974
......@@ -987,7 +987,7 @@ pub const Object = struct {
987987 llvm_arg_i += 1;
988988 },
989989 .byref => {
990 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
990 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
991991 const param_llvm_ty = try o.lowerType(param_ty);
992992 const param = llvm_func.getParam(llvm_arg_i);
993993 const alignment = param_ty.abiAlignment(mod);
......@@ -1006,7 +1006,7 @@ pub const Object = struct {
10061006 }
10071007 },
10081008 .byref_mut => {
1009 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1009 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
10101010 const param_llvm_ty = try o.lowerType(param_ty);
10111011 const param = llvm_func.getParam(llvm_arg_i);
10121012 const alignment = param_ty.abiAlignment(mod);
......@@ -1026,7 +1026,7 @@ pub const Object = struct {
10261026 },
10271027 .abi_sized_int => {
10281028 assert(!it.byval_attr);
1029 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1029 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
10301030 const param = llvm_func.getParam(llvm_arg_i);
10311031 llvm_arg_i += 1;
10321032
......@@ -1053,7 +1053,7 @@ pub const Object = struct {
10531053 },
10541054 .slice => {
10551055 assert(!it.byval_attr);
1056 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1056 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
10571057 const ptr_info = param_ty.ptrInfo(mod);
10581058
10591059 if (math.cast(u5, it.zig_index - 1)) |i| {
......@@ -1083,7 +1083,7 @@ pub const Object = struct {
10831083 .multiple_llvm_types => {
10841084 assert(!it.byval_attr);
10851085 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];
1086 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1086 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
10871087 const param_llvm_ty = try o.lowerType(param_ty);
10881088 const param_alignment = param_ty.abiAlignment(mod);
10891089 const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
......@@ -1114,7 +1114,7 @@ pub const Object = struct {
11141114 args.appendAssumeCapacity(casted);
11151115 },
11161116 .float_array => {
1117 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1117 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
11181118 const param_llvm_ty = try o.lowerType(param_ty);
11191119 const param = llvm_func.getParam(llvm_arg_i);
11201120 llvm_arg_i += 1;
......@@ -1132,7 +1132,7 @@ pub const Object = struct {
11321132 }
11331133 },
11341134 .i32_array, .i64_array => {
1135 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1135 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
11361136 const param_llvm_ty = try o.lowerType(param_ty);
11371137 const param = llvm_func.getParam(llvm_arg_i);
11381138 llvm_arg_i += 1;
......@@ -1168,7 +1168,7 @@ pub const Object = struct {
11681168 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
11691169 const subprogram = dib.createFunction(
11701170 di_file.?.toScope(),
1171 mod.intern_pool.stringToSlice(decl.name),
1171 ip.stringToSlice(decl.name),
11721172 llvm_func.getValueName(),
11731173 di_file.?,
11741174 line_number,
......@@ -1460,6 +1460,7 @@ pub const Object = struct {
14601460 const target = o.target;
14611461 const dib = o.di_builder.?;
14621462 const mod = o.module;
1463 const ip = &mod.intern_pool;
14631464 switch (ty.zigTypeTag(mod)) {
14641465 .Void, .NoReturn => {
14651466 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
......@@ -1492,7 +1493,6 @@ pub const Object = struct {
14921493 return enum_di_ty;
14931494 }
14941495
1495 const ip = &mod.intern_pool;
14961496 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
14971497
14981498 const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);
......@@ -1518,7 +1518,7 @@ pub const Object = struct {
15181518 if (@sizeOf(usize) == @sizeOf(u64)) {
15191519 enumerators[i] = dib.createEnumerator2(
15201520 field_name_z,
1521 @as(c_uint, @intCast(bigint.limbs.len)),
1521 @intCast(bigint.limbs.len),
15221522 bigint.limbs.ptr,
15231523 int_info.bits,
15241524 int_info.signedness == .unsigned,
......@@ -2320,8 +2320,8 @@ pub const Object = struct {
23202320 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
23212321 }
23222322
2323 for (0..mod.typeToFunc(ty).?.param_types.len) |i| {
2324 const param_ty = mod.typeToFunc(ty).?.param_types[i].toType();
2323 for (0..fn_info.param_types.len) |i| {
2324 const param_ty = fn_info.param_types.get(ip)[i].toType();
23252325 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
23262326
23272327 if (isByRef(param_ty, mod)) {
......@@ -2475,9 +2475,10 @@ pub const Object = struct {
24752475 const fn_type = try o.lowerType(zig_fn_type);
24762476
24772477 const fqn = try decl.getFullyQualifiedName(mod);
2478 const ip = &mod.intern_pool;
24782479
24792480 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
2480 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(mod.intern_pool.stringToSlice(fqn), fn_type, llvm_addrspace);
2481 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(ip.stringToSlice(fqn), fn_type, llvm_addrspace);
24812482 gop.value_ptr.* = llvm_fn;
24822483
24832484 const is_extern = decl.isExtern(mod);
......@@ -2486,8 +2487,8 @@ pub const Object = struct {
24862487 llvm_fn.setUnnamedAddr(.True);
24872488 } else {
24882489 if (target.isWasm()) {
2489 o.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name));
2490 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
2490 o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
2491 if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
24912492 if (!std.mem.eql(u8, lib_name, "c")) {
24922493 o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
24932494 }
......@@ -2546,13 +2547,13 @@ pub const Object = struct {
25462547 while (it.next()) |lowering| switch (lowering) {
25472548 .byval => {
25482549 const param_index = it.zig_index - 1;
2549 const param_ty = fn_info.param_types[param_index].toType();
2550 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
25502551 if (!isByRef(param_ty, mod)) {
25512552 o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
25522553 }
25532554 },
25542555 .byref => {
2555 const param_ty = fn_info.param_types[it.zig_index - 1];
2556 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1];
25562557 const param_llvm_ty = try o.lowerType(param_ty.toType());
25572558 const alignment = param_ty.toType().abiAlignment(mod);
25582559 o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
......@@ -3031,6 +3032,7 @@ pub const Object = struct {
30313032
30323033 fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {
30333034 const mod = o.module;
3035 const ip = &mod.intern_pool;
30343036 const fn_info = mod.typeToFunc(fn_ty).?;
30353037 const llvm_ret_ty = try lowerFnRetTy(o, fn_info);
30363038
......@@ -3052,19 +3054,19 @@ pub const Object = struct {
30523054 while (it.next()) |lowering| switch (lowering) {
30533055 .no_bits => continue,
30543056 .byval => {
3055 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3057 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
30563058 try llvm_params.append(try o.lowerType(param_ty));
30573059 },
30583060 .byref, .byref_mut => {
30593061 try llvm_params.append(o.context.pointerType(0));
30603062 },
30613063 .abi_sized_int => {
3062 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3064 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
30633065 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
30643066 try llvm_params.append(o.context.intType(abi_size * 8));
30653067 },
30663068 .slice => {
3067 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3069 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
30683070 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
30693071 param_ty.optionalChild(mod).slicePtrFieldType(mod)
30703072 else
......@@ -3083,7 +3085,7 @@ pub const Object = struct {
30833085 try llvm_params.append(o.context.intType(16));
30843086 },
30853087 .float_array => |count| {
3086 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3088 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
30873089 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
30883090 const field_count = @as(c_uint, @intCast(count));
30893091 const arr_ty = float_ty.arrayType(field_count);
......@@ -3137,8 +3139,7 @@ pub const Object = struct {
31373139 return llvm_type.getUndef();
31383140 }
31393141
3140 const val_key = mod.intern_pool.indexToKey(tv.val.toIntern());
3141 switch (val_key) {
3142 switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
31423143 .int_type,
31433144 .ptr_type,
31443145 .array_type,
......@@ -3175,12 +3176,14 @@ pub const Object = struct {
31753176 .enum_literal,
31763177 .empty_enum_value,
31773178 => unreachable, // non-runtime values
3178 .extern_func, .func => {
3179 const fn_decl_index = switch (val_key) {
3180 .extern_func => |extern_func| extern_func.decl,
3181 .func => |func| mod.funcPtr(func.index).owner_decl,
3182 else => unreachable,
3183 };
3179 .extern_func => |extern_func| {
3180 const fn_decl_index = extern_func.decl;
3181 const fn_decl = mod.declPtr(fn_decl_index);
3182 try mod.markDeclAlive(fn_decl);
3183 return o.resolveLlvmFunction(fn_decl_index);
3184 },
3185 .func => |func| {
3186 const fn_decl_index = func.owner_decl;
31843187 const fn_decl = mod.declPtr(fn_decl_index);
31853188 try mod.markDeclAlive(fn_decl);
31863189 return o.resolveLlvmFunction(fn_decl_index);
......@@ -4598,6 +4601,7 @@ pub const FuncGen = struct {
45984601 const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));
45994602 const o = self.dg.object;
46004603 const mod = o.module;
4604 const ip = &mod.intern_pool;
46014605 const callee_ty = self.typeOf(pl_op.operand);
46024606 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
46034607 .Fn => callee_ty,
......@@ -4801,14 +4805,14 @@ pub const FuncGen = struct {
48014805 while (it.next()) |lowering| switch (lowering) {
48024806 .byval => {
48034807 const param_index = it.zig_index - 1;
4804 const param_ty = fn_info.param_types[param_index].toType();
4808 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
48054809 if (!isByRef(param_ty, mod)) {
48064810 o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
48074811 }
48084812 },
48094813 .byref => {
48104814 const param_index = it.zig_index - 1;
4811 const param_ty = fn_info.param_types[param_index].toType();
4815 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
48124816 const param_llvm_ty = try o.lowerType(param_ty);
48134817 const alignment = param_ty.abiAlignment(mod);
48144818 o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
......@@ -4828,7 +4832,7 @@ pub const FuncGen = struct {
48284832
48294833 .slice => {
48304834 assert(!it.byval_attr);
4831 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
4835 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
48324836 const ptr_info = param_ty.ptrInfo(mod);
48334837 const llvm_arg_i = it.llvm_index - 2;
48344838
......@@ -4930,7 +4934,7 @@ pub const FuncGen = struct {
49304934 fg.context.pointerType(0).constNull(),
49314935 null_opt_addr_global,
49324936 };
4933 const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?;
4937 const panic_func = mod.funcInfo(mod.panic_func_index);
49344938 const panic_decl = mod.declPtr(panic_func.owner_decl);
49354939 const fn_info = mod.typeToFunc(panic_decl.ty).?;
49364940 const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);
......@@ -6030,7 +6034,7 @@ pub const FuncGen = struct {
60306034 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
60316035
60326036 const mod = o.module;
6033 const func = mod.funcPtr(ty_fn.func);
6037 const func = mod.funcInfo(ty_fn.func);
60346038 const decl_index = func.owner_decl;
60356039 const decl = mod.declPtr(decl_index);
60366040 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
......@@ -6039,7 +6043,7 @@ pub const FuncGen = struct {
60396043 const cur_debug_location = self.builder.getCurrentDebugLocation2();
60406044
60416045 try self.dbg_inlined.append(self.gpa, .{
6042 .loc = @as(*llvm.DILocation, @ptrCast(cur_debug_location)),
6046 .loc = @ptrCast(cur_debug_location),
60436047 .scope = self.di_scope.?,
60446048 .base_line = self.base_line,
60456049 });
......@@ -6090,8 +6094,7 @@ pub const FuncGen = struct {
60906094 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
60916095
60926096 const mod = o.module;
6093 const func = mod.funcPtr(ty_fn.func);
6094 const decl = mod.declPtr(func.owner_decl);
6097 const decl = mod.funcOwnerDeclPtr(ty_fn.func);
60956098 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
60966099 self.di_file = di_file;
60976100 const old = self.dbg_inlined.pop();
......@@ -8137,12 +8140,13 @@ pub const FuncGen = struct {
81378140 }
81388141
81398142 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
8140 const func = self.dg.decl.getOwnedFunction(mod).?;
8143 const func_index = self.dg.decl.getOwnedFunctionIndex();
8144 const func = mod.funcInfo(func_index);
81418145 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
81428146 const lbrace_col = func.lbrace_column + 1;
81438147 const di_local_var = dib.createParameterVariable(
81448148 self.di_scope.?,
8145 func.getParamName(mod, src_index).ptr, // TODO test 0 bit args
8149 mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args
81468150 self.di_file.?,
81478151 lbrace_line,
81488152 try o.lowerDebugType(inst_ty, .full),
......@@ -10888,13 +10892,17 @@ const ParamTypeIterator = struct {
1088810892
1088910893 pub fn next(it: *ParamTypeIterator) ?Lowering {
1089010894 if (it.zig_index >= it.fn_info.param_types.len) return null;
10891 const ty = it.fn_info.param_types[it.zig_index];
10895 const mod = it.object.module;
10896 const ip = &mod.intern_pool;
10897 const ty = it.fn_info.param_types.get(ip)[it.zig_index];
1089210898 it.byval_attr = false;
1089310899 return nextInner(it, ty.toType());
1089410900 }
1089510901
1089610902 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
1089710903 pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) ?Lowering {
10904 const mod = it.object.module;
10905 const ip = &mod.intern_pool;
1089810906 if (it.zig_index >= it.fn_info.param_types.len) {
1089910907 if (it.zig_index >= args.len) {
1090010908 return null;
......@@ -10902,7 +10910,7 @@ const ParamTypeIterator = struct {
1090210910 return nextInner(it, fg.typeOf(args[it.zig_index]));
1090310911 }
1090410912 } else {
10905 return nextInner(it, it.fn_info.param_types[it.zig_index].toType());
10913 return nextInner(it, it.fn_info.param_types.get(ip)[it.zig_index].toType());
1090610914 }
1090710915 }
1090810916
src/codegen/spirv.zig+12-8
......@@ -238,7 +238,7 @@ pub const DeclGen = struct {
238238 if (ty.zigTypeTag(mod) == .Fn) {
239239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
240240 .extern_func => |extern_func| extern_func.decl,
241 .func => |func| mod.funcPtr(func.index).owner_decl,
241 .func => |func| func.owner_decl,
242242 else => unreachable,
243243 };
244244 const spv_decl_index = try self.resolveDecl(fn_decl_index);
......@@ -255,13 +255,14 @@ pub const DeclGen = struct {
255255 /// Fetch or allocate a result id for decl index. This function also marks the decl as alive.
256256 /// Note: Function does not actually generate the decl.
257257 fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
258 const decl = self.module.declPtr(decl_index);
259 try self.module.markDeclAlive(decl);
258 const mod = self.module;
259 const decl = mod.declPtr(decl_index);
260 try mod.markDeclAlive(decl);
260261
261262 const entry = try self.decl_link.getOrPut(decl_index);
262263 if (!entry.found_existing) {
263264 // TODO: Extern fn?
264 const kind: SpvModule.DeclKind = if (decl.val.getFunctionIndex(self.module) != .none)
265 const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod))
265266 .func
266267 else
267268 .global;
......@@ -1268,6 +1269,7 @@ pub const DeclGen = struct {
12681269 },
12691270 .Fn => switch (repr) {
12701271 .direct => {
1272 const ip = &mod.intern_pool;
12711273 const fn_info = mod.typeToFunc(ty).?;
12721274 // TODO: Put this somewhere in Sema.zig
12731275 if (fn_info.is_var_args)
......@@ -1275,8 +1277,8 @@ pub const DeclGen = struct {
12751277
12761278 const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);
12771279 defer self.gpa.free(param_ty_refs);
1278 for (param_ty_refs, 0..) |*param_type, i| {
1279 param_type.* = try self.resolveType(fn_info.param_types[i].toType(), .direct);
1280 for (param_ty_refs, fn_info.param_types.get(ip)) |*param_type, fn_param_type| {
1281 param_type.* = try self.resolveType(fn_param_type.toType(), .direct);
12801282 }
12811283 const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct);
12821284
......@@ -1576,6 +1578,7 @@ pub const DeclGen = struct {
15761578
15771579 fn genDecl(self: *DeclGen) !void {
15781580 const mod = self.module;
1581 const ip = &mod.intern_pool;
15791582 const decl = mod.declPtr(self.decl_index);
15801583 const spv_decl_index = try self.resolveDecl(self.decl_index);
15811584
......@@ -1594,7 +1597,8 @@ pub const DeclGen = struct {
15941597 const fn_info = mod.typeToFunc(decl.ty).?;
15951598
15961599 try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
1597 for (fn_info.param_types) |param_type| {
1600 for (0..fn_info.param_types.len) |i| {
1601 const param_type = fn_info.param_types.get(ip)[i];
15981602 const param_type_id = try self.resolveTypeId(param_type.toType());
15991603 const arg_result_id = self.spv.allocId();
16001604 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
......@@ -1621,7 +1625,7 @@ pub const DeclGen = struct {
16211625 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
16221626 try self.spv.addFunction(spv_decl_index, self.func);
16231627
1624 const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(self.module));
1628 const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module));
16251629
16261630 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
16271631 .target = decl_id,
src/link.zig+2-1
......@@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig");
1616const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
1717const Liveness = @import("Liveness.zig");
1818const Module = @import("Module.zig");
19const InternPool = @import("InternPool.zig");
1920const Package = @import("Package.zig");
2021const Type = @import("type.zig").Type;
2122const TypedValue = @import("TypedValue.zig");
......@@ -562,7 +563,7 @@ pub const File = struct {
562563 }
563564
564565 /// May be called before or after updateDeclExports for any given Decl.
565 pub fn updateFunc(base: *File, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
566 pub fn updateFunc(base: *File, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
566567 if (build_options.only_c) {
567568 assert(base.tag == .c);
568569 return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness);
src/link/C.zig+2-2
......@@ -88,13 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
8888 }
8989}
9090
91pub fn updateFunc(self: *C, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
91pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
9292 const tracy = trace(@src());
9393 defer tracy.end();
9494
9595 const gpa = self.base.allocator;
9696
97 const func = module.funcPtr(func_index);
97 const func = module.funcInfo(func_index);
9898 const decl_index = func.owner_decl;
9999 const gop = try self.decl_table.getOrPut(gpa, decl_index);
100100 if (!gop.found_existing) {
src/link/Coff.zig+3-3
......@@ -1032,7 +1032,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
10321032 self.getAtomPtr(atom_index).sym_index = 0;
10331033}
10341034
1035pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
1035pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
10361036 if (build_options.skip_non_native and builtin.object_format != .coff) {
10371037 @panic("Attempted to compile for object format that was disabled by build configuration");
10381038 }
......@@ -1044,7 +1044,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: A
10441044 const tracy = trace(@src());
10451045 defer tracy.end();
10461046
1047 const func = mod.funcPtr(func_index);
1047 const func = mod.funcInfo(func_index);
10481048 const decl_index = func.owner_decl;
10491049 const decl = mod.declPtr(decl_index);
10501050
......@@ -1424,7 +1424,7 @@ pub fn updateDeclExports(
14241424 // detect the default subsystem.
14251425 for (exports) |exp| {
14261426 const exported_decl = mod.declPtr(exp.exported_decl);
1427 if (exported_decl.getOwnedFunctionIndex(mod) == .none) continue;
1427 if (exported_decl.getOwnedFunctionIndex() == .none) continue;
14281428 const winapi_cc = switch (self.base.options.target.cpu.arch) {
14291429 .x86 => std.builtin.CallingConvention.Stdcall,
14301430 else => std.builtin.CallingConvention.C,
src/link/Elf.zig+2-2
......@@ -2575,7 +2575,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
25752575 return local_sym;
25762576}
25772577
2578pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
2578pub fn updateFunc(self: *Elf, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
25792579 if (build_options.skip_non_native and builtin.object_format != .elf) {
25802580 @panic("Attempted to compile for object format that was disabled by build configuration");
25812581 }
......@@ -2586,7 +2586,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Ai
25862586 const tracy = trace(@src());
25872587 defer tracy.end();
25882588
2589 const func = mod.funcPtr(func_index);
2589 const func = mod.funcInfo(func_index);
25902590 const decl_index = func.owner_decl;
25912591 const decl = mod.declPtr(decl_index);
25922592
src/link/MachO.zig+2-2
......@@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
18451845 self.markRelocsDirtyByTarget(target);
18461846}
18471847
1848pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
1848pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
18491849 if (build_options.skip_non_native and builtin.object_format != .macho) {
18501850 @panic("Attempted to compile for object format that was disabled by build configuration");
18511851 }
......@@ -1855,7 +1855,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air:
18551855 const tracy = trace(@src());
18561856 defer tracy.end();
18571857
1858 const func = mod.funcPtr(func_index);
1858 const func = mod.funcInfo(func_index);
18591859 const decl_index = func.owner_decl;
18601860 const decl = mod.declPtr(decl_index);
18611861
src/link/NvPtx.zig+2-1
......@@ -13,6 +13,7 @@ const assert = std.debug.assert;
1313const log = std.log.scoped(.link);
1414
1515const Module = @import("../Module.zig");
16const InternPool = @import("../InternPool.zig");
1617const Compilation = @import("../Compilation.zig");
1718const link = @import("../link.zig");
1819const trace = @import("../tracy.zig").trace;
......@@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void {
6869 self.base.allocator.free(self.ptx_file_name);
6970}
7071
71pub fn updateFunc(self: *NvPtx, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
72pub fn updateFunc(self: *NvPtx, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
7273 if (!build_options.have_llvm) return;
7374 try self.llvm_object.updateFunc(module, func_index, air, liveness);
7475}
src/link/Plan9.zig+4-3
......@@ -4,6 +4,7 @@
44const Plan9 = @This();
55const link = @import("../link.zig");
66const Module = @import("../Module.zig");
7const InternPool = @import("../InternPool.zig");
78const Compilation = @import("../Compilation.zig");
89const aout = @import("Plan9/aout.zig");
910const codegen = @import("../codegen.zig");
......@@ -344,12 +345,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi
344345 }
345346}
346347
347pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
348pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
348349 if (build_options.skip_non_native and builtin.object_format != .plan9) {
349350 @panic("Attempted to compile for object format that was disabled by build configuration");
350351 }
351352
352 const func = mod.funcPtr(func_index);
353 const func = mod.funcInfo(func_index);
353354 const decl_index = func.owner_decl;
354355 const decl = mod.declPtr(decl_index);
355356 self.freeUnnamedConsts(decl_index);
......@@ -908,7 +909,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
908909 // in the deleteUnusedDecl function.
909910 const mod = self.base.options.module.?;
910911 const decl = mod.declPtr(decl_index);
911 const is_fn = decl.val.getFunctionIndex(mod) != .none;
912 const is_fn = decl.val.isFuncBody(mod);
912913 if (is_fn) {
913914 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
914915 var submap = symidx_and_submap.functions;
src/link/SpirV.zig+4-3
......@@ -29,6 +29,7 @@ const assert = std.debug.assert;
2929const log = std.log.scoped(.link);
3030
3131const Module = @import("../Module.zig");
32const InternPool = @import("../InternPool.zig");
3233const Compilation = @import("../Compilation.zig");
3334const link = @import("../link.zig");
3435const codegen = @import("../codegen/spirv.zig");
......@@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void {
103104 self.decl_link.deinit();
104105}
105106
106pub fn updateFunc(self: *SpirV, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
107pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
107108 if (build_options.skip_non_native) {
108109 @panic("Attempted to compile for architecture that was disabled by build configuration");
109110 }
110111
111 const func = module.funcPtr(func_index);
112 const func = module.funcInfo(func_index);
112113
113114 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
114115 defer decl_gen.deinit();
......@@ -138,7 +139,7 @@ pub fn updateDeclExports(
138139 exports: []const *Module.Export,
139140) !void {
140141 const decl = mod.declPtr(decl_index);
141 if (decl.val.getFunctionIndex(mod) != .none and decl.ty.fnCallingConvention(mod) == .Kernel) {
142 if (decl.val.isFuncBody(mod) and decl.ty.fnCallingConvention(mod) == .Kernel) {
142143 // TODO: Unify with resolveDecl in spirv.zig.
143144 const entry = try self.decl_link.getOrPut(decl_index);
144145 if (!entry.found_existing) {
src/link/Wasm.zig+3-2
......@@ -12,6 +12,7 @@ const log = std.log.scoped(.link);
1212pub const Atom = @import("Wasm/Atom.zig");
1313const Dwarf = @import("Dwarf.zig");
1414const Module = @import("../Module.zig");
15const InternPool = @import("../InternPool.zig");
1516const Compilation = @import("../Compilation.zig");
1617const CodeGen = @import("../arch/wasm/CodeGen.zig");
1718const codegen = @import("../codegen.zig");
......@@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
13381339 return index;
13391340}
13401341
1341pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
1342pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
13421343 if (build_options.skip_non_native and builtin.object_format != .wasm) {
13431344 @panic("Attempted to compile for object format that was disabled by build configuration");
13441345 }
......@@ -1349,7 +1350,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: A
13491350 const tracy = trace(@src());
13501351 defer tracy.end();
13511352
1352 const func = mod.funcPtr(func_index);
1353 const func = mod.funcInfo(func_index);
13531354 const decl_index = func.owner_decl;
13541355 const decl = mod.declPtr(decl_index);
13551356 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
src/print_air.zig+1-1
......@@ -665,7 +665,7 @@ const Writer = struct {
665665 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
666666 const ty_fn = w.air.instructions.items(.data)[inst].ty_fn;
667667 const func_index = ty_fn.func;
668 const owner_decl = w.module.declPtr(w.module.funcPtr(func_index).owner_decl);
668 const owner_decl = w.module.funcOwnerDeclPtr(func_index);
669669 try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});
670670 }
671671
src/type.zig+4-3
......@@ -255,7 +255,7 @@ pub const Type = struct {
255255 const func = ies.func;
256256
257257 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
258 const owner_decl = mod.declPtr(mod.funcPtr(func).owner_decl);
258 const owner_decl = mod.funcOwnerDeclPtr(func);
259259 try owner_decl.renderFullyQualifiedName(mod, writer);
260260 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
261261 },
......@@ -367,7 +367,8 @@ pub const Type = struct {
367367 try writer.writeAll("noinline ");
368368 }
369369 try writer.writeAll("fn(");
370 for (fn_info.param_types, 0..) |param_ty, i| {
370 const param_types = fn_info.param_types.get(&mod.intern_pool);
371 for (param_types, 0..) |param_ty, i| {
371372 if (i != 0) try writer.writeAll(", ");
372373 if (std.math.cast(u5, i)) |index| {
373374 if (fn_info.paramIsComptime(index)) {
......@@ -384,7 +385,7 @@ pub const Type = struct {
384385 }
385386 }
386387 if (fn_info.is_var_args) {
387 if (fn_info.param_types.len != 0) {
388 if (param_types.len != 0) {
388389 try writer.writeAll(", ");
389390 }
390391 try writer.writeAll("...");
src/value.zig+8-5
......@@ -473,12 +473,15 @@ pub const Value = struct {
473473 };
474474 }
475475
476 pub fn getFunction(val: Value, mod: *Module) ?*Module.Fn {
477 return mod.funcPtrUnwrap(val.getFunctionIndex(mod));
476 pub fn isFuncBody(val: Value, mod: *Module) bool {
477 return mod.intern_pool.isFuncBody(val.toIntern());
478478 }
479479
480 pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex {
481 return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.toIntern()) else .none;
480 pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func {
481 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
482 .func => |x| x,
483 else => null,
484 };
482485 }
483486
484487 pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
......@@ -1462,7 +1465,7 @@ pub const Value = struct {
14621465 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
14631466 .variable => |variable| variable.decl,
14641467 .extern_func => |extern_func| extern_func.decl,
1465 .func => |func| mod.funcPtr(func.index).owner_decl,
1468 .func => |func| func.owner_decl,
14661469 .ptr => |ptr| switch (ptr.addr) {
14671470 .decl => |decl| decl,
14681471 .mut_decl => |mut_decl| mut_decl.decl,