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 {...@@ -1003,7 +1003,7 @@ pub const Inst = struct {
1003 },1003 },
1004 ty_fn: struct {1004 ty_fn: struct {
1005 ty: Ref,1005 ty: Ref,
1006 func: Module.Fn.Index,1006 func: InternPool.Index,
1007 },1007 },
1008 br: struct {1008 br: struct {
1009 block_inst: Index,1009 block_inst: Index,
src/Compilation.zig+4-3
...@@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig");...@@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig");
29const fatal = @import("main.zig").fatal;29const fatal = @import("main.zig").fatal;
30const clangMain = @import("main.zig").clangMain;30const clangMain = @import("main.zig").clangMain;
31const Module = @import("Module.zig");31const Module = @import("Module.zig");
32const InternPool = @import("InternPool.zig");
32const BuildId = std.Build.CompileStep.BuildId;33const BuildId = std.Build.CompileStep.BuildId;
33const Cache = std.Build.Cache;34const Cache = std.Build.Cache;
34const translate_c = @import("translate_c.zig");35const translate_c = @import("translate_c.zig");
...@@ -227,7 +228,8 @@ const Job = union(enum) {...@@ -227,7 +228,8 @@ const Job = union(enum) {
227 /// Write the constant value for a Decl to the output file.228 /// Write the constant value for a Decl to the output file.
228 codegen_decl: Module.Decl.Index,229 codegen_decl: Module.Decl.Index,
229 /// Write the machine code for a function to the output file.230 /// Write the machine code for a function to the output file.
230 codegen_func: Module.Fn.Index,231 /// This will either be a non-generic `func_decl` or a `func_instance`.
232 codegen_func: InternPool.Index,
231 /// Render the .h file snippet for the Decl.233 /// Render the .h file snippet for the Decl.
232 emit_h_decl: Module.Decl.Index,234 emit_h_decl: Module.Decl.Index,
233 /// The Decl needs to be analyzed and possibly export itself.235 /// The Decl needs to be analyzed and possibly export itself.
...@@ -3216,8 +3218,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v...@@ -3216,8 +3218,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
3216 // Tests are always emitted in test binaries. The decl_refs are created by3218 // Tests are always emitted in test binaries. The decl_refs are created by
3217 // Module.populateTestFunctions, but this will not queue body analysis, so do3219 // Module.populateTestFunctions, but this will not queue body analysis, so do
3218 // that now.3220 // that now.
3219 const func_index = module.intern_pool.indexToFunc(decl.val.ip_index).unwrap().?;3221 try module.ensureFuncBodyAnalysisQueued(decl.val.toIntern());
3220 try module.ensureFuncBodyAnalysisQueued(func_index);
3221 }3222 }
3222 },3223 },
3223 .update_embed_file => |embed_file| {3224 .update_embed_file => |embed_file| {
src/InternPool.zig+490-221
...@@ -34,19 +34,13 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},...@@ -34,19 +34,13 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},
34/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.34/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.
35unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},35unions_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
43/// InferredErrorSet objects are stored in this data structure because:37/// InferredErrorSet objects are stored in this data structure because:
44/// * They contain pointers such as the errors map and the set of other inferred error sets.38/// * They contain pointers such as the errors map and the set of other inferred error sets.
45/// * They need to be mutated after creation.39/// * 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) = .{},
47/// When a Struct object is freed from `allocated_inferred_error_sets`, it is41/// When a Struct object is freed from `allocated_inferred_error_sets`, it is
48/// pushed into this stack.42/// 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
51/// Some types such as enums, structs, and unions need to store mappings from field names45/// Some types such as enums, structs, and unions need to store mappings from field names
52/// to field index, or value to field index. In such cases, they will store the underlying46/// 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;...@@ -73,6 +67,7 @@ const Hash = std.hash.Wyhash;
7367
74const InternPool = @This();68const InternPool = @This();
75const Module = @import("Module.zig");69const Module = @import("Module.zig");
70const Zir = @import("Zir.zig");
76const Sema = @import("Sema.zig");71const Sema = @import("Sema.zig");
7772
78const KeyAdapter = struct {73const KeyAdapter = struct {
...@@ -224,7 +219,7 @@ pub const Key = union(enum) {...@@ -224,7 +219,7 @@ pub const Key = union(enum) {
224 enum_type: EnumType,219 enum_type: EnumType,
225 func_type: FuncType,220 func_type: FuncType,
226 error_set_type: ErrorSetType,221 error_set_type: ErrorSetType,
227 inferred_error_set_type: Module.Fn.InferredErrorSet.Index,222 inferred_error_set_type: Module.InferredErrorSet.Index,
228223
229 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented224 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
230 /// via `simple_value` and has a named `Index` tag for it.225 /// via `simple_value` and has a named `Index` tag for it.
...@@ -487,7 +482,7 @@ pub const Key = union(enum) {...@@ -487,7 +482,7 @@ pub const Key = union(enum) {
487 };482 };
488483
489 pub const FuncType = struct {484 pub const FuncType = struct {
490 param_types: []Index,485 param_types: Index.Slice,
491 return_type: Index,486 return_type: Index,
492 /// Tells whether a parameter is comptime. See `paramIsComptime` helper487 /// Tells whether a parameter is comptime. See `paramIsComptime` helper
493 /// method for accessing this.488 /// method for accessing this.
...@@ -541,10 +536,61 @@ pub const Key = union(enum) {...@@ -541,10 +536,61 @@ pub const Key = union(enum) {
541 lib_name: OptionalNullTerminatedString,536 lib_name: OptionalNullTerminatedString,
542 };537 };
543538
544 /// Extern so it can be hashed by reinterpreting memory.539 pub const Func = struct {
545 pub const Func = extern 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.
546 ty: Index,542 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 }
548 };594 };
549595
550 pub const Int = struct {596 pub const Int = struct {
...@@ -679,7 +725,7 @@ pub const Key = union(enum) {...@@ -679,7 +725,7 @@ pub const Key = union(enum) {
679 };725 };
680726
681 pub const MemoizedCall = struct {727 pub const MemoizedCall = struct {
682 func: Module.Fn.Index,728 func: Index,
683 arg_values: []const Index,729 arg_values: []const Index,
684 result: Index,730 result: Index,
685 };731 };
...@@ -695,7 +741,6 @@ pub const Key = union(enum) {...@@ -695,7 +741,6 @@ pub const Key = union(enum) {
695 return switch (key) {741 return switch (key) {
696 // TODO: assert no padding in these types742 // TODO: assert no padding in these types
697 inline .ptr_type,743 inline .ptr_type,
698 .func,
699 .array_type,744 .array_type,
700 .vector_type,745 .vector_type,
701 .opt_type,746 .opt_type,
...@@ -723,20 +768,11 @@ pub const Key = union(enum) {...@@ -723,20 +768,11 @@ pub const Key = union(enum) {
723 },768 },
724769
725 .runtime_value => |x| Hash.hash(seed, asBytes(&x.val)),770 .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| {772 inline .opaque_type,
735 var hasher = Hash.init(seed);773 .enum_type,
736 std.hash.autoHash(&hasher, variable.decl);774 .variable,
737 return hasher.final();775 => |x| Hash.hash(seed, asBytes(&x.decl)),
738 },
739 .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)),
740776
741 .int => |int| {777 .int => |int| {
742 var hasher = Hash.init(seed);778 var hasher = Hash.init(seed);
...@@ -875,7 +911,9 @@ pub const Key = union(enum) {...@@ -875,7 +911,9 @@ pub const Key = union(enum) {
875911
876 .func_type => |func_type| {912 .func_type => |func_type| {
877 var hasher = Hash.init(seed);913 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 }
879 std.hash.autoHash(&hasher, func_type.return_type);917 std.hash.autoHash(&hasher, func_type.return_type);
880 std.hash.autoHash(&hasher, func_type.comptime_bits);918 std.hash.autoHash(&hasher, func_type.comptime_bits);
881 std.hash.autoHash(&hasher, func_type.noalias_bits);919 std.hash.autoHash(&hasher, func_type.noalias_bits);
...@@ -893,6 +931,19 @@ pub const Key = union(enum) {...@@ -893,6 +931,19 @@ pub const Key = union(enum) {
893 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg);931 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg);
894 return hasher.final();932 return hasher.final();
895 },933 },
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)),
896 };947 };
897 }948 }
898949
...@@ -993,7 +1044,17 @@ pub const Key = union(enum) {...@@ -993,7 +1044,17 @@ pub const Key = union(enum) {
993 },1044 },
994 .func => |a_info| {1045 .func => |a_info| {
995 const b_info = b.func;1046 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));
997 },1058 },
9981059
999 .ptr => |a_info| {1060 .ptr => |a_info| {
...@@ -1155,7 +1216,7 @@ pub const Key = union(enum) {...@@ -1155,7 +1216,7 @@ pub const Key = union(enum) {
1155 .func_type => |a_info| {1216 .func_type => |a_info| {
1156 const b_info = b.func_type;1217 const b_info = b.func_type;
11571218
1158 return std.mem.eql(Index, a_info.param_types, b_info.param_types) and1219 return std.mem.eql(Index, a_info.param_types.get(ip), b_info.param_types.get(ip)) and
1159 a_info.return_type == b_info.return_type and1220 a_info.return_type == b_info.return_type and
1160 a_info.comptime_bits == b_info.comptime_bits and1221 a_info.comptime_bits == b_info.comptime_bits and
1161 a_info.noalias_bits == b_info.noalias_bits and1222 a_info.noalias_bits == b_info.noalias_bits and
...@@ -1360,6 +1421,18 @@ pub const Index = enum(u32) {...@@ -1360,6 +1421,18 @@ pub const Index = enum(u32) {
13601421
1361 _,1422 _,
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
1363 pub fn toType(i: Index) @import("type.zig").Type {1436 pub fn toType(i: Index) @import("type.zig").Type {
1364 assert(i != .none);1437 assert(i != .none);
1365 return .{ .ip_index = i };1438 return .{ .ip_index = i };
...@@ -1390,6 +1463,7 @@ pub const Index = enum(u32) {...@@ -1390,6 +1463,7 @@ pub const Index = enum(u32) {
13901463
1391 /// This function is used in the debugger pretty formatters in tools/ to fetch the1464 /// This function is used in the debugger pretty formatters in tools/ to fetch the
1392 /// Tag to encoding mapping to facilitate fancy debug printing for this type.1465 /// Tag to encoding mapping to facilitate fancy debug printing for this type.
1466 /// TODO merge this with `Tag.Payload`.
1393 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {1467 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {
1394 const DataIsIndex = struct { data: Index };1468 const DataIsIndex = struct { data: Index };
1395 const DataIsExtraIndexOfEnumExplicit = struct {1469 const DataIsExtraIndexOfEnumExplicit = struct {
...@@ -1427,11 +1501,11 @@ pub const Index = enum(u32) {...@@ -1427,11 +1501,11 @@ pub const Index = enum(u32) {
1427 type_error_union: struct { data: *Key.ErrorUnionType },1501 type_error_union: struct { data: *Key.ErrorUnionType },
1428 type_error_set: struct {1502 type_error_set: struct {
1429 const @"data.names_len" = opaque {};1503 const @"data.names_len" = opaque {};
1430 data: *ErrorSet,1504 data: *Tag.ErrorSet,
1431 @"trailing.names.len": *@"data.names_len",1505 @"trailing.names.len": *@"data.names_len",
1432 trailing: struct { names: []NullTerminatedString },1506 trailing: struct { names: []NullTerminatedString },
1433 },1507 },
1434 type_inferred_error_set: struct { data: Module.Fn.InferredErrorSet.Index },1508 type_inferred_error_set: struct { data: Module.InferredErrorSet.Index },
1435 type_enum_auto: struct {1509 type_enum_auto: struct {
1436 const @"data.fields_len" = opaque {};1510 const @"data.fields_len" = opaque {};
1437 data: *EnumAuto,1511 data: *EnumAuto,
...@@ -1451,7 +1525,7 @@ pub const Index = enum(u32) {...@@ -1451,7 +1525,7 @@ pub const Index = enum(u32) {
1451 type_union_safety: struct { data: Module.Union.Index },1525 type_union_safety: struct { data: Module.Union.Index },
1452 type_function: struct {1526 type_function: struct {
1453 const @"data.params_len" = opaque {};1527 const @"data.params_len" = opaque {};
1454 data: *TypeFunction,1528 data: *Tag.TypeFunction,
1455 @"trailing.param_types.len": *@"data.params_len",1529 @"trailing.param_types.len": *@"data.params_len",
1456 trailing: struct { param_types: []Index },1530 trailing: struct { param_types: []Index },
1457 },1531 },
...@@ -1497,7 +1571,8 @@ pub const Index = enum(u32) {...@@ -1497,7 +1571,8 @@ pub const Index = enum(u32) {
1497 float_comptime_float: struct { data: *Float128 },1571 float_comptime_float: struct { data: *Float128 },
1498 variable: struct { data: *Tag.Variable },1572 variable: struct { data: *Tag.Variable },
1499 extern_func: struct { data: *Key.ExternFunc },1573 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 },
1501 only_possible_value: DataIsIndex,1576 only_possible_value: DataIsIndex,
1502 union_value: struct { data: *Key.Union },1577 union_value: struct { data: *Key.Union },
1503 bytes: struct { data: *Bytes },1578 bytes: struct { data: *Bytes },
...@@ -1826,7 +1901,7 @@ pub const Tag = enum(u8) {...@@ -1826,7 +1901,7 @@ pub const Tag = enum(u8) {
1826 /// data is payload to `ErrorSet`.1901 /// data is payload to `ErrorSet`.
1827 type_error_set,1902 type_error_set,
1828 /// The inferred error set type of a function.1903 /// The inferred error set type of a function.
1829 /// data is `Module.Fn.InferredErrorSet.Index`.1904 /// data is `Module.InferredErrorSet.Index`.
1830 type_inferred_error_set,1905 type_inferred_error_set,
1831 /// An enum type with auto-numbered tag values.1906 /// An enum type with auto-numbered tag values.
1832 /// The enum is exhaustive.1907 /// The enum is exhaustive.
...@@ -2005,11 +2080,16 @@ pub const Tag = enum(u8) {...@@ -2005,11 +2080,16 @@ pub const Tag = enum(u8) {
2005 /// data is extra index to Variable.2080 /// data is extra index to Variable.
2006 variable,2081 variable,
2007 /// An extern function.2082 /// An extern function.
2008 /// data is extra index to Key.ExternFunc.2083 /// data is extra index to ExternFunc.
2009 extern_func,2084 extern_func,
2010 /// A regular function.2085 /// A non-extern function corresponding directly to the AST node from whence it originated.
2011 /// data is extra index to Func.2086 /// data is extra index to `FuncDecl`.
2012 func,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,
2013 /// This represents the only possible value for *some* types which have2093 /// This represents the only possible value for *some* types which have
2014 /// only one possible value. Not all only-possible-values are encoded this way;2094 /// only one possible value. Not all only-possible-values are encoded this way;
2015 /// for example structs which have all comptime fields are not encoded this way.2095 /// for example structs which have all comptime fields are not encoded this way.
...@@ -2114,7 +2194,8 @@ pub const Tag = enum(u8) {...@@ -2114,7 +2194,8 @@ pub const Tag = enum(u8) {
2114 .float_comptime_float => unreachable,2194 .float_comptime_float => unreachable,
2115 .variable => Variable,2195 .variable => Variable,
2116 .extern_func => ExternFunc,2196 .extern_func => ExternFunc,
2117 .func => Func,2197 .func_decl => FuncDecl,
2198 .func_instance => FuncInstance,
2118 .only_possible_value => unreachable,2199 .only_possible_value => unreachable,
2119 .union_value => Union,2200 .union_value => Union,
2120 .bytes => Bytes,2201 .bytes => Bytes,
...@@ -2150,36 +2231,93 @@ pub const Tag = enum(u8) {...@@ -2150,36 +2231,93 @@ pub const Tag = enum(u8) {
2150 /// The type of the aggregate.2231 /// The type of the aggregate.
2151 ty: Index,2232 ty: Index,
2152 };2233 };
2153};
21542234
2155/// Trailing:2235 pub const FuncDecl = struct {
2156/// 0. name: NullTerminatedString for each names_len2236 analysis: FuncAnalysis,
2157pub const ErrorSet = struct {2237 owner_decl: Module.Decl.Index,
2158 names_len: u32,2238 ty: Index,
2159 /// Maps error names to declaration index.2239 zir_body_inst: Zir.Inst.Index,
2160 names_map: MapIndex,2240 lbrace_line: u32,
2161};2241 rbrace_line: u32,
2242 lbrace_column: u32,
2243 rbrace_column: u32,
2244 };
21622245
2163/// Trailing:2246 /// Trailing:
2164/// 0. param_type: Index for each params_len2247 /// 0. For each parameter of generic_owner: Index
2165pub const TypeFunction = struct {2248 /// - comptime parameter: the comptime-known value
2166 params_len: u32,2249 /// - anytype parameter: the type of the runtime-known value
2167 return_type: Index,2250 /// - otherwise: `none`
2168 comptime_bits: u32,2251 pub const FuncInstance = struct {
2169 noalias_bits: u32,2252 analysis: FuncAnalysis,
2170 flags: Flags,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) {2261 /// Trailing:
2173 alignment: Alignment,2262 /// 0. name: NullTerminatedString for each names_len
2174 cc: std.builtin.CallingConvention,2263 pub const ErrorSet = struct {
2175 is_var_args: bool,2264 names_len: u32,
2176 is_generic: bool,2265 /// Maps error names to declaration index.
2177 is_noinline: bool,2266 names_map: MapIndex,
2178 align_is_generic: bool,2267 };
2179 cc_is_generic: bool,2268
2180 section_is_generic: bool,2269 /// Trailing:
2181 addrspace_is_generic: bool,2270 /// 0. comptime_bits: u32, // if has_comptime_bits
2182 _: u11 = 0,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,
2183 };2321 };
2184};2322};
21852323
...@@ -2499,7 +2637,7 @@ pub const Float128 = struct {...@@ -2499,7 +2637,7 @@ pub const Float128 = struct {
2499/// Trailing:2637/// Trailing:
2500/// 0. arg value: Index for each args_len2638/// 0. arg value: Index for each args_len
2501pub const MemoizedCall = struct {2639pub const MemoizedCall = struct {
2502 func: Module.Fn.Index,2640 func: Index,
2503 args_len: u32,2641 args_len: u32,
2504 result: Index,2642 result: Index,
2505};2643};
...@@ -2553,9 +2691,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {...@@ -2553,9 +2691,6 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
2553 ip.unions_free_list.deinit(gpa);2691 ip.unions_free_list.deinit(gpa);
2554 ip.allocated_unions.deinit(gpa);2692 ip.allocated_unions.deinit(gpa);
25552693
2556 ip.funcs_free_list.deinit(gpa);
2557 ip.allocated_funcs.deinit(gpa);
2558
2559 ip.inferred_error_sets_free_list.deinit(gpa);2694 ip.inferred_error_sets_free_list.deinit(gpa);
2560 ip.allocated_inferred_error_sets.deinit(gpa);2695 ip.allocated_inferred_error_sets.deinit(gpa);
25612696
...@@ -2625,21 +2760,21 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2625,21 +2760,21 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
26252760
2626 .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) },2761 .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) },
2627 .type_error_set => {2762 .type_error_set => {
2628 const error_set = ip.extraDataTrail(ErrorSet, data);2763 const error_set = ip.extraDataTrail(Tag.ErrorSet, data);
2629 const names_len = error_set.data.names_len;2764 const names_len = error_set.data.names_len;
2630 const names = ip.extra.items[error_set.end..][0..names_len];2765 const names = ip.extra.items[error_set.end..][0..names_len];
2631 return .{ .error_set_type = .{2766 return .{ .error_set_type = .{
2632 .names = @as([]const NullTerminatedString, @ptrCast(names)),2767 .names = @ptrCast(names),
2633 .names_map = error_set.data.names_map.toOptional(),2768 .names_map = error_set.data.names_map.toOptional(),
2634 } };2769 } };
2635 },2770 },
2636 .type_inferred_error_set => .{2771 .type_inferred_error_set => .{
2637 .inferred_error_set_type = @as(Module.Fn.InferredErrorSet.Index, @enumFromInt(data)),2772 .inferred_error_set_type = @enumFromInt(data),
2638 },2773 },
26392774
2640 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },2775 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
2641 .type_struct => {2776 .type_struct => {
2642 const struct_index = @as(Module.Struct.OptionalIndex, @enumFromInt(data));2777 const struct_index: Module.Struct.OptionalIndex = @enumFromInt(data);
2643 const namespace = if (struct_index.unwrap()) |i|2778 const namespace = if (struct_index.unwrap()) |i|
2644 ip.structPtrConst(i).namespace.toOptional()2779 ip.structPtrConst(i).namespace.toOptional()
2645 else2780 else
...@@ -2661,9 +2796,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2661,9 +2796,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2661 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];2796 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
2662 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];2797 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];
2663 return .{ .anon_struct_type = .{2798 return .{ .anon_struct_type = .{
2664 .types = @as([]const Index, @ptrCast(types)),2799 .types = @ptrCast(types),
2665 .values = @as([]const Index, @ptrCast(values)),2800 .values = @ptrCast(values),
2666 .names = @as([]const NullTerminatedString, @ptrCast(names)),2801 .names = @ptrCast(names),
2667 } };2802 } };
2668 },2803 },
2669 .type_tuple_anon => {2804 .type_tuple_anon => {
...@@ -2672,8 +2807,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2672,8 +2807,8 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2672 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];2807 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
2673 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];2808 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
2674 return .{ .anon_struct_type = .{2809 return .{ .anon_struct_type = .{
2675 .types = @as([]const Index, @ptrCast(types)),2810 .types = @ptrCast(types),
2676 .values = @as([]const Index, @ptrCast(values)),2811 .values = @ptrCast(values),
2677 .names = &.{},2812 .names = &.{},
2678 } };2813 } };
2679 },2814 },
...@@ -2957,7 +3092,12 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -2957,7 +3092,12 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2957 } };3092 } };
2958 },3093 },
2959 .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) },3094 .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 },
2961 .only_possible_value => {3101 .only_possible_value => {
2962 const ty = @as(Index, @enumFromInt(data));3102 const ty = @as(Index, @enumFromInt(data));
2963 const ty_item = ip.items.get(@intFromEnum(ty));3103 const ty_item = ip.items.get(@intFromEnum(ty));
...@@ -3063,25 +3203,39 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -3063,25 +3203,39 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
3063}3203}
30643204
3065fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType {3205fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType {
3066 const type_function = ip.extraDataTrail(TypeFunction, data);3206 const type_function = ip.extraDataTrail(Tag.TypeFunction, data);
3067 const param_types = @as(3207 var index: usize = type_function.end;
3068 []Index,3208 const comptime_bits: u32 = if (!type_function.data.flags.has_comptime_bits) 0 else b: {
3069 @ptrCast(ip.extra.items[type_function.end..][0..type_function.data.params_len]),3209 const x = ip.extra.items[index];
3070 );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 };
3071 return .{3218 return .{
3072 .param_types = param_types,3219 .param_types = .{
3220 .start = @intCast(index),
3221 .len = type_function.data.params_len,
3222 },
3073 .return_type = type_function.data.return_type,3223 .return_type = type_function.data.return_type,
3074 .comptime_bits = type_function.data.comptime_bits,3224 .comptime_bits = comptime_bits,
3075 .noalias_bits = type_function.data.noalias_bits,3225 .noalias_bits = noalias_bits,
3076 .alignment = type_function.data.flags.alignment,3226 .alignment = type_function.data.flags.alignment,
3077 .cc = type_function.data.flags.cc,3227 .cc = type_function.data.flags.cc,
3078 .is_var_args = type_function.data.flags.is_var_args,3228 .is_var_args = type_function.data.flags.is_var_args,
3079 .is_generic = type_function.data.flags.is_generic,
3080 .is_noinline = type_function.data.flags.is_noinline,3229 .is_noinline = type_function.data.flags.is_noinline,
3081 .align_is_generic = type_function.data.flags.align_is_generic,3230 .align_is_generic = type_function.data.flags.align_is_generic,
3082 .cc_is_generic = type_function.data.flags.cc_is_generic,3231 .cc_is_generic = type_function.data.flags.cc_is_generic,
3083 .section_is_generic = type_function.data.flags.section_is_generic,3232 .section_is_generic = type_function.data.flags.section_is_generic,
3084 .addrspace_is_generic = type_function.data.flags.addrspace_is_generic,3233 .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,
3085 };3239 };
3086}3240}
30873241
...@@ -3224,10 +3378,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3224,10 +3378,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3224 const names_map = try ip.addMap(gpa);3378 const names_map = try ip.addMap(gpa);
3225 try addStringsToMap(ip, gpa, names_map, error_set_type.names);3379 try addStringsToMap(ip, gpa, names_map, error_set_type.names);
3226 const names_len = @as(u32, @intCast(error_set_type.names.len));3380 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);
3228 ip.items.appendAssumeCapacity(.{3382 ip.items.appendAssumeCapacity(.{
3229 .tag = .type_error_set,3383 .tag = .type_error_set,
3230 .data = ip.addExtraAssumeCapacity(ErrorSet{3384 .data = ip.addExtraAssumeCapacity(Tag.ErrorSet{
3231 .names_len = names_len,3385 .names_len = names_len,
3232 .names_map = names_map,3386 .names_map = names_map,
3233 }),3387 }),
...@@ -3369,36 +3523,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3369,36 +3523,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3369 }3523 }
3370 },3524 },
33713525
3372 .func_type => |func_type| {3526 .func_type => unreachable, // use getFuncType() instead
3373 assert(func_type.return_type != .none);3527 .extern_func => unreachable, // use getExternFunc() instead
3374 for (func_type.param_types) |param_type| assert(param_type != .none);3528 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead
3375
3376 const params_len = @as(u32, @intCast(func_type.param_types.len));
3377
3378 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(TypeFunction).Struct.fields.len +
3379 params_len);
3380 ip.items.appendAssumeCapacity(.{
3381 .tag = .type_function,
3382 .data = ip.addExtraAssumeCapacity(TypeFunction{
3383 .params_len = params_len,
3384 .return_type = func_type.return_type,
3385 .comptime_bits = func_type.comptime_bits,
3386 .noalias_bits = func_type.noalias_bits,
3387 .flags = .{
3388 .alignment = func_type.alignment,
3389 .cc = func_type.cc,
3390 .is_var_args = func_type.is_var_args,
3391 .is_generic = func_type.is_generic,
3392 .is_noinline = func_type.is_noinline,
3393 .align_is_generic = func_type.align_is_generic,
3394 .cc_is_generic = func_type.cc_is_generic,
3395 .section_is_generic = func_type.section_is_generic,
3396 .addrspace_is_generic = func_type.addrspace_is_generic,
3397 },
3398 }),
3399 });
3400 ip.extra.appendSliceAssumeCapacity(@as([]const u32, @ptrCast(func_type.param_types)));
3401 },
34023529
3403 .variable => |variable| {3530 .variable => |variable| {
3404 const has_init = variable.init != .none;3531 const has_init = variable.init != .none;
...@@ -3420,16 +3547,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3420,16 +3547,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3420 });3547 });
3421 },3548 },
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
3433 .ptr => |ptr| {3550 .ptr => |ptr| {
3434 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;3551 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
3435 switch (ptr.len) {3552 switch (ptr.len) {
...@@ -4068,6 +4185,147 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4068,6 +4185,147 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4068 return @as(Index, @enumFromInt(ip.items.len - 1));4185 return @as(Index, @enumFromInt(ip.items.len - 1));
4069}4186}
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
4071/// Provides API for completing an enum type after calling `getIncompleteEnum`.4329/// Provides API for completing an enum type after calling `getIncompleteEnum`.
4072pub const IncompleteEnumType = struct {4330pub const IncompleteEnumType = struct {
4073 index: Index,4331 index: Index,
...@@ -4347,7 +4605,6 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -4347,7 +4605,6 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
4347 Module.Decl.Index => @intFromEnum(@field(extra, field.name)),4605 Module.Decl.Index => @intFromEnum(@field(extra, field.name)),
4348 Module.Namespace.Index => @intFromEnum(@field(extra, field.name)),4606 Module.Namespace.Index => @intFromEnum(@field(extra, field.name)),
4349 Module.Namespace.OptionalIndex => @intFromEnum(@field(extra, field.name)),4607 Module.Namespace.OptionalIndex => @intFromEnum(@field(extra, field.name)),
4350 Module.Fn.Index => @intFromEnum(@field(extra, field.name)),
4351 MapIndex => @intFromEnum(@field(extra, field.name)),4608 MapIndex => @intFromEnum(@field(extra, field.name)),
4352 OptionalMapIndex => @intFromEnum(@field(extra, field.name)),4609 OptionalMapIndex => @intFromEnum(@field(extra, field.name)),
4353 RuntimeIndex => @intFromEnum(@field(extra, field.name)),4610 RuntimeIndex => @intFromEnum(@field(extra, field.name)),
...@@ -4356,7 +4613,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -4356,7 +4613,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
4356 OptionalNullTerminatedString => @intFromEnum(@field(extra, field.name)),4613 OptionalNullTerminatedString => @intFromEnum(@field(extra, field.name)),
4357 i32 => @as(u32, @bitCast(@field(extra, field.name))),4614 i32 => @as(u32, @bitCast(@field(extra, field.name))),
4358 Tag.TypePointer.Flags => @as(u32, @bitCast(@field(extra, field.name))),4615 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))),
4360 Tag.TypePointer.PackedOffset => @as(u32, @bitCast(@field(extra, field.name))),4617 Tag.TypePointer.PackedOffset => @as(u32, @bitCast(@field(extra, field.name))),
4361 Tag.TypePointer.VectorIndex => @intFromEnum(@field(extra, field.name)),4618 Tag.TypePointer.VectorIndex => @intFromEnum(@field(extra, field.name)),
4362 Tag.Variable.Flags => @as(u32, @bitCast(@field(extra, field.name))),4619 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...@@ -4411,23 +4668,28 @@ fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct
4411 const int32 = ip.extra.items[i + index];4668 const int32 = ip.extra.items[i + index];
4412 @field(result, field.name) = switch (field.type) {4669 @field(result, field.name) = switch (field.type) {
4413 u32 => int32,4670 u32 => int32,
4414 Index => @as(Index, @enumFromInt(int32)),4671
4415 Module.Decl.Index => @as(Module.Decl.Index, @enumFromInt(int32)),4672 Index,
4416 Module.Namespace.Index => @as(Module.Namespace.Index, @enumFromInt(int32)),4673 Module.Decl.Index,
4417 Module.Namespace.OptionalIndex => @as(Module.Namespace.OptionalIndex, @enumFromInt(int32)),4674 Module.Namespace.Index,
4418 Module.Fn.Index => @as(Module.Fn.Index, @enumFromInt(int32)),4675 Module.Namespace.OptionalIndex,
4419 MapIndex => @as(MapIndex, @enumFromInt(int32)),4676 MapIndex,
4420 OptionalMapIndex => @as(OptionalMapIndex, @enumFromInt(int32)),4677 OptionalMapIndex,
4421 RuntimeIndex => @as(RuntimeIndex, @enumFromInt(int32)),4678 RuntimeIndex,
4422 String => @as(String, @enumFromInt(int32)),4679 String,
4423 NullTerminatedString => @as(NullTerminatedString, @enumFromInt(int32)),4680 NullTerminatedString,
4424 OptionalNullTerminatedString => @as(OptionalNullTerminatedString, @enumFromInt(int32)),4681 OptionalNullTerminatedString,
4425 i32 => @as(i32, @bitCast(int32)),4682 Tag.TypePointer.VectorIndex,
4426 Tag.TypePointer.Flags => @as(Tag.TypePointer.Flags, @bitCast(int32)),4683 => @enumFromInt(int32),
4427 TypeFunction.Flags => @as(TypeFunction.Flags, @bitCast(int32)),4684
4428 Tag.TypePointer.PackedOffset => @as(Tag.TypePointer.PackedOffset, @bitCast(int32)),4685 i32,
4429 Tag.TypePointer.VectorIndex => @as(Tag.TypePointer.VectorIndex, @enumFromInt(int32)),4686 Tag.TypePointer.Flags,
4430 Tag.Variable.Flags => @as(Tag.Variable.Flags, @bitCast(int32)),4687 Tag.TypeFunction.Flags,
4688 Tag.TypePointer.PackedOffset,
4689 Tag.Variable.Flags,
4690 FuncAnalysis,
4691 => @bitCast(int32),
4692
4431 else => @compileError("bad field type: " ++ @typeName(field.type)),4693 else => @compileError("bad field type: " ++ @typeName(field.type)),
4432 };4694 };
4433 }4695 }
...@@ -4627,11 +4889,15 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al...@@ -4627,11 +4889,15 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
4627 .decl = extern_func.decl,4889 .decl = extern_func.decl,
4628 .lib_name = extern_func.lib_name,4890 .lib_name = extern_func.lib_name,
4629 } }),4891 } }),
4630 .func => |func| if (ip.isFunctionType(new_ty))4892
4631 return ip.get(gpa, .{ .func = .{4893 .func => |func| {
4632 .ty = new_ty,4894 if (func.generic_owner == .none) {
4633 .index = func.index,4895 @panic("TODO");
4634 } }),4896 } else {
4897 @panic("TODO");
4898 }
4899 },
4900
4635 .int => |int| switch (ip.indexToKey(new_ty)) {4901 .int => |int| switch (ip.indexToKey(new_ty)) {
4636 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{4902 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
4637 .ty = new_ty,4903 .ty = new_ty,
...@@ -4886,20 +5152,12 @@ pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType {...@@ -4886,20 +5152,12 @@ pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType {
4886 }5152 }
4887}5153}
48885154
4889pub fn indexToFunc(ip: *const InternPool, val: Index) Module.Fn.OptionalIndex {5155pub fn indexToInferredErrorSetType(ip: *const InternPool, val: Index) Module.InferredErrorSet.OptionalIndex {
4890 assert(val != .none);
4891 const tags = ip.items.items(.tag);
4892 if (tags[@intFromEnum(val)] != .func) return .none;
4893 const datas = ip.items.items(.data);
4894 return ip.extraData(Tag.Func, datas[@intFromEnum(val)]).index.toOptional();
4895}
4896
4897pub fn indexToInferredErrorSetType(ip: *const InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex {
4898 assert(val != .none);5156 assert(val != .none);
4899 const tags = ip.items.items(.tag);5157 const tags = ip.items.items(.tag);
4900 if (tags[@intFromEnum(val)] != .type_inferred_error_set) return .none;5158 if (tags[@intFromEnum(val)] != .type_inferred_error_set) return .none;
4901 const datas = ip.items.items(.data);5159 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();
4903}5161}
49045162
4905/// includes .comptime_int_type5163/// includes .comptime_int_type
...@@ -4994,12 +5252,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -4994,12 +5252,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
4994 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));5252 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
4995 const unions_size = ip.allocated_unions.len *5253 const unions_size = ip.allocated_unions.len *
4996 (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));5254 (@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
5000 // TODO: map overhead size is not taken into account5256 // TODO: map overhead size is not taken into account
5001 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +5257 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +
5002 structs_size + unions_size + funcs_size;5258 structs_size + unions_size;
50035259
5004 std.debug.print(5260 std.debug.print(
5005 \\InternPool size: {d} bytes5261 \\InternPool size: {d} bytes
...@@ -5008,7 +5264,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5008,7 +5264,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5008 \\ {d} limbs: {d} bytes5264 \\ {d} limbs: {d} bytes
5009 \\ {d} structs: {d} bytes5265 \\ {d} structs: {d} bytes
5010 \\ {d} unions: {d} bytes5266 \\ {d} unions: {d} bytes
5011 \\ {d} funcs: {d} bytes
5012 \\5267 \\
5013 , .{5268 , .{
5014 total_size,5269 total_size,
...@@ -5022,8 +5277,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5022,8 +5277,6 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5022 structs_size,5277 structs_size,
5023 ip.allocated_unions.len,5278 ip.allocated_unions.len,
5024 unions_size,5279 unions_size,
5025 ip.allocated_funcs.len,
5026 funcs_size,
5027 });5280 });
50285281
5029 const tags = ip.items.items(.tag);5282 const tags = ip.items.items(.tag);
...@@ -5049,10 +5302,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5049,10 +5302,10 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5049 .type_anyframe => 0,5302 .type_anyframe => 0,
5050 .type_error_union => @sizeOf(Key.ErrorUnionType),5303 .type_error_union => @sizeOf(Key.ErrorUnionType),
5051 .type_error_set => b: {5304 .type_error_set => b: {
5052 const info = ip.extraData(ErrorSet, data);5305 const info = ip.extraData(Tag.ErrorSet, data);
5053 break :b @sizeOf(ErrorSet) + (@sizeOf(u32) * info.names_len);5306 break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len);
5054 },5307 },
5055 .type_inferred_error_set => @sizeOf(Module.Fn.InferredErrorSet),5308 .type_inferred_error_set => @sizeOf(Module.InferredErrorSet),
5056 .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),5309 .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),
5057 .type_enum_auto => @sizeOf(EnumAuto),5310 .type_enum_auto => @sizeOf(EnumAuto),
5058 .type_opaque => @sizeOf(Key.OpaqueType),5311 .type_opaque => @sizeOf(Key.OpaqueType),
...@@ -5080,8 +5333,8 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5080,8 +5333,8 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5080 => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),5333 => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),
50815334
5082 .type_function => b: {5335 .type_function => b: {
5083 const info = ip.extraData(TypeFunction, data);5336 const info = ip.extraData(Tag.TypeFunction, data);
5084 break :b @sizeOf(TypeFunction) + (@sizeOf(Index) * info.params_len);5337 break :b @sizeOf(Tag.TypeFunction) + (@sizeOf(Index) * info.params_len);
5085 },5338 },
50865339
5087 .undef => 0,5340 .undef => 0,
...@@ -5130,7 +5383,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5130,7 +5383,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5130 },5383 },
5131 .aggregate => b: {5384 .aggregate => b: {
5132 const info = ip.extraData(Tag.Aggregate, data);5385 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));
5134 break :b @sizeOf(Tag.Aggregate) + (@sizeOf(Index) * fields_len);5387 break :b @sizeOf(Tag.Aggregate) + (@sizeOf(Index) * fields_len);
5135 },5388 },
5136 .repeated => @sizeOf(Repeated),5389 .repeated => @sizeOf(Repeated),
...@@ -5145,7 +5398,14 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -5145,7 +5398,14 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
5145 .float_comptime_float => @sizeOf(Float128),5398 .float_comptime_float => @sizeOf(Float128),
5146 .variable => @sizeOf(Tag.Variable) + @sizeOf(Module.Decl),5399 .variable => @sizeOf(Tag.Variable) + @sizeOf(Module.Decl),
5147 .extern_func => @sizeOf(Tag.ExternFunc) + @sizeOf(Module.Decl),5400 .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 },
5149 .only_possible_value => 0,5409 .only_possible_value => 0,
5150 .union_value => @sizeOf(Key.Union),5410 .union_value => @sizeOf(Key.Union),
51515411
...@@ -5249,7 +5509,8 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -5249,7 +5509,8 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
5249 .float_comptime_float,5509 .float_comptime_float,
5250 .variable,5510 .variable,
5251 .extern_func,5511 .extern_func,
5252 .func,5512 .func_decl,
5513 .func_instance,
5253 .union_value,5514 .union_value,
5254 .memoized_call,5515 .memoized_call,
5255 => try w.print("{d}", .{data}),5516 => try w.print("{d}", .{data}),
...@@ -5284,19 +5545,11 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo...@@ -5284,19 +5545,11 @@ pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Mo
5284 return ip.allocated_unions.at(@intFromEnum(index));5545 return ip.allocated_unions.at(@intFromEnum(index));
5285}5546}
52865547
5287pub fn funcPtr(ip: *InternPool, index: Module.Fn.Index) *Module.Fn {5548pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.InferredErrorSet.Index) *Module.InferredErrorSet {
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 {
5296 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));5549 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));
5297}5550}
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 {
5300 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));5553 return ip.allocated_inferred_error_sets.at(@intFromEnum(index));
5301}5554}
53025555
...@@ -5344,43 +5597,21 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)...@@ -5344,43 +5597,21 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)
5344 };5597 };
5345}5598}
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
5369pub fn createInferredErrorSet(5600pub fn createInferredErrorSet(
5370 ip: *InternPool,5601 ip: *InternPool,
5371 gpa: Allocator,5602 gpa: Allocator,
5372 initialization: Module.Fn.InferredErrorSet,5603 initialization: Module.InferredErrorSet,
5373) Allocator.Error!Module.Fn.InferredErrorSet.Index {5604) Allocator.Error!Module.InferredErrorSet.Index {
5374 if (ip.inferred_error_sets_free_list.popOrNull()) |index| {5605 if (ip.inferred_error_sets_free_list.popOrNull()) |index| {
5375 ip.allocated_inferred_error_sets.at(@intFromEnum(index)).* = initialization;5606 ip.allocated_inferred_error_sets.at(@intFromEnum(index)).* = initialization;
5376 return index;5607 return index;
5377 }5608 }
5378 const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);5609 const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);
5379 ptr.* = initialization;5610 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));
5381}5612}
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 {
5384 ip.inferredErrorSetPtr(index).* = undefined;5615 ip.inferredErrorSetPtr(index).* = undefined;
5385 ip.inferred_error_sets_free_list.append(gpa, index) catch {5616 ip.inferred_error_sets_free_list.append(gpa, index) catch {
5386 // In order to keep `destroyInferredErrorSet` a non-fallible function, we ignore memory5617 // 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 {...@@ -5620,7 +5851,8 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
5620 .enum_tag,5851 .enum_tag,
5621 .variable,5852 .variable,
5622 .extern_func,5853 .extern_func,
5623 .func,5854 .func_decl,
5855 .func_instance,
5624 .union_value,5856 .union_value,
5625 .bytes,5857 .bytes,
5626 .aggregate,5858 .aggregate,
...@@ -5704,7 +5936,7 @@ pub fn funcReturnType(ip: *const InternPool, ty: Index) Index {...@@ -5704,7 +5936,7 @@ pub fn funcReturnType(ip: *const InternPool, ty: Index) Index {
5704 };5936 };
5705 assert(child_item.tag == .type_function);5937 assert(child_item.tag == .type_function);
5706 return @as(Index, @enumFromInt(ip.extra.items[5938 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").?
5708 ]));5940 ]));
5709}5941}
57105942
...@@ -5712,7 +5944,7 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {...@@ -5712,7 +5944,7 @@ pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
5712 return switch (ty) {5944 return switch (ty) {
5713 .noreturn_type => true,5945 .noreturn_type => true,
5714 else => switch (ip.items.items(.tag)[@intFromEnum(ty)]) {5946 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,
5716 else => false,5948 else => false,
5717 },5949 },
5718 };5950 };
...@@ -5969,7 +6201,8 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -5969,7 +6201,8 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
5969 .float_comptime_float,6201 .float_comptime_float,
5970 .variable,6202 .variable,
5971 .extern_func,6203 .extern_func,
5972 .func,6204 .func_decl,
6205 .func_instance,
5973 .only_possible_value,6206 .only_possible_value,
5974 .union_value,6207 .union_value,
5975 .bytes,6208 .bytes,
...@@ -5982,3 +6215,39 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -5982,3 +6215,39 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
5982 .none => unreachable, // special tag6215 .none => unreachable, // special tag
5983 };6216 };
5984}6217}
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,...@@ -101,16 +101,6 @@ tmp_hack_arena: std.heap.ArenaAllocator,
101/// This is currently only used for string literals.101/// This is currently only used for string literals.
102memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},102memoized_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
114/// We optimize memory usage for a compilation with no compile errors by storing the104/// We optimize memory usage for a compilation with no compile errors by storing the
115/// error messages and mapping outside of `Decl`.105/// error messages and mapping outside of `Decl`.
116/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.106/// 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 {...@@ -189,7 +179,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
189}) = .{},179}) = .{},
190180
191panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len,181panic_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,
193null_stack_trace: InternPool.Index = .none,184null_stack_trace: InternPool.Index = .none,
194185
195pub const PanicId = enum {186pub const PanicId = enum {
...@@ -239,50 +230,6 @@ pub const CImportError = struct {...@@ -239,50 +230,6 @@ pub const CImportError = struct {
239 }230 }
240};231};
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
286/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.233/// A `Module` has zero or one of these depending on whether `-femit-h` is enabled.
287pub const GlobalEmitH = struct {234pub const GlobalEmitH = struct {
288 /// Where to put the output.235 /// Where to put the output.
...@@ -625,13 +572,6 @@ pub const Decl = struct {...@@ -625,13 +572,6 @@ pub const Decl = struct {
625 function_body,572 function_body,
626 };573 };
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
635 /// This name is relative to the containing namespace of the decl.575 /// This name is relative to the containing namespace of the decl.
636 /// The memory is owned by the containing File ZIR.576 /// The memory is owned by the containing File ZIR.
637 pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {577 pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {
...@@ -816,14 +756,17 @@ pub const Decl = struct {...@@ -816,14 +756,17 @@ pub const Decl = struct {
816 return mod.typeToUnion(decl.val.toType());756 return mod.typeToUnion(decl.val.toType());
817 }757 }
818758
819 /// If the Decl owns its value and it is a function, return it,759 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?InternPool.Key.Func {
820 /// otherwise null.760 const i = decl.getOwnedFunctionIndex();
821 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?*Fn {761 if (i == .none) return null;
822 return mod.funcPtrUnwrap(decl.getOwnedFunctionIndex(mod));762 return switch (mod.intern_pool.indexToKey(i)) {
763 .func => |func| func,
764 else => null,
765 };
823 }766 }
824767
825 pub fn getOwnedFunctionIndex(decl: Decl, mod: *Module) Fn.OptionalIndex {768 pub fn getOwnedFunctionIndex(decl: Decl) InternPool.Index {
826 return if (decl.owns_tv) decl.val.getFunctionIndex(mod) else .none;769 return if (decl.owns_tv) decl.val.toIntern() else .none;
827 }770 }
828771
829 /// If the Decl owns its value and it is an extern function, returns it,772 /// If the Decl owns its value and it is an extern function, returns it,
...@@ -1385,71 +1328,39 @@ pub const ExternFn = struct {...@@ -1385,71 +1328,39 @@ pub const ExternFn = struct {
1385 }1328 }
1386};1329};
13871330
1388/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.1331/// This struct is used to keep track of any dependencies related to functions instances
1389/// Extern functions do not have this data structure; they are represented by `ExternFn`1332/// that return inferred error sets. Note that a function may be associated to
1390/// instead.1333/// multiple different error sets, for example an inferred error set which
1391pub const Fn = struct {1334/// this function returns, but also any inferred error sets of called inline
1392 /// The Decl that corresponds to the function itself.1335/// or comptime functions.
1393 owner_decl: Decl.Index,1336pub const InferredErrorSet = struct {
1394 /// The ZIR instruction that is a function instruction. Use this to find1337 /// The function from which this error set originates.
1395 /// the body. We store this rather than the body directly so that when ZIR1338 func: InternPool.Index,
1396 /// is regenerated on update(), we can map this to the new corresponding1339
1397 /// ZIR instruction.1340 /// All currently known errors that this error set contains. This includes
1398 zir_body_inst: Zir.Inst.Index,1341 /// direct additions via `return error.Foo;`, and possibly also errors that
1399 /// If this is not null, this function is a generic function instantiation, and1342 /// are returned from any dependent functions. When the inferred error set is
1400 /// there is a `TypedValue` here for each parameter of the function.1343 /// fully resolved, this map contains all the errors that the function might return.
1401 /// Non-comptime parameters are marked with a `generic_poison` for the value.1344 errors: NameMap = .{},
1402 /// Non-anytype parameters are marked with a `generic_poison` for the type.1345
1403 /// These never have .generic_poison for the Type1346 /// Other inferred error sets which this inferred error set should include.
1404 /// because the Type is needed to pass to `Type.eql` and for inserting comptime arguments1347 inferred_error_sets: std.AutoArrayHashMapUnmanaged(InferredErrorSet.Index, void) = .{},
1405 /// into the inst_map when analyzing the body of a generic function instantiation.1348
1406 /// Instead, the is_anytype knowledge is communicated via `isAnytypeParam`.1349 /// Whether the function returned anyerror. This is true if either of
1407 comptime_args: ?[*]TypedValue,1350 /// the dependent functions returns anyerror.
14081351 is_anyerror: bool = false,
1409 /// Precomputed hash for monomorphed_funcs.1352
1410 /// This is important because it may be accessed when resizing monomorphed_funcs1353 /// Whether this error set is already fully resolved. If true, resolving
1411 /// while this Fn has already been added to the set, but does not have the1354 /// can skip resolving any dependents of this inferred error set.
1412 /// owner_decl, comptime_args, or other fields populated yet.1355 is_resolved: bool = false,
1413 /// This field is undefined if comptime_args == null.1356
1414 hash: u64,1357 pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
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,
14471358
1448 pub const Index = enum(u32) {1359 pub const Index = enum(u32) {
1449 _,1360 _,
14501361
1451 pub fn toOptional(i: Index) OptionalIndex {1362 pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1452 return @as(OptionalIndex, @enumFromInt(@intFromEnum(i)));1363 return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(i)));
1453 }1364 }
1454 };1365 };
14551366
...@@ -1457,159 +1368,37 @@ pub const Fn = struct {...@@ -1457,159 +1368,37 @@ pub const Fn = struct {
1457 none = std.math.maxInt(u32),1368 none = std.math.maxInt(u32),
1458 _,1369 _,
14591370
1460 pub fn init(oi: ?Index) OptionalIndex {1371 pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1461 return @as(OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none)));1372 return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none)));
1462 }1373 }
14631374
1464 pub fn unwrap(oi: OptionalIndex) ?Index {1375 pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index {
1465 if (oi == .none) return null;1376 if (oi == .none) return null;
1466 return @as(Index, @enumFromInt(@intFromEnum(oi)));1377 return @as(InferredErrorSet.Index, @enumFromInt(@intFromEnum(oi)));
1467 }1378 }
1468 };1379 };
14691380
1470 pub const Analysis = enum {1381 pub fn addErrorSet(
1471 /// This function has not yet undergone analysis, because we have not1382 self: *InferredErrorSet,
1472 /// seen a potential runtime call. It may be analyzed in future.1383 err_set_ty: Type,
1473 none,1384 ip: *InternPool,
1474 /// Analysis for this function has been queued, but not yet completed.1385 gpa: Allocator,
1475 queued,1386 ) !void {
1476 /// This function intentionally only has ZIR generated because it is marked1387 switch (err_set_ty.toIntern()) {
1477 /// inline, which means no runtime version of the function will be generated.1388 .anyerror_type => {
1478 inline_only,1389 self.is_anyerror = true;
1479 in_progress,1390 },
1480 /// There will be a corresponding ErrorMsg in Module.failed_decls1391 else => switch (ip.indexToKey(err_set_ty.toIntern())) {
1481 sema_failure,1392 .error_set_type => |error_set_type| {
1482 /// This Fn might be OK but it depends on another Decl which did not1393 for (error_set_type.names) |name| {
1483 /// successfully complete semantic analysis.1394 try self.errors.put(gpa, name, {});
1484 dependency_failure,1395 }
1485 success,
1486 };
1487
1488 /// This struct is used to keep track of any dependencies related to functions instances
1489 /// that return inferred error sets. Note that a function may be associated to
1490 /// multiple different error sets, for example an inferred error set which
1491 /// this function returns, but also any inferred error sets of called inline
1492 /// or comptime functions.
1493 pub const InferredErrorSet = struct {
1494 /// The function from which this error set originates.
1495 func: Fn.Index,
1496
1497 /// All currently known errors that this error set contains. This includes
1498 /// direct additions via `return error.Foo;`, and possibly also errors that
1499 /// are returned from any dependent functions. When the inferred error set is
1500 /// fully resolved, this map contains all the errors that the function might return.
1501 errors: NameMap = .{},
1502
1503 /// Other inferred error sets which this inferred error set should include.
1504 inferred_error_sets: std.AutoArrayHashMapUnmanaged(InferredErrorSet.Index, void) = .{},
1505
1506 /// Whether the function returned anyerror. This is true if either of
1507 /// the dependent functions returns anyerror.
1508 is_anyerror: bool = false,
1509
1510 /// Whether this error set is already fully resolved. If true, resolving
1511 /// can skip resolving any dependents of this inferred error set.
1512 is_resolved: bool = false,
1513
1514 pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
1515
1516 pub const Index = enum(u32) {
1517 _,
1518
1519 pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1520 return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(i)));
1521 }
1522 };
1523
1524 pub const OptionalIndex = enum(u32) {
1525 none = std.math.maxInt(u32),
1526 _,
1527
1528 pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1529 return @as(InferredErrorSet.OptionalIndex, @enumFromInt(@intFromEnum(oi orelse return .none)));
1530 }
1531
1532 pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index {
1533 if (oi == .none) return null;
1534 return @as(InferredErrorSet.Index, @enumFromInt(@intFromEnum(oi)));
1535 }
1536 };
1537
1538 pub fn addErrorSet(
1539 self: *InferredErrorSet,
1540 err_set_ty: Type,
1541 ip: *InternPool,
1542 gpa: Allocator,
1543 ) !void {
1544 switch (err_set_ty.toIntern()) {
1545 .anyerror_type => {
1546 self.is_anyerror = true;
1547 },1396 },
1548 else => switch (ip.indexToKey(err_set_ty.toIntern())) {1397 .inferred_error_set_type => |ies_index| {
1549 .error_set_type => |error_set_type| {1398 try self.inferred_error_sets.put(gpa, ies_index, {});
1550 for (error_set_type.names) |name| {
1551 try self.errors.put(gpa, name, {});
1552 }
1553 },
1554 .inferred_error_set_type => |ies_index| {
1555 try self.inferred_error_sets.put(gpa, ies_index, {});
1556 },
1557 else => unreachable,
1558 },1399 },
1559 }1400 else => unreachable,
1560 }
1561 };
1562
1563 pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {
1564 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
1565
1566 const tags = file.zir.instructions.items(.tag);
1567
1568 const param_body = file.zir.getParamBody(func.zir_body_inst);
1569 const param = param_body[index];
1570
1571 return switch (tags[param]) {
1572 .param, .param_comptime => false,
1573 .param_anytype, .param_anytype_comptime => true,
1574 else => unreachable,
1575 };
1576 }
1577
1578 pub fn getParamName(func: Fn, mod: *Module, index: u32) [:0]const u8 {
1579 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
1580
1581 const tags = file.zir.instructions.items(.tag);
1582 const data = file.zir.instructions.items(.data);
1583
1584 const param_body = file.zir.getParamBody(func.zir_body_inst);
1585 const param = param_body[index];
1586
1587 return switch (tags[param]) {
1588 .param, .param_comptime => blk: {
1589 const extra = file.zir.extraData(Zir.Inst.Param, data[param].pl_tok.payload_index);
1590 break :blk file.zir.nullTerminatedString(extra.data.name);
1591 },
1592 .param_anytype, .param_anytype_comptime => blk: {
1593 const param_data = data[param].str_tok;
1594 break :blk param_data.get(file.zir);
1595 },
1596 else => unreachable,
1597 };
1598 }
1599
1600 pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool {
1601 const owner_decl = mod.declPtr(func.owner_decl);
1602 const zir = owner_decl.getFileScope(mod).zir;
1603 const zir_tags = zir.instructions.items(.tag);
1604 switch (zir_tags[func.zir_body_inst]) {
1605 .func => return false,
1606 .func_inferred => return true,
1607 .func_fancy => {
1608 const inst_data = zir.instructions.items(.data)[func.zir_body_inst].pl_node;
1609 const extra = zir.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
1610 return extra.data.bits.is_inferred_error;
1611 },1401 },
1612 else => unreachable,
1613 }1402 }
1614 }1403 }
1615};1404};
...@@ -2468,6 +2257,22 @@ pub const SrcLoc = struct {...@@ -2468,6 +2257,22 @@ pub const SrcLoc = struct {
2468 }2257 }
2469 } else unreachable;2258 } else unreachable;
2470 },2259 },
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 },
2471 .node_offset_bin_lhs => |node_off| {2276 .node_offset_bin_lhs => |node_off| {
2472 const tree = try src_loc.file_scope.getTree(gpa);2277 const tree = try src_loc.file_scope.getTree(gpa);
2473 const node = src_loc.declRelativeToNodeIndex(node_off);2278 const node = src_loc.declRelativeToNodeIndex(node_off);
...@@ -3146,6 +2951,20 @@ pub const LazySrcLoc = union(enum) {...@@ -3146,6 +2951,20 @@ pub const LazySrcLoc = union(enum) {
3146 /// Next, navigate to the corresponding capture.2951 /// Next, navigate to the corresponding capture.
3147 /// The Decl is determined contextually.2952 /// The Decl is determined contextually.
3148 for_capture_from_input: i32,2953 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
3150 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;2969 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
31512970
...@@ -3235,6 +3054,8 @@ pub const LazySrcLoc = union(enum) {...@@ -3235,6 +3054,8 @@ pub const LazySrcLoc = union(enum) {
3235 .node_offset_store_operand,3054 .node_offset_store_operand,
3236 .for_input,3055 .for_input,
3237 .for_capture_from_input,3056 .for_capture_from_input,
3057 .call_arg,
3058 .fn_proto_param,
3238 => .{3059 => .{
3239 .file_scope = decl.getFileScope(mod),3060 .file_scope = decl.getFileScope(mod),
3240 .parent_decl_node = decl.src_node,3061 .parent_decl_node = decl.src_node,
...@@ -3373,8 +3194,6 @@ pub fn deinit(mod: *Module) void {...@@ -3373,8 +3194,6 @@ pub fn deinit(mod: *Module) void {
3373 mod.global_error_set.deinit(gpa);3194 mod.global_error_set.deinit(gpa);
33743195
3375 mod.test_functions.deinit(gpa);3196 mod.test_functions.deinit(gpa);
3376 mod.align_stack_fns.deinit(gpa);
3377 mod.monomorphed_funcs.deinit(gpa);
33783197
3379 mod.decls_free_list.deinit(gpa);3198 mod.decls_free_list.deinit(gpa);
3380 mod.allocated_decls.deinit(gpa);3199 mod.allocated_decls.deinit(gpa);
...@@ -3407,7 +3226,6 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -3407,7 +3226,6 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
3407 }3226 }
3408 }3227 }
3409 if (decl.src_scope) |scope| scope.decRef(gpa);3228 if (decl.src_scope) |scope| scope.decRef(gpa);
3410 decl.clearValues(mod);
3411 decl.dependants.deinit(gpa);3229 decl.dependants.deinit(gpa);
3412 decl.dependencies.deinit(gpa);3230 decl.dependencies.deinit(gpa);
3413 decl.* = undefined;3231 decl.* = undefined;
...@@ -3439,11 +3257,7 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {...@@ -3439,11 +3257,7 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
3439 return mod.intern_pool.structPtr(index);3257 return mod.intern_pool.structPtr(index);
3440}3258}
34413259
3442pub fn funcPtr(mod: *Module, index: Fn.Index) *Fn {3260pub fn inferredErrorSetPtr(mod: *Module, index: InferredErrorSet.Index) *InferredErrorSet {
3443 return mod.intern_pool.funcPtr(index);
3444}
3445
3446pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet {
3447 return mod.intern_pool.inferredErrorSetPtr(index);3261 return mod.intern_pool.inferredErrorSetPtr(index);
3448}3262}
34493263
...@@ -3457,10 +3271,6 @@ pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {...@@ -3457,10 +3271,6 @@ pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {
3457 return mod.structPtr(index.unwrap() orelse return null);3271 return mod.structPtr(index.unwrap() orelse return null);
3458}3272}
34593273
3460pub fn funcPtrUnwrap(mod: *Module, index: Fn.OptionalIndex) ?*Fn {
3461 return mod.funcPtr(index.unwrap() orelse return null);
3462}
3463
3464/// Returns true if and only if the Decl is the top level struct associated with a File.3274/// Returns true if and only if the Decl is the top level struct associated with a File.
3465pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {3275pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
3466 const decl = mod.declPtr(decl_index);3276 const decl = mod.declPtr(decl_index);
...@@ -3881,6 +3691,8 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {...@@ -3881,6 +3691,8 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3881 // to re-generate ZIR for the File.3691 // to re-generate ZIR for the File.
3882 try file.outdated_decls.append(gpa, root_decl);3692 try file.outdated_decls.append(gpa, root_decl);
38833693
3694 const ip = &mod.intern_pool;
3695
3884 while (decl_stack.popOrNull()) |decl_index| {3696 while (decl_stack.popOrNull()) |decl_index| {
3885 const decl = mod.declPtr(decl_index);3697 const decl = mod.declPtr(decl_index);
3886 // Anonymous decls and the root decl have this set to 0. We still need3698 // 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 {...@@ -3918,7 +3730,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
3918 }3730 }
39193731
3920 if (decl.getOwnedFunction(mod)) |func| {3732 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 {
3922 try file.deleted_decls.append(gpa, decl_index);3734 try file.deleted_decls.append(gpa, decl_index);
3923 continue;3735 continue;
3924 };3736 };
...@@ -4101,11 +3913,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4101,11 +3913,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4101 // prior to re-analysis.3913 // prior to re-analysis.
4102 try mod.deleteDeclExports(decl_index);3914 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
4109 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.3916 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
4110 for (decl.dependencies.keys()) |dep_index| {3917 for (decl.dependencies.keys()) |dep_index| {
4111 const dep = mod.declPtr(dep_index);3918 const dep = mod.declPtr(dep_index);
...@@ -4189,11 +3996,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4189,11 +3996,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
4189 }3996 }
4190}3997}
41913998
4192pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void {3999pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: InternPool.Index) SemaError!void {
4193 const tracy = trace(@src());4000 const tracy = trace(@src());
4194 defer tracy.end();4001 defer tracy.end();
41954002
4196 const func = mod.funcPtr(func_index);4003 const ip = &mod.intern_pool;
4004 const func = mod.funcInfo(func_index);
4197 const decl_index = func.owner_decl;4005 const decl_index = func.owner_decl;
4198 const decl = mod.declPtr(decl_index);4006 const decl = mod.declPtr(decl_index);
41994007
...@@ -4211,7 +4019,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4211,7 +4019,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
4211 => return error.AnalysisFail,4019 => return error.AnalysisFail,
42124020
4213 .complete, .codegen_failure_retryable => {4021 .complete, .codegen_failure_retryable => {
4214 switch (func.state) {4022 switch (func.analysis(ip).state) {
4215 .sema_failure, .dependency_failure => return error.AnalysisFail,4023 .sema_failure, .dependency_failure => return error.AnalysisFail,
4216 .none, .queued => {},4024 .none, .queued => {},
4217 .in_progress => unreachable,4025 .in_progress => unreachable,
...@@ -4227,11 +4035,11 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4227,11 +4035,11 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42274035
4228 var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {4036 var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
4229 error.AnalysisFail => {4037 error.AnalysisFail => {
4230 if (func.state == .in_progress) {4038 if (func.analysis(ip).state == .in_progress) {
4231 // If this decl caused the compile error, the analysis field would4039 // If this decl caused the compile error, the analysis field would
4232 // be changed to indicate it was this Decl's fault. Because this4040 // be changed to indicate it was this Decl's fault. Because this
4233 // did not happen, we infer here that it was a dependency failure.4041 // did not happen, we infer here that it was a dependency failure.
4234 func.state = .dependency_failure;4042 func.analysis(ip).state = .dependency_failure;
4235 }4043 }
4236 return error.AnalysisFail;4044 return error.AnalysisFail;
4237 },4045 },
...@@ -4251,14 +4059,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4251,14 +4059,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
42514059
4252 if (no_bin_file and !dump_air and !dump_llvm_ir) return;4060 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);
4255 defer liveness.deinit(gpa);4063 defer liveness.deinit(gpa);
42564064
4257 if (dump_air) {4065 if (dump_air) {
4258 const fqn = try decl.getFullyQualifiedName(mod);4066 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)});
4260 @import("print_air.zig").dump(mod, air, liveness);4068 @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)});
4262 }4070 }
42634071
4264 if (std.debug.runtime_safety) {4072 if (std.debug.runtime_safety) {
...@@ -4266,7 +4074,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4266,7 +4074,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
4266 .gpa = gpa,4074 .gpa = gpa,
4267 .air = air,4075 .air = air,
4268 .liveness = liveness,4076 .liveness = liveness,
4269 .intern_pool = &mod.intern_pool,4077 .intern_pool = ip,
4270 };4078 };
4271 defer verify.deinit();4079 defer verify.deinit();
42724080
...@@ -4321,8 +4129,9 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void...@@ -4321,8 +4129,9 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void
4321/// analyzed, and for ensuring it can exist at runtime (see4129/// analyzed, and for ensuring it can exist at runtime (see
4322/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body4130/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
4323/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.4131/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
4324pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {4132pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index) !void {
4325 const func = mod.funcPtr(func_index);4133 const ip = &mod.intern_pool;
4134 const func = mod.funcInfo(func_index);
4326 const decl_index = func.owner_decl;4135 const decl_index = func.owner_decl;
4327 const decl = mod.declPtr(decl_index);4136 const decl = mod.declPtr(decl_index);
43284137
...@@ -4348,7 +4157,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {...@@ -4348,7 +4157,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
43484157
4349 assert(decl.has_tv);4158 assert(decl.has_tv);
43504159
4351 switch (func.state) {4160 switch (func.analysis(ip).state) {
4352 .none => {},4161 .none => {},
4353 .queued => return,4162 .queued => return,
4354 // As above, we don't need to forward errors here.4163 // As above, we don't need to forward errors here.
...@@ -4366,7 +4175,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {...@@ -4366,7 +4175,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
4366 // since the last update4175 // since the last update
4367 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });4176 try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index });
4368 }4177 }
4369 func.state = .queued;4178 func.analysis(ip).state = .queued;
4370}4179}
43714180
4372pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {4181pub fn updateEmbedFile(mod: *Module, embed_file: *EmbedFile) SemaError!void {
...@@ -4490,10 +4299,8 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {...@@ -4490,10 +4299,8 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4490 .code = file.zir,4299 .code = file.zir,
4491 .owner_decl = new_decl,4300 .owner_decl = new_decl,
4492 .owner_decl_index = new_decl_index,4301 .owner_decl_index = new_decl_index,
4493 .func = null,
4494 .func_index = .none,4302 .func_index = .none,
4495 .fn_ret_ty = Type.void,4303 .fn_ret_ty = Type.void,
4496 .owner_func = null,
4497 .owner_func_index = .none,4304 .owner_func_index = .none,
4498 .comptime_mutable_decls = &comptime_mutable_decls,4305 .comptime_mutable_decls = &comptime_mutable_decls,
4499 };4306 };
...@@ -4573,10 +4380,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4573,10 +4380,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4573 .code = zir,4380 .code = zir,
4574 .owner_decl = decl,4381 .owner_decl = decl,
4575 .owner_decl_index = decl_index,4382 .owner_decl_index = decl_index,
4576 .func = null,
4577 .func_index = .none,4383 .func_index = .none,
4578 .fn_ret_ty = Type.void,4384 .fn_ret_ty = Type.void,
4579 .owner_func = null,
4580 .owner_func_index = .none,4385 .owner_func_index = .none,
4581 .comptime_mutable_decls = &comptime_mutable_decls,4386 .comptime_mutable_decls = &comptime_mutable_decls,
4582 };4387 };
...@@ -4658,48 +4463,49 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4658,48 +4463,49 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4658 return true;4463 return true;
4659 }4464 }
46604465
4661 if (mod.intern_pool.indexToFunc(decl_tv.val.toIntern()).unwrap()) |func_index| {4466 const ip = &mod.intern_pool;
4662 const func = mod.funcPtr(func_index);4467 switch (ip.indexToKey(decl_tv.val.toIntern())) {
4663 const owns_tv = func.owner_decl == decl_index;4468 .func => |func| {
4664 if (owns_tv) {4469 const owns_tv = func.owner_decl == decl_index;
4665 var prev_type_has_bits = false;4470 if (owns_tv) {
4666 var prev_is_inline = false;4471 var prev_type_has_bits = false;
4667 var type_changed = true;4472 var prev_is_inline = false;
46684473 var type_changed = true;
4669 if (decl.has_tv) {4474
4670 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);4475 if (decl.has_tv) {
4671 type_changed = !decl.ty.eql(decl_tv.ty, mod);4476 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
4672 if (decl.getOwnedFunction(mod)) |prev_func| {4477 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4673 prev_is_inline = prev_func.state == .inline_only;4478 if (decl.getOwnedFunction(mod)) |prev_func| {
4479 prev_is_inline = prev_func.analysis(ip).state == .inline_only;
4480 }
4674 }4481 }
4675 }4482
4676 decl.clearValues(mod);4483 decl.ty = decl_tv.ty;
46774484 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
4678 decl.ty = decl_tv.ty;4485 // linksection, align, and addrspace were already set by Sema
4679 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();4486 decl.has_tv = true;
4680 // linksection, align, and addrspace were already set by Sema4487 decl.owns_tv = owns_tv;
4681 decl.has_tv = true;4488 decl.analysis = .complete;
4682 decl.owns_tv = owns_tv;4489 decl.generation = mod.generation;
4683 decl.analysis = .complete;4490
4684 decl.generation = mod.generation;4491 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
46854492 if (decl.is_exported) {
4686 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;4493 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };
4687 if (decl.is_exported) {4494 if (is_inline) {
4688 const export_src: LazySrcLoc = .{ .token_offset = @intFromBool(decl.is_pub) };4495 return sema.fail(&block_scope, export_src, "export of inline function", .{});
4689 if (is_inline) {4496 }
4690 return sema.fail(&block_scope, export_src, "export of inline function", .{});4497 // The scope needs to have the decl in it.
4498 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
4691 }4499 }
4692 // The scope needs to have the decl in it.4500 return type_changed or is_inline != prev_is_inline;
4693 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
4694 }4501 }
4695 return type_changed or is_inline != prev_is_inline;4502 },
4696 }4503 else => {},
4697 }4504 }
4698 var type_changed = true;4505 var type_changed = true;
4699 if (decl.has_tv) {4506 if (decl.has_tv) {
4700 type_changed = !decl.ty.eql(decl_tv.ty, mod);4507 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4701 }4508 }
4702 decl.clearValues(mod);
47034509
4704 decl.owns_tv = false;4510 decl.owns_tv = false;
4705 var queue_linker_work = false;4511 var queue_linker_work = false;
...@@ -4707,7 +4513,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4707,7 +4513,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4707 switch (decl_tv.val.toIntern()) {4513 switch (decl_tv.val.toIntern()) {
4708 .generic_poison => unreachable,4514 .generic_poison => unreachable,
4709 .unreachable_value => unreachable,4515 .unreachable_value => unreachable,
4710 else => switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {4516 else => switch (ip.indexToKey(decl_tv.val.toIntern())) {
4711 .variable => |variable| if (variable.decl == decl_index) {4517 .variable => |variable| if (variable.decl == decl_index) {
4712 decl.owns_tv = true;4518 decl.owns_tv = true;
4713 queue_linker_work = true;4519 queue_linker_work = true;
...@@ -4743,11 +4549,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4743,11 +4549,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4743 } else if (bytes.len == 0) {4549 } else if (bytes.len == 0) {
4744 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});4550 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
4745 }4551 }
4746 const section = try mod.intern_pool.getOrPutString(gpa, bytes);4552 const section = try ip.getOrPutString(gpa, bytes);
4747 break :blk section.toOptional();4553 break :blk section.toOptional();
4748 };4554 };
4749 decl.@"addrspace" = blk: {4555 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())) {
4751 .variable => .variable,4557 .variable => .variable,
4752 .extern_func, .func => .function,4558 .extern_func, .func => .function,
4753 else => .constant,4559 else => .constant,
...@@ -5309,7 +5115,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5309,7 +5115,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5309 decl.has_align = has_align;5115 decl.has_align = has_align;
5310 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;5116 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
5311 decl.zir_decl_index = @as(u32, @intCast(decl_sub_index));5117 decl.zir_decl_index = @as(u32, @intCast(decl_sub_index));
5312 if (decl.getOwnedFunctionIndex(mod) != .none) {5118 if (decl.getOwnedFunctionIndex() != .none) {
5313 switch (comp.bin_file.tag) {5119 switch (comp.bin_file.tag) {
5314 .coff, .elf, .macho, .plan9 => {5120 .coff, .elf, .macho, .plan9 => {
5315 // TODO Look into detecting when this would be unnecessary by storing enough state5121 // TODO Look into detecting when this would be unnecessary by storing enough state
...@@ -5386,7 +5192,6 @@ pub fn clearDecl(...@@ -5386,7 +5192,6 @@ pub fn clearDecl(
5386 try namespace.deleteAllDecls(mod, outdated_decls);5192 try namespace.deleteAllDecls(mod, outdated_decls);
5387 }5193 }
5388 }5194 }
5389 decl.clearValues(mod);
53905195
5391 if (decl.deletion_flag) {5196 if (decl.deletion_flag) {
5392 decl.deletion_flag = false;5197 decl.deletion_flag = false;
...@@ -5497,19 +5302,26 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void...@@ -5497,19 +5302,26 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
5497 export_owners.deinit(mod.gpa);5302 export_owners.deinit(mod.gpa);
5498}5303}
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 {
5501 const tracy = trace(@src());5306 const tracy = trace(@src());
5502 defer tracy.end();5307 defer tracy.end();
55035308
5504 const gpa = mod.gpa;5309 const gpa = mod.gpa;
5505 const func = mod.funcPtr(func_index);5310 const ip = &mod.intern_pool;
5311 const func = mod.funcInfo(func_index);
5506 const decl_index = func.owner_decl;5312 const decl_index = func.owner_decl;
5507 const decl = mod.declPtr(decl_index);5313 const decl = mod.declPtr(decl_index);
55085314
5509 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);5315 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
5510 defer comptime_mutable_decls.deinit();5316 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.
5512 const fn_ty = decl.ty;5323 const fn_ty = decl.ty;
5324 const fn_ty_info = mod.typeToFunc(fn_ty).?;
55135325
5514 var sema: Sema = .{5326 var sema: Sema = .{
5515 .mod = mod,5327 .mod = mod,
...@@ -5518,18 +5330,16 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5518,18 +5330,16 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5518 .code = decl.getFileScope(mod).zir,5330 .code = decl.getFileScope(mod).zir,
5519 .owner_decl = decl,5331 .owner_decl = decl,
5520 .owner_decl_index = decl_index,5332 .owner_decl_index = decl_index,
5521 .func = func,5333 .func_index = func_index,
5522 .func_index = func_index.toOptional(),5334 .fn_ret_ty = fn_ty_info.return_type.toType(),
5523 .fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(),5335 .owner_func_index = func_index,
5524 .owner_func = func,5336 .branch_quota = @max(func.branchQuota(ip).*, Sema.default_branch_quota),
5525 .owner_func_index = func_index.toOptional(),
5526 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
5527 .comptime_mutable_decls = &comptime_mutable_decls,5337 .comptime_mutable_decls = &comptime_mutable_decls,
5528 };5338 };
5529 defer sema.deinit();5339 defer sema.deinit();
55305340
5531 // reset in case calls to errorable functions are removed.5341 // 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
5534 // First few indexes of extra are reserved and set at the end.5344 // First few indexes of extra are reserved and set at the end.
5535 const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len;5345 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...@@ -5551,8 +5361,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5551 };5361 };
5552 defer inner_block.instructions.deinit(gpa);5362 defer inner_block.instructions.deinit(gpa);
55535363
5554 const fn_info = sema.code.getFnInfo(func.zir_body_inst);5364 const fn_info = sema.code.getFnInfo(func.zirBodyInst(ip).*);
5555 const zir_tags = sema.code.instructions.items(.tag);
55565365
5557 // Here we are performing "runtime semantic analysis" for a function body, which means5366 // Here we are performing "runtime semantic analysis" for a function body, which means
5558 // we must map the parameter ZIR instructions to `arg` AIR instructions.5367 // 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...@@ -5560,35 +5369,36 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5560 // This could be a generic function instantiation, however, in which case we need to5369 // This could be a generic function instantiation, however, in which case we need to
5561 // map the comptime parameters to constant values and only emit arg AIR instructions5370 // map the comptime parameters to constant values and only emit arg AIR instructions
5562 // for the runtime ones.5371 // 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;
5564 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);5373 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);
5566 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);5375 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
55675376
5568 var runtime_param_index: usize = 0;5377 // In the case of a generic function instance, pre-populate all the comptime args.
5569 var total_param_index: usize = 0;5378 if (func.comptime_args.len != 0) {
5570 for (fn_info.param_body) |inst| {5379 for (
5571 switch (zir_tags[inst]) {5380 fn_info.param_body[0..func.comptime_args.len],
5572 .param, .param_comptime, .param_anytype, .param_anytype_comptime => {},5381 func.comptime_args.get(ip),
5573 else => continue,5382 ) |inst, comptime_arg| {
5383 if (comptime_arg == .none) continue;
5384 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.internedToRef(comptime_arg));
5574 }5385 }
5575 const param_ty = if (func.comptime_args) |comptime_args| t: {5386 }
5576 const arg_tv = comptime_args[total_param_index];5387
55775388 const src_params_len = if (func.comptime_args.len != 0)
5578 const arg_val = if (!arg_tv.val.isGenericPoison())5389 func.comptime_args.len
5579 arg_tv.val5390 else
5580 else if (try arg_tv.ty.onePossibleValue(mod)) |opv|5391 runtime_params_len;
5581 opv5392
5582 else5393 var runtime_param_index: usize = 0;
5583 break :t arg_tv.ty;5394 for (fn_info.param_body[0..src_params_len], 0..) |inst, src_param_index| {
55845395 const gop = sema.inst_map.getOrPutAssumeCapacity(inst);
5585 const arg = try sema.addConstant(arg_val);5396 if (gop.found_existing) continue; // provided above by comptime arg
5586 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5587 total_param_index += 1;
5588 continue;
5589 } else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType();
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) {
5592 error.NeededSourceLocation => unreachable,5402 error.NeededSourceLocation => unreachable,
5593 error.GenericPoison => unreachable,5403 error.GenericPoison => unreachable,
5594 error.ComptimeReturn => unreachable,5404 error.ComptimeReturn => unreachable,
...@@ -5596,28 +5406,22 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5596,28 +5406,22 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5596 else => |e| return e,5406 else => |e| return e,
5597 };5407 };
5598 if (opt_opv) |opv| {5408 if (opt_opv) |opv| {
5599 const arg = try sema.addConstant(opv);5409 gop.value_ptr.* = Air.internedToRef(opv.toIntern());
5600 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5601 total_param_index += 1;
5602 runtime_param_index += 1;
5603 continue;5410 continue;
5604 }5411 }
5605 const air_ty = try sema.addType(param_ty);5412 const arg_index: u32 = @intCast(sema.air_instructions.len);
5606 const arg_index = @as(u32, @intCast(sema.air_instructions.len));5413 gop.value_ptr.* = Air.indexToRef(arg_index);
5607 inner_block.instructions.appendAssumeCapacity(arg_index);5414 inner_block.instructions.appendAssumeCapacity(arg_index);
5608 sema.air_instructions.appendAssumeCapacity(.{5415 sema.air_instructions.appendAssumeCapacity(.{
5609 .tag = .arg,5416 .tag = .arg,
5610 .data = .{ .arg = .{5417 .data = .{ .arg = .{
5611 .ty = air_ty,5418 .ty = Air.internedToRef(param_ty),
5612 .src_index = @as(u32, @intCast(total_param_index)),5419 .src_index = @intCast(src_param_index),
5613 } },5420 } },
5614 });5421 });
5615 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(arg_index));
5616 total_param_index += 1;
5617 runtime_param_index += 1;
5618 }5422 }
56195423
5620 func.state = .in_progress;5424 func.analysis(ip).state = .in_progress;
56215425
5622 const last_arg_index = inner_block.instructions.items.len;5426 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...@@ -5648,7 +5452,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5648 }5452 }
56495453
5650 // If we don't get an error return trace from a caller, create our own.5454 // If we don't get an error return trace from a caller, create our own.
5651 if (func.calls_or_awaits_errorable_fn and5455 if (func.analysis(ip).calls_or_awaits_errorable_fn and
5652 mod.comp.bin_file.options.error_return_tracing and5456 mod.comp.bin_file.options.error_return_tracing and
5653 !sema.fn_ret_ty.isError(mod))5457 !sema.fn_ret_ty.isError(mod))
5654 {5458 {
...@@ -5677,7 +5481,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5677,7 +5481,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5677 sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);5481 sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
5678 sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;5482 sema.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)] = main_block_index;
56795483
5680 func.state = .success;5484 func.analysis(ip).state = .success;
56815485
5682 // Finally we must resolve the return type and parameter types so that backends5486 // Finally we must resolve the return type and parameter types so that backends
5683 // have full access to type information.5487 // have full access to type information.
...@@ -5716,7 +5520,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE...@@ -5716,7 +5520,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaE
5716 };5520 };
5717 }5521 }
57185522
5719 return Air{5523 return .{
5720 .instructions = sema.air_instructions.toOwnedSlice(),5524 .instructions = sema.air_instructions.toOwnedSlice(),
5721 .extra = try sema.air_extra.toOwnedSlice(gpa),5525 .extra = try sema.air_extra.toOwnedSlice(gpa),
5722 };5526 };
...@@ -5731,9 +5535,6 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -5731,9 +5535,6 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5731 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {5535 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
5732 for (kv.value) |err| err.deinit(mod.gpa);5536 for (kv.value) |err| err.deinit(mod.gpa);
5733 }5537 }
5734 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
5735 _ = mod.align_stack_fns.remove(func);
5736 }
5737 if (mod.emit_h) |emit_h| {5538 if (mod.emit_h) |emit_h| {
5738 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {5539 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
5739 kv.value.destroy(mod.gpa);5540 kv.value.destroy(mod.gpa);
...@@ -5777,14 +5578,6 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {...@@ -5777,14 +5578,6 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {
5777 return mod.intern_pool.destroyUnion(mod.gpa, index);5578 return mod.intern_pool.destroyUnion(mod.gpa, index);
5778}5579}
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
5788pub fn allocateNewDecl(5581pub fn allocateNewDecl(
5789 mod: *Module,5582 mod: *Module,
5790 namespace: Namespace.Index,5583 namespace: Namespace.Index,
...@@ -6578,7 +6371,6 @@ pub fn populateTestFunctions(...@@ -6578,7 +6371,6 @@ pub fn populateTestFunctions(
65786371
6579 // Since we are replacing the Decl's value we must perform cleanup on the6372 // Since we are replacing the Decl's value we must perform cleanup on the
6580 // previous value.6373 // previous value.
6581 decl.clearValues(mod);
6582 decl.ty = new_ty;6374 decl.ty = new_ty;
6583 decl.val = new_val;6375 decl.val = new_val;
6584 decl.has_tv = true;6376 decl.has_tv = true;
...@@ -6657,7 +6449,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {...@@ -6657,7 +6449,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
6657 switch (mod.intern_pool.indexToKey(val.toIntern())) {6449 switch (mod.intern_pool.indexToKey(val.toIntern())) {
6658 .variable => |variable| try mod.markDeclIndexAlive(variable.decl),6450 .variable => |variable| try mod.markDeclIndexAlive(variable.decl),
6659 .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),6451 .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),
6661 .error_union => |error_union| switch (error_union.val) {6453 .error_union => |error_union| switch (error_union.val) {
6662 .err_name => {},6454 .err_name => {},
6663 .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),6455 .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),
...@@ -6851,8 +6643,8 @@ pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator...@@ -6851,8 +6643,8 @@ pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator
6851 return mod.ptrType(info);6643 return mod.ptrType(info);
6852}6644}
68536645
6854pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Type {6646pub fn funcType(mod: *Module, key: InternPool.GetFuncTypeKey) Allocator.Error!Type {
6855 return (try intern(mod, .{ .func_type = info })).toType();6647 return (try mod.intern_pool.getFuncType(mod.gpa, key)).toType();
6856}6648}
68576649
6858/// Use this for `anyframe->T` only.6650/// Use this for `anyframe->T` only.
...@@ -7231,16 +7023,28 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {...@@ -7231,16 +7023,28 @@ pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {
7231 return mod.intern_pool.indexToFuncType(ty.toIntern());7023 return mod.intern_pool.indexToFuncType(ty.toIntern());
7232}7024}
72337025
7234pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*Fn.InferredErrorSet {7026pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*InferredErrorSet {
7235 const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;7027 const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;
7236 return mod.inferredErrorSetPtr(index);7028 return mod.inferredErrorSetPtr(index);
7237}7029}
72387030
7239pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) Fn.InferredErrorSet.OptionalIndex {7031pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) InferredErrorSet.OptionalIndex {
7240 if (ty.ip_index == .none) return .none;7032 if (ty.ip_index == .none) return .none;
7241 return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern());7033 return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern());
7242}7034}
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
7244pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {7048pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {
7245 @setCold(true);7049 @setCold(true);
7246 const owner_decl = mod.declPtr(owner_decl_index);7050 const owner_decl = mod.declPtr(owner_decl_index);
...@@ -7265,3 +7069,57 @@ pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQu...@@ -7265,3 +7069,57 @@ pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQu
7265pub fn toEnum(mod: *Module, comptime E: type, val: Value) E {7069pub fn toEnum(mod: *Module, comptime E: type, val: Value) E {
7266 return mod.intern_pool.toEnum(E, val.toIntern());7070 return mod.intern_pool.toEnum(E, val.toIntern());
7267}7071}
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,...@@ -23,13 +23,13 @@ owner_decl: *Decl,
23owner_decl_index: Decl.Index,23owner_decl_index: Decl.Index,
24/// For an inline or comptime function call, this will be the root parent function24/// For an inline or comptime function call, this will be the root parent function
25/// which contains the callsite. Corresponds to `owner_decl`.25/// which contains the callsite. Corresponds to `owner_decl`.
26owner_func: ?*Module.Fn,26/// This could be `none`, a `func_decl`, or a `func_instance`.
27owner_func_index: Module.Fn.OptionalIndex,27owner_func_index: InternPool.Index,
28/// The function this ZIR code is the body of, according to the source code.28/// The function this ZIR code is the body of, according to the source code.
29/// This starts out the same as `owner_func` and then diverges in the case of29/// This starts out the same as `owner_func_index` and then diverges in the case of
30/// an inline or comptime function call.30/// an inline or comptime function call.
31func: ?*Module.Fn,31/// This could be `none`, a `func_decl`, or a `func_instance`.
32func_index: Module.Fn.OptionalIndex,32func_index: InternPool.Index,
33/// Used to restore the error return trace when returning a non-error from a function.33/// Used to restore the error return trace when returning a non-error from a function.
34error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,34error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
35/// When semantic analysis needs to know the return type of the function whose body35/// When semantic analysis needs to know the return type of the function whose body
...@@ -49,21 +49,16 @@ comptime_break_inst: Zir.Inst.Index = undefined,...@@ -49,21 +49,16 @@ comptime_break_inst: Zir.Inst.Index = undefined,
49/// contain a mapped source location.49/// contain a mapped source location.
50src: LazySrcLoc = .{ .token_offset = 0 },50src: LazySrcLoc = .{ .token_offset = 0 },
51decl_val_table: std.AutoHashMapUnmanaged(Decl.Index, Air.Inst.Ref) = .{},51decl_val_table: std.AutoHashMapUnmanaged(Decl.Index, Air.Inst.Ref) = .{},
52/// When doing a generic function instantiation, this array collects a52/// When doing a generic function instantiation, this array collects a value
53/// `Value` object for each parameter that is comptime-known and thus elided53/// for each parameter of the generic owner. `none` for non-comptime parameters.
54/// from the generated function. This memory is allocated by a parent `Sema` and54/// This is a separate array from `block.params` so that it can be passed
55/// owned by the values arena of the Sema owner_decl.55/// directly to `comptime_args` when calling `InternPool.getFuncInstance`.
56comptime_args: []TypedValue = &.{},56/// This memory is allocated by a parent `Sema` in the temporary arena, and is
57/// Marks the function instruction that `comptime_args` applies to so that we57/// used only to add a `func_instance` into the `InternPool`.
58/// don't accidentally apply it to a function prototype which is used in the58comptime_args: []InternPool.Index = &.{},
59/// type expression of a generic function parameter.59/// Used to communicate from a generic function instantiation to the logic that
60comptime_args_fn_inst: Zir.Inst.Index = 0,60/// creates a generic function instantiation value in `funcCommon`.
61/// When `comptime_args` is provided, this field is also provided. It was used as61generic_owner: InternPool.Index = .none,
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,
67/// The key is types that must be fully resolved prior to machine code62/// The key is types that must be fully resolved prior to machine code
68/// generation pass. Types are added to this set when resolving them63/// generation pass. Types are added to this set when resolving them
69/// immediately could cause a dependency loop, but they do need to be resolved64/// 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) = .{},...@@ -79,8 +74,6 @@ types_to_resolve: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{},
79post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},74post_hoc_blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, *LabeledBlock) = .{},
80/// Populated with the last compile error created.75/// Populated with the last compile error created.
81err: ?*Module.ErrorMsg = null,76err: ?*Module.ErrorMsg = null,
82/// True when analyzing a generic instantiation. Used to suppress some errors.
83is_generic_instantiation: bool = false,
84/// Set to true when analyzing a func type instruction so that nested generic77/// Set to true when analyzing a func type instruction so that nested generic
85/// function types will emit generic poison instead of a partial type.78/// function types will emit generic poison instead of a partial type.
86no_partial_func_ty: bool = false,79no_partial_func_ty: bool = false,
...@@ -97,6 +90,10 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAll...@@ -97,6 +90,10 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAll
97/// involve transitioning comptime-mutable memory away from using Decls at all.90/// involve transitioning comptime-mutable memory away from using Decls at all.
98comptime_mutable_decls: *std.ArrayList(Decl.Index),91comptime_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
100const std = @import("std");97const std = @import("std");
101const math = std.math;98const math = std.math;
102const mem = std.mem;99const mem = std.mem;
...@@ -243,7 +240,13 @@ pub const Block = struct {...@@ -243,7 +240,13 @@ pub const Block = struct {
243 /// The AIR instructions generated for this block.240 /// The AIR instructions generated for this block.
244 instructions: std.ArrayListUnmanaged(Air.Inst.Index),241 instructions: std.ArrayListUnmanaged(Air.Inst.Index),
245 // `param` instructions are collected here to be used by the `func` instruction.242 // `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
248 wip_capture_scope: *CaptureScope,251 wip_capture_scope: *CaptureScope,
249252
...@@ -323,10 +326,10 @@ pub const Block = struct {...@@ -323,10 +326,10 @@ pub const Block = struct {
323 };326 };
324327
325 const Param = struct {328 const Param = struct {
326 /// `noreturn` means `anytype`.329 /// `none` means `anytype`.
327 ty: Type,330 ty: InternPool.Index,
328 is_comptime: bool,331 is_comptime: bool,
329 name: []const u8,332 name: Zir.NullTerminatedString,
330 };333 };
331334
332 /// This `Block` maps a block ZIR instruction to the corresponding335 /// This `Block` maps a block ZIR instruction to the corresponding
...@@ -342,7 +345,8 @@ pub const Block = struct {...@@ -342,7 +345,8 @@ pub const Block = struct {
342 /// It is shared among all the blocks in an inline or comptime called345 /// It is shared among all the blocks in an inline or comptime called
343 /// function.346 /// function.
344 pub const Inlining = struct {347 pub const Inlining = struct {
345 func: ?*Module.Fn,348 /// Might be `none`.
349 func: InternPool.Index,
346 comptime_result: Air.Inst.Ref,350 comptime_result: Air.Inst.Ref,
347 merges: Merges,351 merges: Merges,
348 };352 };
...@@ -906,7 +910,7 @@ fn analyzeBodyInner(...@@ -906,7 +910,7 @@ fn analyzeBodyInner(
906 // We use a while (true) loop here to avoid a redundant way of breaking out of910 // We use a while (true) loop here to avoid a redundant way of breaking out of
907 // the loop. The only way to break out of the loop is with a `noreturn`911 // the loop. The only way to break out of the loop is with a `noreturn`
908 // instruction.912 // instruction.
909 var i: usize = 0;913 var i: u32 = 0;
910 const result = while (true) {914 const result = while (true) {
911 crash_info.setBodyIndex(i);915 crash_info.setBodyIndex(i);
912 const inst = body[i];916 const inst = body[i];
...@@ -1338,22 +1342,22 @@ fn analyzeBodyInner(...@@ -1338,22 +1342,22 @@ fn analyzeBodyInner(
1338 continue;1342 continue;
1339 },1343 },
1340 .param => {1344 .param => {
1341 try sema.zirParam(block, inst, false);1345 try sema.zirParam(block, inst, i, false);
1342 i += 1;1346 i += 1;
1343 continue;1347 continue;
1344 },1348 },
1345 .param_comptime => {1349 .param_comptime => {
1346 try sema.zirParam(block, inst, true);1350 try sema.zirParam(block, inst, i, true);
1347 i += 1;1351 i += 1;
1348 continue;1352 continue;
1349 },1353 },
1350 .param_anytype => {1354 .param_anytype => {
1351 try sema.zirParamAnytype(block, inst, false);1355 try sema.zirParamAnytype(block, inst, i, false);
1352 i += 1;1356 i += 1;
1353 continue;1357 continue;
1354 },1358 },
1355 .param_anytype_comptime => {1359 .param_anytype_comptime => {
1356 try sema.zirParamAnytype(block, inst, true);1360 try sema.zirParamAnytype(block, inst, i, true);
1357 i += 1;1361 i += 1;
1358 continue;1362 continue;
1359 },1363 },
...@@ -1493,10 +1497,7 @@ fn analyzeBodyInner(...@@ -1493,10 +1497,7 @@ fn analyzeBodyInner(
1493 // Note: this probably needs to be resolved in a more general manner.1497 // Note: this probably needs to be resolved in a more general manner.
1494 const prev_params = block.params;1498 const prev_params = block.params;
1495 block.params = .{};1499 block.params = .{};
1496 defer {1500 defer block.params = prev_params;
1497 block.params.deinit(sema.gpa);
1498 block.params = prev_params;
1499 }
1500 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse1501 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
1501 break always_noreturn;1502 break always_noreturn;
1502 if (inst == break_data.block_inst) {1503 if (inst == break_data.block_inst) {
...@@ -1532,7 +1533,6 @@ fn analyzeBodyInner(...@@ -1532,7 +1533,6 @@ fn analyzeBodyInner(
1532 .merges = undefined,1533 .merges = undefined,
1533 };1534 };
1534 child_block.label = &label;1535 child_block.label = &label;
1535 defer child_block.params.deinit(gpa);
15361536
1537 // Write these instructions directly into the parent block1537 // Write these instructions directly into the parent block
1538 child_block.instructions = block.instructions;1538 child_block.instructions = block.instructions;
...@@ -2363,7 +2363,10 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {...@@ -2363,7 +2363,10 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2363 break :blk default_reference_trace_len;2363 break :blk default_reference_trace_len;
2364 };2364 };
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;
2367 var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa);2370 var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa);
2368 defer reference_stack.deinit();2371 defer reference_stack.deinit();
23692372
...@@ -2399,14 +2402,15 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {...@@ -2399,14 +2402,15 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
2399 }2402 }
2400 err_msg.reference_trace = try reference_stack.toOwnedSlice();2403 err_msg.reference_trace = try reference_stack.toOwnedSlice();
2401 }2404 }
2402 if (sema.owner_func) |func| {2405 const ip = &mod.intern_pool;
2403 func.state = .sema_failure;2406 if (sema.owner_func_index != .none) {
2407 ip.funcAnalysis(sema.owner_func_index).state = .sema_failure;
2404 } else {2408 } else {
2405 sema.owner_decl.analysis = .sema_failure;2409 sema.owner_decl.analysis = .sema_failure;
2406 sema.owner_decl.generation = mod.generation;2410 sema.owner_decl.generation = mod.generation;
2407 }2411 }
2408 if (sema.func) |func| {2412 if (sema.func_index != .none) {
2409 func.state = .sema_failure;2413 ip.funcAnalysis(sema.func_index).state = .sema_failure;
2410 }2414 }
2411 const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index);2415 const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index);
2412 if (gop.found_existing) {2416 if (gop.found_existing) {
...@@ -2866,6 +2870,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2866,6 +2870,7 @@ fn createAnonymousDeclTypeNamed(
2866 inst: ?Zir.Inst.Index,2870 inst: ?Zir.Inst.Index,
2867) !Decl.Index {2871) !Decl.Index {
2868 const mod = sema.mod;2872 const mod = sema.mod;
2873 const ip = &mod.intern_pool;
2869 const gpa = sema.gpa;2874 const gpa = sema.gpa;
2870 const namespace = block.namespace;2875 const namespace = block.namespace;
2871 const src_scope = block.wip_capture_scope;2876 const src_scope = block.wip_capture_scope;
...@@ -2895,7 +2900,7 @@ fn createAnonymousDeclTypeNamed(...@@ -2895,7 +2900,7 @@ fn createAnonymousDeclTypeNamed(
2895 return new_decl_index;2900 return new_decl_index;
2896 },2901 },
2897 .func => {2902 .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));
2899 const zir_tags = sema.code.instructions.items(.tag);2904 const zir_tags = sema.code.instructions.items(.tag);
29002905
2901 var buf = std.ArrayList(u8).init(gpa);2906 var buf = std.ArrayList(u8).init(gpa);
...@@ -3070,18 +3075,12 @@ fn zirEnumDecl(...@@ -3070,18 +3075,12 @@ fn zirEnumDecl(
3070 sema.owner_decl_index = prev_owner_decl_index;3075 sema.owner_decl_index = prev_owner_decl_index;
3071 }3076 }
30723077
3073 const prev_owner_func = sema.owner_func;
3074 const prev_owner_func_index = sema.owner_func_index;3078 const prev_owner_func_index = sema.owner_func_index;
3075 sema.owner_func = null;
3076 sema.owner_func_index = .none;3079 sema.owner_func_index = .none;
3077 defer sema.owner_func = prev_owner_func;
3078 defer sema.owner_func_index = prev_owner_func_index;3080 defer sema.owner_func_index = prev_owner_func_index;
30793081
3080 const prev_func = sema.func;
3081 const prev_func_index = sema.func_index;3082 const prev_func_index = sema.func_index;
3082 sema.func = null;
3083 sema.func_index = .none;3083 sema.func_index = .none;
3084 defer sema.func = prev_func;
3085 defer sema.func_index = prev_func_index;3084 defer sema.func_index = prev_func_index;
30863085
3087 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);3086 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);
...@@ -3393,7 +3392,7 @@ fn zirErrorSetDecl(...@@ -3393,7 +3392,7 @@ fn zirErrorSetDecl(
3393 const src = inst_data.src();3392 const src = inst_data.src();
3394 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);3393 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 = .{};
3397 try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len);3396 try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len);
33983397
3399 var extra_index = @as(u32, @intCast(extra.end));3398 var extra_index = @as(u32, @intCast(extra.end));
...@@ -5379,7 +5378,10 @@ fn zirCompileLog(...@@ -5379,7 +5378,10 @@ fn zirCompileLog(
5379 }5378 }
5380 try writer.print("\n", .{});5379 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;
5383 const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index);5385 const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index);
5384 if (!gop.found_existing) {5386 if (!gop.found_existing) {
5385 gop.value_ptr.* = src_node;5387 gop.value_ptr.* = src_node;
...@@ -5967,11 +5969,11 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -5967,11 +5969,11 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5967 alignment.toByteUnitsOptional().?,5969 alignment.toByteUnitsOptional().?,
5968 });5970 });
5969 }5971 }
5970 const func_index = sema.func_index.unwrap() orelse5972 if (sema.func_index == .none) {
5971 return sema.fail(block, src, "@setAlignStack outside function body", .{});5973 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);
5975 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {5977 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
5976 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),5978 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
5977 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),5979 .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...@@ -5980,25 +5982,34 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5980 },5982 },
5981 }5983 }
59825984
5983 const gop = try mod.align_stack_fns.getOrPut(sema.gpa, func_index);5985 if (sema.prev_stack_alignment_src) |prev_src| {
5984 if (gop.found_existing) {
5985 const msg = msg: {5986 const msg = msg: {
5986 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});5987 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});
5987 errdefer msg.destroy(sema.gpa);5988 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", .{});
5989 break :msg msg;5990 break :msg msg;
5990 };5991 };
5991 return sema.failWithOwnedErrorMsg(msg);5992 return sema.failWithOwnedErrorMsg(msg);
5992 }5993 }
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 }
5994}6003}
59956004
5996fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {6005fn zirSetCold(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
6006 const mod = sema.mod;
6007 const ip = &mod.intern_pool;
5997 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;6008 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
5998 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };6009 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
5999 const is_cold = try sema.resolveConstBool(block, operand_src, extra.operand, "operand to @setCold must be comptime-known");6010 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 function6011 if (sema.func_index == .none) return; // does nothing outside a function
6001 func.is_cold = is_cold;6012 ip.funcAnalysis(sema.func_index).is_cold = is_cold;
6002}6013}
60036014
6004fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {6015fn 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 {...@@ -6308,7 +6319,7 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
6308 if (func_val.isUndef(mod)) return null;6319 if (func_val.isUndef(mod)) return null;
6309 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {6320 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
6310 .extern_func => |extern_func| extern_func.decl,6321 .extern_func => |extern_func| extern_func.decl,
6311 .func => |func| mod.funcPtr(func.index).owner_decl,6322 .func => |func| func.owner_decl,
6312 .ptr => |ptr| switch (ptr.addr) {6323 .ptr => |ptr| switch (ptr.addr) {
6313 .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl,6324 .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl,
6314 else => return null,6325 else => return null,
...@@ -6445,6 +6456,7 @@ fn zirCall(...@@ -6445,6 +6456,7 @@ fn zirCall(
6445 defer tracy.end();6456 defer tracy.end();
64466457
6447 const mod = sema.mod;6458 const mod = sema.mod;
6459 const ip = &mod.intern_pool;
6448 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6460 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6449 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };6461 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
6450 const call_src = inst_data.src();6462 const call_src = inst_data.src();
...@@ -6493,9 +6505,10 @@ fn zirCall(...@@ -6493,9 +6505,10 @@ fn zirCall(
6493 const args_body = sema.code.extra[extra.end..];6505 const args_body = sema.code.extra[extra.end..];
64946506
6495 var input_is_error = false;6507 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;
6499 const parent_comptime = block.is_comptime;6512 const parent_comptime = block.is_comptime;
6500 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.6513 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
6501 var extra_index: usize = 0;6514 var extra_index: usize = 0;
...@@ -6504,13 +6517,12 @@ fn zirCall(...@@ -6504,13 +6517,12 @@ fn zirCall(
6504 extra_index += 1;6517 extra_index += 1;
6505 arg_index += 1;6518 arg_index += 1;
6506 }) {6519 }) {
6507 const func_ty_info = mod.typeToFunc(func_ty).?;
6508 const arg_end = sema.code.extra[extra.end + extra_index];6520 const arg_end = sema.code.extra[extra.end + extra_index];
6509 defer arg_start = arg_end;6521 defer arg_start = arg_end;
65106522
6511 // Generate args to comptime params in comptime block.6523 // Generate args to comptime params in comptime block.
6512 defer block.is_comptime = parent_comptime;6524 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))) {
6514 block.is_comptime = true;6526 block.is_comptime = true;
6515 // TODO set comptime_reason6527 // TODO set comptime_reason
6516 }6528 }
...@@ -6519,10 +6531,10 @@ fn zirCall(...@@ -6519,10 +6531,10 @@ fn zirCall(
6519 if (arg_index >= fn_params_len)6531 if (arg_index >= fn_params_len)
6520 break :inst Air.Inst.Ref.var_args_param_type;6532 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)
6523 break :inst Air.Inst.Ref.generic_poison_type;6535 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());
6526 });6538 });
65276539
6528 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);6540 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
...@@ -6535,7 +6547,9 @@ fn zirCall(...@@ -6535,7 +6547,9 @@ fn zirCall(
6535 }6547 }
6536 resolved_args[arg_index] = resolved;6548 resolved_args[arg_index] = resolved;
6537 }6549 }
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 {
6539 input_is_error = false; // input was an error type, but no errorable fn's were actually called6553 input_is_error = false; // input was an error type, but no errorable fn's were actually called
6540 }6554 }
65416555
...@@ -6702,6 +6716,7 @@ fn analyzeCall(...@@ -6702,6 +6716,7 @@ fn analyzeCall(
6702 call_dbg_node: ?Zir.Inst.Index,6716 call_dbg_node: ?Zir.Inst.Index,
6703) CompileError!Air.Inst.Ref {6717) CompileError!Air.Inst.Ref {
6704 const mod = sema.mod;6718 const mod = sema.mod;
6719 const ip = &mod.intern_pool;
67056720
6706 const callee_ty = sema.typeOf(func);6721 const callee_ty = sema.typeOf(func);
6707 const func_ty_info = mod.typeToFunc(func_ty).?;6722 const func_ty_info = mod.typeToFunc(func_ty).?;
...@@ -6749,20 +6764,17 @@ fn analyzeCall(...@@ -6749,20 +6764,17 @@ fn analyzeCall(
67496764
6750 var is_generic_call = func_ty_info.is_generic;6765 var is_generic_call = func_ty_info.is_generic;
6751 var is_comptime_call = block.is_comptime or modifier == .compile_time;6766 var is_comptime_call = block.is_comptime or modifier == .compile_time;
6752 var comptime_reason_buf: Block.ComptimeReason = undefined;
6753 var comptime_reason: ?*const Block.ComptimeReason = null;6767 var comptime_reason: ?*const Block.ComptimeReason = null;
6754 if (!is_comptime_call) {6768 if (!is_comptime_call) {
6755 if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| {6769 if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| {
6756 is_comptime_call = ct;6770 is_comptime_call = ct;
6757 if (ct) {6771 if (ct) {
6758 // stage1 can't handle doing this directly6772 comptime_reason = &.{ .comptime_ret_ty = .{
6759 comptime_reason_buf = .{ .comptime_ret_ty = .{
6760 .block = block,6773 .block = block,
6761 .func = func,6774 .func = func,
6762 .func_src = func_src,6775 .func_src = func_src,
6763 .return_ty = func_ty_info.return_type.toType(),6776 .return_ty = func_ty_info.return_type.toType(),
6764 } };6777 } };
6765 comptime_reason = &comptime_reason_buf;
6766 }6778 }
6767 } else |err| switch (err) {6779 } else |err| switch (err) {
6768 error.GenericPoison => is_generic_call = true,6780 error.GenericPoison => is_generic_call = true,
...@@ -6778,7 +6790,6 @@ fn analyzeCall(...@@ -6778,7 +6790,6 @@ fn analyzeCall(
6778 func,6790 func,
6779 func_src,6791 func_src,
6780 call_src,6792 call_src,
6781 func_ty,
6782 ensure_result_used,6793 ensure_result_used,
6783 uncasted_args,6794 uncasted_args,
6784 call_tag,6795 call_tag,
...@@ -6793,14 +6804,12 @@ fn analyzeCall(...@@ -6793,14 +6804,12 @@ fn analyzeCall(
6793 error.ComptimeReturn => {6804 error.ComptimeReturn => {
6794 is_inline_call = true;6805 is_inline_call = true;
6795 is_comptime_call = true;6806 is_comptime_call = true;
6796 // stage1 can't handle doing this directly6807 comptime_reason = &.{ .comptime_ret_ty = .{
6797 comptime_reason_buf = .{ .comptime_ret_ty = .{
6798 .block = block,6808 .block = block,
6799 .func = func,6809 .func = func,
6800 .func_src = func_src,6810 .func_src = func_src,
6801 .return_ty = func_ty_info.return_type.toType(),6811 .return_ty = func_ty_info.return_type.toType(),
6802 } };6812 } };
6803 comptime_reason = &comptime_reason_buf;
6804 },6813 },
6805 else => |e| return e,6814 else => |e| return e,
6806 }6815 }
...@@ -6819,9 +6828,9 @@ fn analyzeCall(...@@ -6819,9 +6828,9 @@ fn analyzeCall(
6819 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{6828 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
6820 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),6829 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
6821 }),6830 }),
6822 .func => |function| function.index,6831 .func => func_val.toIntern(),
6823 .ptr => |ptr| switch (ptr.addr) {6832 .ptr => |ptr| switch (ptr.addr) {
6824 .decl => |decl| mod.declPtr(decl).val.getFunctionIndex(mod).unwrap().?,6833 .decl => |decl| mod.declPtr(decl).val.toIntern(),
6825 else => {6834 else => {
6826 assert(callee_ty.isPtrAtRuntime(mod));6835 assert(callee_ty.isPtrAtRuntime(mod));
6827 return sema.fail(block, call_src, "{s} call of function pointer", .{6836 return sema.fail(block, call_src, "{s} call of function pointer", .{
...@@ -6850,7 +6859,7 @@ fn analyzeCall(...@@ -6850,7 +6859,7 @@ fn analyzeCall(
6850 // This one is shared among sub-blocks within the same callee, but not6859 // This one is shared among sub-blocks within the same callee, but not
6851 // shared among the entire inline/comptime call stack.6860 // shared among the entire inline/comptime call stack.
6852 var inlining: Block.Inlining = .{6861 var inlining: Block.Inlining = .{
6853 .func = null,6862 .func = .none,
6854 .comptime_result = undefined,6863 .comptime_result = undefined,
6855 .merges = .{6864 .merges = .{
6856 .src_locs = .{},6865 .src_locs = .{},
...@@ -6862,7 +6871,7 @@ fn analyzeCall(...@@ -6862,7 +6871,7 @@ fn analyzeCall(
6862 // In order to save a bit of stack space, directly modify Sema rather6871 // In order to save a bit of stack space, directly modify Sema rather
6863 // than create a child one.6872 // than create a child one.
6864 const parent_zir = sema.code;6873 const parent_zir = sema.code;
6865 const module_fn = mod.funcPtr(module_fn_index);6874 const module_fn = mod.funcInfo(module_fn_index);
6866 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);6875 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
6867 sema.code = fn_owner_decl.getFileScope(mod).zir;6876 sema.code = fn_owner_decl.getFileScope(mod).zir;
6868 defer sema.code = parent_zir;6877 defer sema.code = parent_zir;
...@@ -6877,11 +6886,8 @@ fn analyzeCall(...@@ -6877,11 +6886,8 @@ fn analyzeCall(
6877 sema.inst_map = parent_inst_map;6886 sema.inst_map = parent_inst_map;
6878 }6887 }
68796888
6880 const parent_func = sema.func;
6881 const parent_func_index = sema.func_index;6889 const parent_func_index = sema.func_index;
6882 sema.func = module_fn;6890 sema.func_index = module_fn_index;
6883 sema.func_index = module_fn_index.toOptional();
6884 defer sema.func = parent_func;
6885 defer sema.func_index = parent_func_index;6891 defer sema.func_index = parent_func_index;
68866892
6887 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;6893 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
...@@ -6913,16 +6919,30 @@ fn analyzeCall(...@@ -6913,16 +6919,30 @@ fn analyzeCall(
69136919
6914 try sema.emitBackwardBranch(block, call_src);6920 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.
6917 var should_memoize = true;6924 var should_memoize = true;
69186925
6919 // If it's a comptime function call, we need to memoize it as long as no external6926 // If it's a comptime function call, we need to memoize it as long as no external
6920 // comptime memory is mutated.6927 // comptime memory is mutated.
6921 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);6928 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).?;6930 const owner_info = mod.typeToFunc(fn_owner_decl.ty).?;
6924 new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len);6931 var new_fn_info: InternPool.GetFuncTypeKey = .{
6925 new_fn_info.comptime_bits = 0;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
6927 // This will have return instructions analyzed as break instructions to6947 // This will have return instructions analyzed as break instructions to
6928 // the block_inst above. Here we are performing "comptime/inline semantic analysis"6948 // the block_inst above. Here we are performing "comptime/inline semantic analysis"
...@@ -6934,59 +6954,42 @@ fn analyzeCall(...@@ -6934,59 +6954,42 @@ fn analyzeCall(
6934 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body);6954 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, fn_info.param_body);
69356955
6936 var has_comptime_args = false;6956 var has_comptime_args = false;
6937 var arg_i: usize = 0;6957 var arg_i: u32 = 0;
6938 for (fn_info.param_body) |inst| {6958 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(
6940 block,6964 block,
6941 &child_block,6965 &child_block,
6942 .unneeded,6966 arg_src,
6943 inst,6967 inst,
6944 &new_fn_info,6968 new_fn_info.param_types,
6945 &arg_i,6969 &arg_i,
6946 uncasted_args,6970 uncasted_args,
6947 is_comptime_call,6971 is_comptime_call,
6948 &should_memoize,6972 &should_memoize,
6949 memoized_arg_values,6973 memoized_arg_values,
6950 mod.typeToFunc(func_ty).?.param_types,6974 func_ty_info.param_types,
6951 func,6975 func,
6952 &has_comptime_args,6976 &has_comptime_args,
6953 ) catch |err| switch (err) {6977 );
6954 error.NeededSourceLocation => {
6955 _ = sema.inst_map.remove(inst);
6956 const decl = mod.declPtr(block.src_decl);
6957 try sema.analyzeInlineCallArg(
6958 block,
6959 &child_block,
6960 mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src),
6961 inst,
6962 &new_fn_info,
6963 &arg_i,
6964 uncasted_args,
6965 is_comptime_call,
6966 &should_memoize,
6967 memoized_arg_values,
6968 mod.typeToFunc(func_ty).?.param_types,
6969 func,
6970 &has_comptime_args,
6971 );
6972 unreachable;
6973 },
6974 else => |e| return e,
6975 };
6976 }6978 }
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
6980 const recursive_msg = "inline call is recursive";6983 const recursive_msg = "inline call is recursive";
6981 var head = if (!has_comptime_args) block else null;6984 var head = if (!has_comptime_args) block else null;
6982 while (head) |some| {6985 while (head) |some| {
6983 const parent_inlining = some.inlining orelse break;6986 const parent_inlining = some.inlining orelse break;
6984 if (parent_inlining.func == module_fn) {6987 if (parent_inlining.func == module_fn_index) {
6985 return sema.fail(block, call_src, recursive_msg, .{});6988 return sema.fail(block, call_src, recursive_msg, .{});
6986 }6989 }
6987 head = some.parent;6990 head = some.parent;
6988 }6991 }
6989 if (!has_comptime_args) inlining.func = module_fn;6992 if (!has_comptime_args) inlining.func = module_fn_index;
69906993
6991 // In case it is a generic function with an expression for the return type that depends6994 // In case it is a generic function with an expression for the return type that depends
6992 // on parameters, we must now do the same for the return type as we just did with6995 // on parameters, we must now do the same for the return type as we just did with
...@@ -7000,7 +7003,7 @@ fn analyzeCall(...@@ -7000,7 +7003,7 @@ fn analyzeCall(
7000 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);7003 const bare_return_type = try sema.analyzeAsType(&child_block, ret_ty_src, ret_ty_inst);
7001 // Create a fresh inferred error set type for inline/comptime calls.7004 // Create a fresh inferred error set type for inline/comptime calls.
7002 const fn_ret_ty = blk: {7005 const fn_ret_ty = blk: {
7003 if (module_fn.hasInferredErrorSet(mod)) {7006 if (mod.hasInferredErrorSet(module_fn)) {
7004 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{7007 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
7005 .func = module_fn_index,7008 .func = module_fn_index,
7006 });7009 });
...@@ -7032,7 +7035,7 @@ fn analyzeCall(...@@ -7032,7 +7035,7 @@ fn analyzeCall(
70327035
7033 const new_func_resolved_ty = try mod.funcType(new_fn_info);7036 const new_func_resolved_ty = try mod.funcType(new_fn_info);
7034 if (!is_comptime_call and !block.is_typeof) {7037 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
7037 const zir_tags = sema.code.instructions.items(.tag);7040 const zir_tags = sema.code.instructions.items(.tag);
7038 for (fn_info.param_body) |param| switch (zir_tags[param]) {7041 for (fn_info.param_body) |param| switch (zir_tags[param]) {
...@@ -7078,21 +7081,22 @@ fn analyzeCall(...@@ -7078,21 +7081,22 @@ fn analyzeCall(
7078 try sema.emitDbgInline(7081 try sema.emitDbgInline(
7079 block,7082 block,
7080 module_fn_index,7083 module_fn_index,
7081 parent_func_index.unwrap().?,7084 parent_func_index,
7082 mod.declPtr(parent_func.?.owner_decl).ty,7085 mod.funcOwnerDeclPtr(parent_func_index).ty,
7083 .dbg_inline_end,7086 .dbg_inline_end,
7084 );7087 );
7085 }7088 }
70867089
7087 if (should_memoize and is_comptime_call) {7090 if (should_memoize and is_comptime_call) {
7088 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");7091 const result_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, result, "");
7092 const result_interned = try result_val.intern(fn_ret_ty, mod);
70897093
7090 // TODO: check whether any external comptime memory was mutated by the7094 // TODO: check whether any external comptime memory was mutated by the
7091 // comptime function call. If so, then do not memoize the call here.7095 // comptime function call. If so, then do not memoize the call here.
7092 _ = try mod.intern(.{ .memoized_call = .{7096 _ = try mod.intern(.{ .memoized_call = .{
7093 .func = module_fn_index,7097 .func = module_fn_index,
7094 .arg_values = memoized_arg_values,7098 .arg_values = memoized_arg_values,
7095 .result = try result_val.intern(fn_ret_ty, mod),7099 .result = result_interned,
7096 } });7100 } });
7097 }7101 }
70987102
...@@ -7112,7 +7116,7 @@ fn analyzeCall(...@@ -7112,7 +7116,7 @@ fn analyzeCall(
7112 .func_inst = func,7116 .func_inst = func,
7113 .param_i = @as(u32, @intCast(i)),7117 .param_i = @as(u32, @intCast(i)),
7114 } };7118 } };
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();
7116 args[i] = sema.analyzeCallArg(7120 args[i] = sema.analyzeCallArg(
7117 block,7121 block,
7118 .unneeded,7122 .unneeded,
...@@ -7152,13 +7156,13 @@ fn analyzeCall(...@@ -7152,13 +7156,13 @@ fn analyzeCall(
7152 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);7156 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
71537157
7154 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());7158 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7155 if (sema.owner_func != null and func_ty_info.return_type.toType().isError(mod)) {7159 if (sema.owner_func_index != .none and func_ty_info.return_type.toType().isError(mod)) {
7156 sema.owner_func.?.calls_or_awaits_errorable_fn = true;7160 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
7157 }7161 }
71587162
7159 if (try sema.resolveMaybeUndefVal(func)) |func_val| {7163 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7160 if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| {7164 if (mod.intern_pool.isFuncBody(func_val.toIntern())) {
7161 try mod.ensureFuncBodyAnalysisQueued(func_index);7165 try mod.ensureFuncBodyAnalysisQueued(func_val.toIntern());
7162 }7166 }
7163 }7167 }
71647168
...@@ -7219,7 +7223,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ...@@ -7219,7 +7223,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ
7219 @tagName(backend), @tagName(target.cpu.arch),7223 @tagName(backend), @tagName(target.cpu.arch),
7220 });7224 });
7221 }7225 }
7222 const func_decl = mod.declPtr(sema.owner_func.?.owner_decl);7226 const func_decl = mod.funcOwnerDeclPtr(sema.owner_func_index);
7223 if (!func_ty.eql(func_decl.ty, mod)) {7227 if (!func_ty.eql(func_decl.ty, mod)) {
7224 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{7228 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{
7225 func_ty.fmt(mod), func_decl.ty.fmt(mod),7229 func_ty.fmt(mod), func_decl.ty.fmt(mod),
...@@ -7235,17 +7239,18 @@ fn analyzeInlineCallArg(...@@ -7235,17 +7239,18 @@ fn analyzeInlineCallArg(
7235 param_block: *Block,7239 param_block: *Block,
7236 arg_src: LazySrcLoc,7240 arg_src: LazySrcLoc,
7237 inst: Zir.Inst.Index,7241 inst: Zir.Inst.Index,
7238 new_fn_info: *InternPool.Key.FuncType,7242 new_param_types: []InternPool.Index,
7239 arg_i: *usize,7243 arg_i: *u32,
7240 uncasted_args: []const Air.Inst.Ref,7244 uncasted_args: []const Air.Inst.Ref,
7241 is_comptime_call: bool,7245 is_comptime_call: bool,
7242 should_memoize: *bool,7246 should_memoize: *bool,
7243 memoized_arg_values: []InternPool.Index,7247 memoized_arg_values: []InternPool.Index,
7244 raw_param_types: []const InternPool.Index,7248 raw_param_types: InternPool.Index.Slice,
7245 func_inst: Air.Inst.Ref,7249 func_inst: Air.Inst.Ref,
7246 has_comptime_args: *bool,7250 has_comptime_args: *bool,
7247) !void {7251) !void {
7248 const mod = sema.mod;7252 const mod = sema.mod;
7253 const ip = &mod.intern_pool;
7249 const zir_tags = sema.code.instructions.items(.tag);7254 const zir_tags = sema.code.instructions.items(.tag);
7250 switch (zir_tags[inst]) {7255 switch (zir_tags[inst]) {
7251 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,7256 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
...@@ -7260,13 +7265,13 @@ fn analyzeInlineCallArg(...@@ -7260,13 +7265,13 @@ fn analyzeInlineCallArg(
7260 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);7265 const extra = sema.code.extraData(Zir.Inst.Param, pl_tok.payload_index);
7261 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];7266 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
7262 const param_ty = param_ty: {7267 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.*];
7264 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;7269 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;
7265 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);7270 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
7266 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);7271 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
7267 break :param_ty param_ty.toIntern();7272 break :param_ty param_ty.toIntern();
7268 };7273 };
7269 new_fn_info.param_types[arg_i.*] = param_ty;7274 new_param_types[arg_i.*] = param_ty;
7270 const uncasted_arg = uncasted_args[arg_i.*];7275 const uncasted_arg = uncasted_args[arg_i.*];
7271 if (try sema.typeRequiresComptime(param_ty.toType())) {7276 if (try sema.typeRequiresComptime(param_ty.toType())) {
7272 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {7277 _ = 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(...@@ -7317,7 +7322,7 @@ fn analyzeInlineCallArg(
7317 .param_anytype, .param_anytype_comptime => {7322 .param_anytype, .param_anytype_comptime => {
7318 // No coercion needed.7323 // No coercion needed.
7319 const uncasted_arg = uncasted_args[arg_i.*];7324 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
7322 if (is_comptime_call) {7327 if (is_comptime_call) {
7323 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);7328 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
...@@ -7371,50 +7376,12 @@ fn analyzeCallArg(...@@ -7371,50 +7376,12 @@ fn analyzeCallArg(
7371 };7376 };
7372}7377}
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
7411fn instantiateGenericCall(7379fn instantiateGenericCall(
7412 sema: *Sema,7380 sema: *Sema,
7413 block: *Block,7381 block: *Block,
7414 func: Air.Inst.Ref,7382 func: Air.Inst.Ref,
7415 func_src: LazySrcLoc,7383 func_src: LazySrcLoc,
7416 call_src: LazySrcLoc,7384 call_src: LazySrcLoc,
7417 generic_func_ty: Type,
7418 ensure_result_used: bool,7385 ensure_result_used: bool,
7419 uncasted_args: []const Air.Inst.Ref,7386 uncasted_args: []const Air.Inst.Ref,
7420 call_tag: Air.Inst.Tag,7387 call_tag: Air.Inst.Tag,
...@@ -7423,248 +7390,132 @@ fn instantiateGenericCall(...@@ -7423,248 +7390,132 @@ fn instantiateGenericCall(
7423) CompileError!Air.Inst.Ref {7390) CompileError!Air.Inst.Ref {
7424 const mod = sema.mod;7391 const mod = sema.mod;
7425 const gpa = sema.gpa;7392 const gpa = sema.gpa;
7393 const ip = &mod.intern_pool;
74267394
7427 const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");7395 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())) {7396 const module_fn = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7429 .func => |function| function.index,7397 .func => |x| x,
7430 .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.getFunctionIndex(mod).unwrap().?,7398 .ptr => |ptr| mod.intern_pool.indexToKey(mod.declPtr(ptr.addr.decl).val.toIntern()).func,
7431 else => unreachable,7399 else => unreachable,
7432 };7400 };
7433 const module_fn = mod.funcPtr(module_fn_index);7401
7434 // Check the Module's generic function map with an adapted context, so that we7402 // Even though there may already be a generic instantiation corresponding
7435 // can match against `uncasted_args` rather than doing the work below to create a7403 // to this callsite, we must evaluate the expressions of the generic
7436 // generic Scope only to junk it if it matches an existing instantiation.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
7437 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);7410 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
7438 const namespace_index = fn_owner_decl.src_namespace;7411 const namespace_index = fn_owner_decl.src_namespace;
7439 const namespace = mod.namespacePtr(namespace_index);7412 const namespace = mod.namespacePtr(namespace_index);
7440 const fn_zir = namespace.file_scope.zir;7413 const fn_zir = namespace.file_scope.zir;
7441 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);7414 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();7416 const comptime_args = try sema.arena.alloc(InternPool.Index, uncasted_args.len);
7543 new_module_func.comptime_args = null;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.7444 var child_block: Block = .{
7548 const src_decl_index = namespace.getDeclIndex(mod);7445 .parent = null,
7549 const src_decl = mod.declPtr(src_decl_index);7446 .sema = &child_sema,
7550 const new_decl_index = try mod.allocateNewDecl(namespace_index, fn_owner_decl.src_node, src_decl.src_scope);7447 .src_decl = module_fn.owner_decl,
7551 const new_decl = mod.declPtr(new_decl_index);7448 .namespace = namespace_index,
7552 // TODO better names for generic function instantiations7449 .wip_capture_scope = block.wip_capture_scope,
7553 const decl_name = try mod.intern_pool.getOrPutStringFmt(gpa, "{}__anon_{d}", .{7450 .instructions = .{},
7554 fn_owner_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index),7451 .inlining = null,
7555 });7452 .is_comptime = true,
7556 new_decl.name = decl_name;7453 };
7557 new_decl.src_line = fn_owner_decl.src_line;7454 defer child_block.instructions.deinit(gpa);
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;
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 dependency7458 for (fn_info.param_body[0..uncasted_args.len], uncasted_args, 0..) |inst, arg, i| {
7572 // of each of its instantiations.7459 // `child_sema` will use a different `inst_map` which means we have to
7573 assert(new_decl.dependencies.keys().len == 0);7460 // convert from parent-relative `Air.Inst.Ref` to child-relative here.
7574 try mod.declareDeclDependencyType(new_decl_index, module_fn.owner_decl, .function_body);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(7476 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
7577 block,7477 const callee_index = (child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable).toIntern();
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 };
76137478
7614 break :callee new_func;7479 const callee = mod.funcInfo(callee_index);
7615 };7480 callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota);
7616 const callee = mod.funcPtr(callee_index);
7617 callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);
76187481
7619 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);7482 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);
76207483
7621 // Make a runtime call to the new function, making sure to omit the comptime args.7484 // Make a runtime call to the new function, making sure to omit the comptime args.
7622 const comptime_args = callee.comptime_args.?;7485 const func_ty = callee.ty.toType();
7623 const func_ty = mod.declPtr(callee.owner_decl).ty;7486 const func_ty_info = mod.typeToFunc(func_ty).?;
7624 const runtime_args_len = @as(u32, @intCast(mod.typeToFunc(func_ty).?.param_types.len));7487 const runtime_args_len: u32 = func_ty_info.param_types.len;
7625 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);7488 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
7626 {7489 {
7627 var runtime_i: u32 = 0;7490 var runtime_i: u32 = 0;
7628 var total_i: u32 = 0;7491 for (uncasted_args, 0..) |uncasted_arg, total_i| {
7629 for (fn_info.param_body) |inst| {7492 const arg_src: LazySrcLoc = if (total_i == 0 and bound_arg_src != null)
7630 switch (zir_tags[inst]) {7493 bound_arg_src.?
7631 .param_comptime, .param_anytype_comptime, .param, .param_anytype => {},7494 else
7632 else => continue,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;
7633 }7507 }
7634 sema.analyzeGenericCallArg(
7635 block,
7636 .unneeded,
7637 uncasted_args[total_i],
7638 comptime_args[total_i],
7639 runtime_args,
7640 mod.typeToFunc(func_ty).?,
7641 &runtime_i,
7642 ) catch |err| switch (err) {
7643 error.NeededSourceLocation => {
7644 const decl = mod.declPtr(block.src_decl);
7645 _ = try sema.analyzeGenericCallArg(
7646 block,
7647 mod.argSrc(call_src.node_offset.x, decl, total_i, bound_arg_src),
7648 uncasted_args[total_i],
7649 comptime_args[total_i],
7650 runtime_args,
7651 mod.typeToFunc(func_ty).?,
7652 &runtime_i,
7653 );
7654 unreachable;
7655 },
7656 else => |e| return e,
7657 };
7658 total_i += 1;
7659 }7508 }
76607509
7661 try sema.queueFullTypeResolution(mod.typeToFunc(func_ty).?.return_type.toType());7510 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7662 }7511 }
76637512
7664 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);7513 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)) {7515 if (sema.owner_func_index != .none and
7667 sema.owner_func.?.calls_or_awaits_errorable_fn = true;7516 func_ty_info.return_type.toType().isError(mod))
7517 {
7518 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
7668 }7519 }
76697520
7670 try mod.ensureFuncBodyAnalysisQueued(callee_index);7521 try mod.ensureFuncBodyAnalysisQueued(callee_index);
...@@ -7695,238 +7546,6 @@ fn instantiateGenericCall(...@@ -7695,238 +7546,6 @@ fn instantiateGenericCall(
7695 return result;7546 return result;
7696}7547}
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
7930fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {7549fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
7931 const mod = sema.mod;7550 const mod = sema.mod;
7932 const tuple = switch (mod.intern_pool.indexToKey(ty.toIntern())) {7551 const tuple = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
...@@ -7944,8 +7563,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)...@@ -7944,8 +7563,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
7944fn emitDbgInline(7563fn emitDbgInline(
7945 sema: *Sema,7564 sema: *Sema,
7946 block: *Block,7565 block: *Block,
7947 old_func: Module.Fn.Index,7566 old_func: InternPool.Index,
7948 new_func: Module.Fn.Index,7567 new_func: InternPool.Index,
7949 new_func_ty: Type,7568 new_func_ty: Type,
7950 tag: Air.Inst.Tag,7569 tag: Air.Inst.Tag,
7951) CompileError!void {7570) CompileError!void {
...@@ -8802,7 +8421,7 @@ fn zirFunc(...@@ -8802,7 +8421,7 @@ fn zirFunc(
8802 inst,8421 inst,
8803 .none,8422 .none,
8804 target_util.defaultAddressSpace(target, .function),8423 target_util.defaultAddressSpace(target, .function),
8805 FuncLinkSection.default,8424 .default,
8806 cc,8425 cc,
8807 ret_ty,8426 ret_ty,
8808 false,8427 false,
...@@ -8831,10 +8450,7 @@ fn resolveGenericBody(...@@ -8831,10 +8450,7 @@ fn resolveGenericBody(
8831 // Make sure any nested param instructions don't clobber our work.8450 // Make sure any nested param instructions don't clobber our work.
8832 const prev_params = block.params;8451 const prev_params = block.params;
8833 block.params = .{};8452 block.params = .{};
8834 defer {8453 defer block.params = prev_params;
8835 block.params.deinit(sema.gpa);
8836 block.params = prev_params;
8837 }
88388454
8839 const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err;8455 const uncasted = sema.resolveBody(block, body, func_inst) catch |err| break :err err;
8840 const result = sema.coerce(block, dest_ty, uncasted, src) catch |err| break :err err;8456 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:...@@ -8952,12 +8568,6 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
8952 }8568 }
8953}8569}
89548570
8955const FuncLinkSection = union(enum) {
8956 generic,
8957 default,
8958 explicit: InternPool.NullTerminatedString,
8959};
8960
8961fn funcCommon(8571fn funcCommon(
8962 sema: *Sema,8572 sema: *Sema,
8963 block: *Block,8573 block: *Block,
...@@ -8967,8 +8577,7 @@ fn funcCommon(...@@ -8967,8 +8577,7 @@ fn funcCommon(
8967 alignment: ?Alignment,8577 alignment: ?Alignment,
8968 /// null means generic poison8578 /// null means generic poison
8969 address_space: ?std.builtin.AddressSpace,8579 address_space: ?std.builtin.AddressSpace,
8970 /// outer null means generic poison; inner null means default link section8580 section: InternPool.GetFuncDeclKey.Section,
8971 section: FuncLinkSection,
8972 /// null means generic poison8581 /// null means generic poison
8973 cc: ?std.builtin.CallingConvention,8582 cc: ?std.builtin.CallingConvention,
8974 /// this might be Type.generic_poison8583 /// this might be Type.generic_poison
...@@ -8984,6 +8593,8 @@ fn funcCommon(...@@ -8984,6 +8593,8 @@ fn funcCommon(
8984) CompileError!Air.Inst.Ref {8593) CompileError!Air.Inst.Ref {
8985 const mod = sema.mod;8594 const mod = sema.mod;
8986 const gpa = sema.gpa;8595 const gpa = sema.gpa;
8596 const target = mod.getTarget();
8597 const ip = &mod.intern_pool;
8987 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };8598 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
8988 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };8599 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };
8989 const func_src = LazySrcLoc.nodeOffset(src_node_offset);8600 const func_src = LazySrcLoc.nodeOffset(src_node_offset);
...@@ -9001,367 +8612,323 @@ fn funcCommon(...@@ -9001,367 +8612,323 @@ fn funcCommon(
9001 try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?);8612 try sema.checkCallConvSupportsVarArgs(block, cc_src, cc.?);
9002 }8613 }
90038614
9004 var destroy_fn_on_error = false;8615 const is_source_decl = sema.generic_owner == .none;
9005 const new_func_index = new_func: {
9006 if (!has_body) break :new_func undefined;
9007 if (sema.comptime_args_fn_inst == func_inst) {
9008 const new_func_index = sema.preallocated_new_func.unwrap().?;
9009 sema.preallocated_new_func = .none; // take ownership
9010 break :new_func new_func_index;
9011 }
9012 destroy_fn_on_error = true;
9013 var new_func: Module.Fn = undefined;
9014 // Set this here so that the inferred return type can be printed correctly if it appears in an error.
9015 new_func.owner_decl = sema.owner_decl_index;
9016 const new_func_index = try mod.createFunc(new_func);
9017 break :new_func new_func_index;
9018 };
9019 errdefer if (destroy_fn_on_error) mod.destroyFunc(new_func_index);
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 };
90778616
9078 const return_type: Type = if (!inferred_error_set or ret_poison)8617 // In the case of generic calling convention, or generic alignment, we use
9079 bare_return_type8618 // default values which are only meaningful for the generic function, *not*
9080 else blk: {8619 // the instantiation, which can depend on comptime parameters.
9081 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);8620 // Related proposal: https://github.com/ziglang/zig/issues/11834
9082 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{8621 const cc_resolved = cc orelse .Unspecified;
9083 .func = new_func_index,8622 var comptime_bits: u32 = 0;
9084 });8623 for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| {
9085 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });8624 const param_ty = param_ty_ip.toType();
9086 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);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;
9087 };8628 };
90888629 const param_src: LazySrcLoc = .{ .fn_proto_param = .{
9089 if (!return_type.isValidReturnType(mod)) {8630 .fn_proto_node_offset = src_node_offset,
9090 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";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 "";
9091 const msg = msg: {8647 const msg = msg: {
9092 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{8648 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{
9093 opaque_str, return_type.fmt(mod),8649 opaque_str, param_ty.fmt(mod),
9094 });8650 });
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);
9098 break :msg msg;8654 break :msg msg;
9099 };8655 };
9100 return sema.failWithOwnedErrorMsg(msg);8656 return sema.failWithOwnedErrorMsg(msg);
9101 }8657 }
9102 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and8658 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(param_ty, .param_ty)) {
9103 !try sema.validateExternType(return_type, .ret_ty))
9104 {
9105 const msg = msg: {8659 const msg = msg: {
9106 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{8660 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
9107 return_type.fmt(mod), @tagName(cc_resolved),8661 param_ty.fmt(mod), @tagName(cc_resolved),
9108 });8662 });
9109 errdefer msg.destroy(gpa);8663 errdefer msg.destroy(sema.gpa);
91108664
9111 const src_decl = mod.declPtr(block.src_decl);8665 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);
9115 break :msg msg;8669 break :msg msg;
9116 };8670 };
9117 return sema.failWithOwnedErrorMsg(msg);8671 return sema.failWithOwnedErrorMsg(msg);
9118 }8672 }
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 comptime8680 const src_decl = mod.declPtr(block.src_decl);
9121 if (!sema.is_generic_instantiation and has_body and ret_ty_requires_comptime) comptime_check: {8681 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param_ty);
9122 for (block.params.items) |param| {
9123 if (!param.is_comptime) break;
9124 } else break :comptime_check;
91258682
9126 const msg = try sema.errMsg(8683 try sema.addDeclaredHereNote(msg, param_ty);
9127 block,8684 break :msg msg;
9128 ret_ty_src,8685 };
9129 "function with comptime-only return type '{}' requires all parameters to be comptime",
9130 .{return_type.fmt(mod)},
9131 );
9132 try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl, mod), return_type);
9133
9134 const tags = sema.code.instructions.items(.tag);
9135 const data = sema.code.instructions.items(.data);
9136 const param_body = sema.code.getParamBody(func_inst);
9137 for (block.params.items, 0..) |param, i| {
9138 if (!param.is_comptime) {
9139 const param_index = param_body[i];
9140 const param_src = switch (tags[param_index]) {
9141 .param => data[param_index].pl_tok.src(),
9142 .param_anytype => data[param_index].str_tok.src(),
9143 else => unreachable,
9144 };
9145 if (param.name.len != 0) {
9146 try sema.errNote(block, param_src, msg, "param '{s}' is required to be comptime", .{param.name});
9147 } else {
9148 try sema.errNote(block, param_src, msg, "param is required to be comptime", .{});
9149 }
9150 }
9151 }
9152 return sema.failWithOwnedErrorMsg(msg);8686 return sema.failWithOwnedErrorMsg(msg);
9153 }8687 }
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;8695 var ret_ty_requires_comptime = false;
9156 if (switch (cc_resolved) {8696 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
9157 .Unspecified, .C, .Naked, .Async, .Inline => null,8697 ret_ty_requires_comptime = ret_comptime;
9158 .Interrupt => switch (arch) {8698 break :rp bare_return_type.isGenericPoison();
9159 .x86, .x86_64, .avr, .msp430 => null,8699 } else |err| switch (err) {
9160 else => @as([]const u8, "x86, x86_64, AVR, and MSP430"),8700 error.GenericPoison => rp: {
9161 },8701 is_generic = true;
9162 .Signal => switch (arch) {8702 break :rp true;
9163 .avr => null,8703 },
9164 else => @as([]const u8, "AVR"),8704 else => |e| return e,
9165 },8705 };
9166 .Stdcall, .Fastcall, .Thiscall => switch (arch) {8706 const final_is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
9167 .x86 => null,8707
9168 else => @as([]const u8, "x86"),8708 const param_types = block.params.items(.ty);
9169 },8709
9170 .Vectorcall => switch (arch) {8710 const opt_func_index: InternPool.Index = i: {
9171 .x86, .aarch64, .aarch64_be, .aarch64_32 => null,8711 if (is_extern) {
9172 else => @as([]const u8, "x86 and AArch64"),8712 assert(comptime_bits == 0);
9173 },8713 assert(cc != null);
9174 .APCS, .AAPCS, .AAPCSVFP => switch (arch) {8714 assert(section != .generic);
9175 .arm, .armeb, .aarch64, .aarch64_be, .aarch64_32, .thumb, .thumbeb => null,8715 assert(address_space != null);
9176 else => @as([]const u8, "ARM"),8716 assert(!is_generic);
9177 },8717 break :i try ip.getExternFunc(gpa, .{
9178 .SysV, .Win64 => switch (arch) {8718 .param_types = param_types,
9179 .x86_64 => null,8719 .noalias_bits = noalias_bits,
9180 else => @as([]const u8, "x86_64"),8720 .return_type = bare_return_type.toIntern(),
9181 },8721 .cc = cc_resolved,
9182 .Kernel => switch (arch) {8722 .alignment = alignment.?,
9183 .nvptx, .nvptx64, .amdgcn, .spirv32, .spirv64 => null,8723 .is_var_args = var_args,
9184 else => @as([]const u8, "nvptx, amdgcn and SPIR-V"),8724 .decl = sema.owner_decl_index,
9185 },8725 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
9186 }) |allowed_platform| {8726 gpa,
9187 return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{8727 try sema.handleExternLibName(block, .{
9188 @tagName(cc_resolved),8728 .node_offset_lib_name = src_node_offset,
9189 allowed_platform,8729 }, lib_name),
9190 @tagName(arch),8730 )).toOptional() else .none,
9191 });8731 });
9192 }8732 }
91938733
9194 if (cc_resolved == .Inline and is_noinline) {8734 if (!has_body) break :i .none;
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;
91998735
9200 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {8736 if (is_source_decl) {
9201 // Make sure that StackTrace's fields are resolved so that the backend can8737 if (inferred_error_set)
9202 // lower this fn type.8738 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
9203 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");8739
9204 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);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 });
9205 }8760 }
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, .{
9208 .param_types = param_types,8770 .param_types = param_types,
9209 .noalias_bits = noalias_bits,8771 .noalias_bits = noalias_bits,
9210 .comptime_bits = comptime_bits,8772 .return_type = bare_return_type.toIntern(),
9211 .return_type = return_type.toIntern(),
9212 .cc = cc_resolved,8773 .cc = cc_resolved,
9213 .cc_is_generic = cc == null,8774 .alignment = alignment.?,
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,
9220 .is_noinline = is_noinline,8775 .is_noinline = is_noinline,
9221 });
9222 };
92238776
9224 sema.owner_decl.@"linksection" = switch (section) {8777 .generic_owner = sema.generic_owner,
9225 .generic => .none,8778 });
9226 .default => .none,
9227 .explicit => |section_name| section_name.toOptional(),
9228 };8779 };
9229 sema.owner_decl.alignment = alignment orelse .none;
9230 sema.owner_decl.@"addrspace" = address_space orelse .generic;
92318780
9232 if (is_extern) {8781 const return_type: Type = if (opt_func_index == .none or ret_poison)
9233 return sema.addConstant((try mod.intern(.{ .extern_func = .{8782 bare_return_type
9234 .ty = fn_ty.toIntern(),8783 else
9235 .decl = sema.owner_decl_index,8784 ip.funcReturnType(ip.typeOf(opt_func_index)).toType();
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}
92788785
9279fn analyzeParameter(8786 if (!return_type.isValidReturnType(mod)) {
9280 sema: *Sema,8787 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";
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 "";
9307 const msg = msg: {8788 const msg = msg: {
9308 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{8789 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{
9309 opaque_str, param.ty.fmt(mod),8790 opaque_str, return_type.fmt(mod),
9310 });8791 });
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);
9314 break :msg msg;8795 break :msg msg;
9315 };8796 };
9316 return sema.failWithOwnedErrorMsg(msg);8797 return sema.failWithOwnedErrorMsg(msg);
9317 }8798 }
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 {
9319 const msg = msg: {8802 const msg = msg: {
9320 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{8803 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
9321 param.ty.fmt(mod), @tagName(cc),8804 return_type.fmt(mod), @tagName(cc_resolved),
9322 });8805 });
9323 errdefer msg.destroy(sema.gpa);8806 errdefer msg.destroy(gpa);
93248807
9325 const src_decl = mod.declPtr(block.src_decl);8808 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);
9329 break :msg msg;8812 break :msg msg;
9330 };8813 };
9331 return sema.failWithOwnedErrorMsg(msg);8814 return sema.failWithOwnedErrorMsg(msg);
9332 }8815 }
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);8817 // If the return type is comptime-only but not dependent on parameters then
9341 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param.ty);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);8824 const msg = try sema.errMsg(
9344 break :msg msg;8825 block,
9345 };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 }
9346 return sema.failWithOwnedErrorMsg(msg);8850 return sema.failWithOwnedErrorMsg(msg);
9347 }8851 }
9348 if (!sema.is_generic_instantiation and !this_generic and is_noalias and8852
9349 !(param.ty.zigTypeTag(mod) == .Pointer or param.ty.isPtrLikeOptional(mod)))8853 const arch = target.cpu.arch;
9350 {8854 if (switch (cc_resolved) {
9351 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});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 });
9352 }8890 }
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);
9353}8919}
93548920
9355fn zirParam(8921fn zirParam(
9356 sema: *Sema,8922 sema: *Sema,
9357 block: *Block,8923 block: *Block,
9358 inst: Zir.Inst.Index,8924 inst: Zir.Inst.Index,
8925 param_index: u32,
9359 comptime_syntax: bool,8926 comptime_syntax: bool,
9360) CompileError!void {8927) CompileError!void {
9361 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;8928 const inst_data = sema.code.instructions.items(.data)[inst].pl_tok;
9362 const src = inst_data.src();8929 const src = inst_data.src();
9363 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index);8930 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);
9365 const body = sema.code.extra[extra.end..][0..extra.data.body_len];8932 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
93668933
9367 // We could be in a generic function instantiation, or we could be evaluating a generic8934 // We could be in a generic function instantiation, or we could be evaluating a generic
...@@ -9370,15 +8937,11 @@ fn zirParam(...@@ -9370,15 +8937,11 @@ fn zirParam(
9370 const err = err: {8937 const err = err: {
9371 // Make sure any nested param instructions don't clobber our work.8938 // Make sure any nested param instructions don't clobber our work.
9372 const prev_params = block.params;8939 const prev_params = block.params;
9373 const prev_preallocated_new_func = sema.preallocated_new_func;
9374 const prev_no_partial_func_type = sema.no_partial_func_ty;8940 const prev_no_partial_func_type = sema.no_partial_func_ty;
9375 block.params = .{};8941 block.params = .{};
9376 sema.preallocated_new_func = .none;
9377 sema.no_partial_func_ty = true;8942 sema.no_partial_func_ty = true;
9378 defer {8943 defer {
9379 block.params.deinit(sema.gpa);
9380 block.params = prev_params;8944 block.params = prev_params;
9381 sema.preallocated_new_func = prev_preallocated_new_func;
9382 sema.no_partial_func_ty = prev_no_partial_func_type;8945 sema.no_partial_func_ty = prev_no_partial_func_type;
9383 }8946 }
93848947
...@@ -9390,7 +8953,7 @@ fn zirParam(...@@ -9390,7 +8953,7 @@ fn zirParam(
9390 };8953 };
9391 switch (err) {8954 switch (err) {
9392 error.GenericPoison => {8955 error.GenericPoison => {
9393 if (sema.inst_map.get(inst)) |_| {8956 if (sema.inst_map.contains(inst)) {
9394 // A generic function is about to evaluate to another generic function.8957 // A generic function is about to evaluate to another generic function.
9395 // Return an error instead.8958 // Return an error instead.
9396 return error.GenericPoison;8959 return error.GenericPoison;
...@@ -9398,8 +8961,8 @@ fn zirParam(...@@ -9398,8 +8961,8 @@ fn zirParam(
9398 // The type is not available until the generic instantiation.8961 // The type is not available until the generic instantiation.
9399 // We result the param instruction with a poison value and8962 // We result the param instruction with a poison value and
9400 // insert an anytype parameter.8963 // insert an anytype parameter.
9401 try block.params.append(sema.gpa, .{8964 try block.params.append(sema.arena, .{
9402 .ty = Type.generic_poison,8965 .ty = .generic_poison_type,
9403 .is_comptime = comptime_syntax,8966 .is_comptime = comptime_syntax,
9404 .name = param_name,8967 .name = param_name,
9405 });8968 });
...@@ -9409,9 +8972,10 @@ fn zirParam(...@@ -9409,9 +8972,10 @@ fn zirParam(
9409 else => |e| return e,8972 else => |e| return e,
9410 }8973 }
9411 };8974 };
8975
9412 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {8976 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {
9413 error.GenericPoison => {8977 error.GenericPoison => {
9414 if (sema.inst_map.get(inst)) |_| {8978 if (sema.inst_map.contains(inst)) {
9415 // A generic function is about to evaluate to another generic function.8979 // A generic function is about to evaluate to another generic function.
9416 // Return an error instead.8980 // Return an error instead.
9417 return error.GenericPoison;8981 return error.GenericPoison;
...@@ -9419,8 +8983,8 @@ fn zirParam(...@@ -9419,8 +8983,8 @@ fn zirParam(
9419 // The type is not available until the generic instantiation.8983 // The type is not available until the generic instantiation.
9420 // We result the param instruction with a poison value and8984 // We result the param instruction with a poison value and
9421 // insert an anytype parameter.8985 // insert an anytype parameter.
9422 try block.params.append(sema.gpa, .{8986 try block.params.append(sema.arena, .{
9423 .ty = Type.generic_poison,8987 .ty = .generic_poison_type,
9424 .is_comptime = comptime_syntax,8988 .is_comptime = comptime_syntax,
9425 .name = param_name,8989 .name = param_name,
9426 });8990 });
...@@ -9429,8 +8993,9 @@ fn zirParam(...@@ -9429,8 +8993,9 @@ fn zirParam(
9429 },8993 },
9430 else => |e| return e,8994 else => |e| return e,
9431 } or comptime_syntax;8995 } or comptime_syntax;
8996
9432 if (sema.inst_map.get(inst)) |arg| {8997 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) {
9434 // We have a comptime value for this parameter so it should be elided from the8999 // We have a comptime value for this parameter so it should be elided from the
9435 // function type of the function instruction in this block.9000 // function type of the function instruction in this block.
9436 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {9001 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
...@@ -9440,12 +9005,13 @@ fn zirParam(...@@ -9440,12 +9005,13 @@ fn zirParam(
9440 // have the callee source location return `GenericPoison`9005 // have the callee source location return `GenericPoison`
9441 // so that the instantiation is failed and the coercion9006 // so that the instantiation is failed and the coercion
9442 // is handled by comptime call logic instead.9007 // is handled by comptime call logic instead.
9443 assert(sema.is_generic_instantiation);9008 assert(sema.generic_owner != .none);
9444 return error.GenericPoison;9009 return error.GenericPoison;
9445 },9010 },
9446 else => return err,9011 else => |e| return e,
9447 };9012 };
9448 sema.inst_map.putAssumeCapacity(inst, coerced_arg);9013 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();
9449 return;9015 return;
9450 }9016 }
9451 // Even though a comptime argument is provided, the generic function wants to treat9017 // Even though a comptime argument is provided, the generic function wants to treat
...@@ -9453,19 +9019,19 @@ fn zirParam(...@@ -9453,19 +9019,19 @@ fn zirParam(
9453 assert(sema.inst_map.remove(inst));9019 assert(sema.inst_map.remove(inst));
9454 }9020 }
94559021
9456 if (sema.preallocated_new_func != .none) {9022 if (sema.generic_owner != .none) {
9457 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {9023 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
9458 // In this case we are instantiating a generic function call with a non-comptime9024 // In this case we are instantiating a generic function call with a non-comptime
9459 // non-anytype parameter that ended up being a one-possible-type.9025 // non-anytype parameter that ended up being a one-possible-type.
9460 // We don't want the parameter to be part of the instantiated function type.9026 // We don't want the parameter to be part of the instantiated function type.
9461 const result = try sema.addConstant(opv);9027 sema.inst_map.putAssumeCapacity(inst, Air.internedToRef(opv.toIntern()));
9462 sema.inst_map.putAssumeCapacity(inst, result);9028 sema.comptime_args[param_index] = opv.toIntern();
9463 return;9029 return;
9464 }9030 }
9465 }9031 }
94669032
9467 try block.params.append(sema.gpa, .{9033 try block.params.append(sema.arena, .{
9468 .ty = param_ty,9034 .ty = param_ty.toIntern(),
9469 .is_comptime = comptime_syntax,9035 .is_comptime = comptime_syntax,
9470 .name = param_name,9036 .name = param_name,
9471 });9037 });
...@@ -9473,17 +9039,15 @@ fn zirParam(...@@ -9473,17 +9039,15 @@ fn zirParam(
9473 if (is_comptime) {9039 if (is_comptime) {
9474 // If this is a comptime parameter we can add a constant generic_poison9040 // If this is a comptime parameter we can add a constant generic_poison
9475 // since this is also a generic parameter.9041 // since this is also a generic parameter.
9476 const result = try sema.addConstant(Value.generic_poison);9042 sema.inst_map.putAssumeCapacityNoClobber(inst, .generic_poison);
9477 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
9478 } else {9043 } else {
9479 // Otherwise we need a dummy runtime instruction.9044 // 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);
9481 try sema.air_instructions.append(sema.gpa, .{9046 try sema.air_instructions.append(sema.gpa, .{
9482 .tag = .alloc,9047 .tag = .alloc,
9483 .data = .{ .ty = param_ty },9048 .data = .{ .ty = param_ty },
9484 });9049 });
9485 const result = Air.indexToRef(result_index);9050 sema.inst_map.putAssumeCapacityNoClobber(inst, Air.indexToRef(result_index));
9486 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
9487 }9051 }
9488}9052}
94899053
...@@ -9491,24 +9055,34 @@ fn zirParamAnytype(...@@ -9491,24 +9055,34 @@ fn zirParamAnytype(
9491 sema: *Sema,9055 sema: *Sema,
9492 block: *Block,9056 block: *Block,
9493 inst: Zir.Inst.Index,9057 inst: Zir.Inst.Index,
9058 param_index: u32,
9494 comptime_syntax: bool,9059 comptime_syntax: bool,
9495) CompileError!void {9060) CompileError!void {
9496 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;9061 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
9499 if (sema.inst_map.get(inst)) |air_ref| {9065 if (sema.inst_map.get(inst)) |air_ref| {
9500 const param_ty = sema.typeOf(air_ref);9066 const param_ty = sema.typeOf(air_ref);
9501 if (comptime_syntax or try sema.typeRequiresComptime(param_ty)) {9067 // If we have a comptime value for this parameter, it should be elided
9502 // We have a comptime value for this parameter so it should be elided from the9068 // from the function type of the function instruction in this block.
9503 // 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();
9504 return;9071 return;
9505 }9072 }
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();
9507 return;9075 return;
9508 }9076 }
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.
9509 // The map is already populated but we do need to add a runtime parameter.9083 // The map is already populated but we do need to add a runtime parameter.
9510 try block.params.append(sema.gpa, .{9084 try block.params.append(sema.arena, .{
9511 .ty = param_ty,9085 .ty = param_ty.toIntern(),
9512 .is_comptime = false,9086 .is_comptime = false,
9513 .name = param_name,9087 .name = param_name,
9514 });9088 });
...@@ -9517,8 +9091,8 @@ fn zirParamAnytype(...@@ -9517,8 +9091,8 @@ fn zirParamAnytype(
95179091
9518 // We are evaluating a generic function without any comptime args provided.9092 // We are evaluating a generic function without any comptime args provided.
95199093
9520 try block.params.append(sema.gpa, .{9094 try block.params.append(sema.arena, .{
9521 .ty = Type.generic_poison,9095 .ty = .generic_poison_type,
9522 .is_comptime = comptime_syntax,9096 .is_comptime = comptime_syntax,
9523 .name = param_name,9097 .name = param_name,
9524 });9098 });
...@@ -10673,7 +10247,7 @@ const SwitchProngAnalysis = struct {...@@ -10673,7 +10247,7 @@ const SwitchProngAnalysis = struct {
10673 return sema.bitCast(block, item_ty, spa.operand, operand_src, null);10247 return sema.bitCast(block, item_ty, spa.operand, operand_src, null);
10674 }10248 }
1067510249
10676 var names: Module.Fn.InferredErrorSet.NameMap = .{};10250 var names: Module.InferredErrorSet.NameMap = .{};
10677 try names.ensureUnusedCapacity(sema.arena, case_vals.len);10251 try names.ensureUnusedCapacity(sema.arena, case_vals.len);
10678 for (case_vals) |err| {10252 for (case_vals) |err| {
10679 const err_val = sema.resolveConstValue(block, .unneeded, err, "") catch unreachable;10253 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...@@ -11122,7 +10696,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index, operand_is_r
11122 }10696 }
1112310697
11124 const error_names = operand_ty.errorSetNames(mod);10698 const error_names = operand_ty.errorSetNames(mod);
11125 var names: Module.Fn.InferredErrorSet.NameMap = .{};10699 var names: Module.InferredErrorSet.NameMap = .{};
11126 try names.ensureUnusedCapacity(sema.arena, error_names.len);10700 try names.ensureUnusedCapacity(sema.arena, error_names.len);
11127 for (error_names) |error_name| {10701 for (error_names) |error_name| {
11128 if (seen_errors.contains(error_name)) continue;10702 if (seen_errors.contains(error_name)) continue;
...@@ -16295,6 +15869,7 @@ fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -16295,6 +15869,7 @@ fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
1629515869
16296fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {15870fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
16297 const mod = sema.mod;15871 const mod = sema.mod;
15872 const ip = &mod.intern_pool;
16298 const inst_data = sema.code.instructions.items(.data)[inst].inst_node;15873 const inst_data = sema.code.instructions.items(.data)[inst].inst_node;
16299 var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?;15874 var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?;
16300 // Note: The target closure must be in this scope list.15875 // 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!...@@ -16305,8 +15880,8 @@ fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1630515880
16306 // Fail this decl if a scope it depended on failed.15881 // Fail this decl if a scope it depended on failed.
16307 if (scope.failed()) {15882 if (scope.failed()) {
16308 if (sema.owner_func) |owner_func| {15883 if (sema.owner_func_index != .none) {
16309 owner_func.state = .dependency_failure;15884 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
16310 } else {15885 } else {
16311 sema.owner_decl.analysis = .dependency_failure;15886 sema.owner_decl.analysis = .dependency_failure;
16312 }15887 }
...@@ -16423,8 +15998,8 @@ fn zirBuiltinSrc(...@@ -16423,8 +15998,8 @@ fn zirBuiltinSrc(
16423 const mod = sema.mod;15998 const mod = sema.mod;
16424 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;15999 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;
16425 const src = LazySrcLoc.nodeOffset(extra.node);16000 const src = LazySrcLoc.nodeOffset(extra.node);
16426 const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{});16001 if (sema.func_index == .none) return sema.fail(block, src, "@src outside function", .{});
16427 const fn_owner_decl = mod.declPtr(func.owner_decl);16002 const fn_owner_decl = mod.funcOwnerDeclPtr(sema.func_index);
1642816003
16429 const func_name_val = blk: {16004 const func_name_val = blk: {
16430 var anon_decl = try block.startAnonDecl();16005 var anon_decl = try block.startAnonDecl();
...@@ -16548,10 +16123,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16548,10 +16123,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16548 const param_info_decl = mod.declPtr(param_info_decl_index);16123 const param_info_decl = mod.declPtr(param_info_decl_index);
16549 const param_info_ty = param_info_decl.val.toType();16124 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);
16552 for (param_vals, 0..) |*param_val, i| {16128 for (param_vals, 0..) |*param_val, i| {
16553 const info = mod.typeToFunc(ty).?;16129 const param_ty = func_ty_info.param_types.get(ip)[i];
16554 const param_ty = info.param_types[i];
16555 const is_generic = param_ty == .generic_poison_type;16130 const is_generic = param_ty == .generic_poison_type;
16556 const param_ty_val = try ip.get(gpa, .{ .opt = .{16131 const param_ty_val = try ip.get(gpa, .{ .opt = .{
16557 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),16132 .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...@@ -16560,7 +16135,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1656016135
16561 const is_noalias = blk: {16136 const is_noalias = blk: {
16562 const index = std.math.cast(u5, i) orelse break :blk false;16137 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;
16564 };16139 };
1656516140
16566 const param_fields = .{16141 const param_fields = .{
...@@ -16603,23 +16178,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16603,23 +16178,25 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16603 } });16178 } });
16604 };16179 };
1660516180
16606 const info = mod.typeToFunc(ty).?;
16607 const ret_ty_opt = try mod.intern(.{ .opt = .{16181 const ret_ty_opt = try mod.intern(.{ .opt = .{
16608 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),16182 .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,
16610 } });16187 } });
1661116188
16612 const callconv_ty = try sema.getBuiltinType("CallingConvention");16189 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1661316190
16614 const field_values = .{16191 const field_values = .{
16615 // calling_convention: CallingConvention,16192 // 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(),
16617 // alignment: comptime_int,16194 // alignment: comptime_int,
16618 (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).toIntern(),16195 (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).toIntern(),
16619 // is_generic: bool,16196 // is_generic: bool,
16620 Value.makeBool(info.is_generic).toIntern(),16197 Value.makeBool(func_ty_info.is_generic).toIntern(),
16621 // is_var_args: bool,16198 // is_var_args: bool,
16622 Value.makeBool(info.is_var_args).toIntern(),16199 Value.makeBool(func_ty_info.is_var_args).toIntern(),
16623 // return_type: ?type,16200 // return_type: ?type,
16624 ret_ty_opt,16201 ret_ty_opt,
16625 // args: []const Fn.Param,16202 // args: []const Fn.Param,
...@@ -18425,9 +18002,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)...@@ -18425,9 +18002,12 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
18425 // This is only relevant at runtime.18002 // This is only relevant at runtime.
18426 if (start_block.is_comptime or start_block.is_typeof) return;18003 if (start_block.is_comptime or start_block.is_typeof) return;
1842718004
18428 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;18005 const mod = sema.mod;
18429 if (!sema.owner_func.?.calls_or_awaits_errorable_fn) return;18006 const ip = &mod.intern_pool;
18430 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;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
18432 const tracy = trace(@src());18012 const tracy = trace(@src());
18433 defer tracy.end();18013 defer tracy.end();
...@@ -19461,13 +19041,14 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -19461,13 +19041,14 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
1946119041
19462fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {19042fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
19463 const mod = sema.mod;19043 const mod = sema.mod;
19044 const ip = &mod.intern_pool;
19464 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");19045 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
19465 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);19046 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
19466 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);19047 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
19467 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());19048 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
1946819049
19469 if (sema.owner_func != null and19050 if (sema.owner_func_index != .none and
19470 sema.owner_func.?.calls_or_awaits_errorable_fn and19051 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn and
19471 mod.comp.bin_file.options.error_return_tracing and19052 mod.comp.bin_file.options.error_return_tracing and
19472 mod.backendSupportsFeature(.error_return_trace))19053 mod.backendSupportsFeature(.error_return_trace))
19473 {19054 {
...@@ -19920,7 +19501,7 @@ fn zirReify(...@@ -19920,7 +19501,7 @@ fn zirReify(
19920 return sema.addType(Type.anyerror);19501 return sema.addType(Type.anyerror);
1992119502
19922 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));19503 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));
19923 var names: Module.Fn.InferredErrorSet.NameMap = .{};19504 var names: Module.InferredErrorSet.NameMap = .{};
19924 try names.ensureUnusedCapacity(sema.arena, len);19505 try names.ensureUnusedCapacity(sema.arena, len);
19925 for (0..len) |i| {19506 for (0..len) |i| {
19926 const elem_val = try payload_val.elemValue(mod, i);19507 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...@@ -23917,7 +23498,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
23917 break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);23498 break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);
23918 } else target_util.defaultAddressSpace(target, .function);23499 } 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: {
23921 const body_len = sema.code.extra[extra_index];23502 const body_len = sema.code.extra[extra_index];
23922 extra_index += 1;23503 extra_index += 1;
23923 const body = sema.code.extra[extra_index..][0..body_len];23504 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...@@ -23926,20 +23507,20 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
23926 const ty = Type.slice_const_u8;23507 const ty = Type.slice_const_u8;
23927 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");23508 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");
23928 if (val.isGenericPoison()) {23509 if (val.isGenericPoison()) {
23929 break :blk FuncLinkSection{ .generic = {} };23510 break :blk .generic;
23930 }23511 }
23931 break :blk FuncLinkSection{ .explicit = try val.toIpString(ty, mod) };23512 break :blk .{ .explicit = try val.toIpString(ty, mod) };
23932 } else if (extra.data.bits.has_section_ref) blk: {23513 } else if (extra.data.bits.has_section_ref) blk: {
23933 const section_ref = @as(Zir.Inst.Ref, @enumFromInt(sema.code.extra[extra_index]));23514 const section_ref = @as(Zir.Inst.Ref, @enumFromInt(sema.code.extra[extra_index]));
23934 extra_index += 1;23515 extra_index += 1;
23935 const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) {23516 const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) {
23936 error.GenericPoison => {23517 error.GenericPoison => {
23937 break :blk FuncLinkSection{ .generic = {} };23518 break :blk .generic;
23938 },23519 },
23939 else => |e| return e,23520 else => |e| return e,
23940 };23521 };
23941 break :blk FuncLinkSection{ .explicit = section_name };23522 break :blk .{ .explicit = section_name };
23942 } else FuncLinkSection{ .default = {} };23523 } else .default;
2394323524
23944 const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {23525 const cc: ?std.builtin.CallingConvention = if (extra.data.bits.has_cc_body) blk: {
23945 const body_len = sema.code.extra[extra_index];23526 const body_len = sema.code.extra[extra_index];
...@@ -24013,7 +23594,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -24013,7 +23594,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
24013 inst,23594 inst,
24014 @"align",23595 @"align",
24015 @"addrspace",23596 @"addrspace",
24016 @"linksection",23597 section,
24017 cc,23598 cc,
24018 ret_ty,23599 ret_ty,
24019 is_var_args,23600 is_var_args,
...@@ -24846,9 +24427,9 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {...@@ -24846,9 +24427,9 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {
24846 const tv = try mod.declPtr(decl_index).typedValue();24427 const tv = try mod.declPtr(decl_index).typedValue();
24847 assert(tv.ty.zigTypeTag(mod) == .Fn);24428 assert(tv.ty.zigTypeTag(mod) == .Fn);
24848 assert(try sema.fnHasRuntimeBits(tv.ty));24429 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();
24850 try mod.ensureFuncBodyAnalysisQueued(func_index);24431 try mod.ensureFuncBodyAnalysisQueued(func_index);
24851 mod.panic_func_index = func_index.toOptional();24432 mod.panic_func_index = func_index;
24852 }24433 }
2485324434
24854 if (mod.null_stack_trace == .none) {24435 if (mod.null_stack_trace == .none) {
...@@ -24982,7 +24563,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, msg_inst: Air.Inst.Ref) !void {...@@ -24982,7 +24563,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, msg_inst: Air.Inst.Ref) !void {
2498224563
24983 try sema.prepareSimplePanic(block);24564 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);
24986 const panic_fn = try sema.analyzeDeclVal(block, .unneeded, panic_func.owner_decl);24567 const panic_fn = try sema.analyzeDeclVal(block, .unneeded, panic_func.owner_decl);
24987 const null_stack_trace = try sema.addConstant(mod.null_stack_trace.toValue());24568 const null_stack_trace = try sema.addConstant(mod.null_stack_trace.toValue());
2498824569
...@@ -25688,7 +25269,7 @@ fn fieldCallBind(...@@ -25688,7 +25269,7 @@ fn fieldCallBind(
25688 if (mod.typeToFunc(decl_type)) |func_type| f: {25269 if (mod.typeToFunc(decl_type)) |func_type| f: {
25689 if (func_type.param_types.len == 0) break :f;25270 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();
25692 // zig fmt: off25273 // zig fmt: off
25693 if (first_param_type.isGenericPoison() or (25274 if (first_param_type.isGenericPoison() or (
25694 first_param_type.zigTypeTag(mod) == .Pointer and25275 first_param_type.zigTypeTag(mod) == .Pointer and
...@@ -27526,7 +27107,7 @@ fn coerceExtra(...@@ -27526,7 +27107,7 @@ fn coerceExtra(
27526 errdefer msg.destroy(sema.gpa);27107 errdefer msg.destroy(sema.gpa);
2752727108
27528 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };27109 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);
27530 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});27111 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});
27531 break :msg msg;27112 break :msg msg;
27532 };27113 };
...@@ -27556,9 +27137,11 @@ fn coerceExtra(...@@ -27556,9 +27137,11 @@ fn coerceExtra(
27556 try in_memory_result.report(sema, block, inst_src, msg);27137 try in_memory_result.report(sema, block, inst_src, msg);
2755727138
27558 // Add notes about function return type27139 // 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 {
27560 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };27143 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);
27562 if (inst_ty.isError(mod) and !dest_ty.isError(mod)) {27145 if (inst_ty.isError(mod) and !dest_ty.isError(mod)) {
27563 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});27146 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});
27564 } else {27147 } else {
...@@ -28185,7 +27768,7 @@ fn coerceInMemoryAllowedErrorSets(...@@ -28185,7 +27768,7 @@ fn coerceInMemoryAllowedErrorSets(
28185 },27768 },
28186 }27769 }
2818727770
28188 if (dst_ies.func == sema.owner_func_index.unwrap()) {27771 if (dst_ies.func == sema.owner_func_index) {
28189 // We are trying to coerce an error set to the current function's27772 // We are trying to coerce an error set to the current function's
28190 // inferred error set.27773 // inferred error set.
28191 try dst_ies.addErrorSet(src_ty, ip, gpa);27774 try dst_ies.addErrorSet(src_ty, ip, gpa);
...@@ -28264,11 +27847,12 @@ fn coerceInMemoryAllowedFns(...@@ -28264,11 +27847,12 @@ fn coerceInMemoryAllowedFns(
28264 src_src: LazySrcLoc,27847 src_src: LazySrcLoc,
28265) !InMemoryCoercionResult {27848) !InMemoryCoercionResult {
28266 const mod = sema.mod;27849 const mod = sema.mod;
27850 const ip = &mod.intern_pool;
2826727851
28268 {27852 const dest_info = mod.typeToFunc(dest_ty).?;
28269 const dest_info = mod.typeToFunc(dest_ty).?;27853 const src_info = mod.typeToFunc(src_ty).?;
28270 const src_info = mod.typeToFunc(src_ty).?;
2827127854
27855 {
28272 if (dest_info.is_var_args != src_info.is_var_args) {27856 if (dest_info.is_var_args != src_info.is_var_args) {
28273 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };27857 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
28274 }27858 }
...@@ -28302,9 +27886,6 @@ fn coerceInMemoryAllowedFns(...@@ -28302,9 +27886,6 @@ fn coerceInMemoryAllowedFns(
28302 }27886 }
2830327887
28304 const params_len = params_len: {27888 const params_len = params_len: {
28305 const dest_info = mod.typeToFunc(dest_ty).?;
28306 const src_info = mod.typeToFunc(src_ty).?;
28307
28308 if (dest_info.param_types.len != src_info.param_types.len) {27889 if (dest_info.param_types.len != src_info.param_types.len) {
28309 return InMemoryCoercionResult{ .fn_param_count = .{27890 return InMemoryCoercionResult{ .fn_param_count = .{
28310 .actual = src_info.param_types.len,27891 .actual = src_info.param_types.len,
...@@ -28323,13 +27904,10 @@ fn coerceInMemoryAllowedFns(...@@ -28323,13 +27904,10 @@ fn coerceInMemoryAllowedFns(
28323 };27904 };
2832427905
28325 for (0..params_len) |param_i| {27906 for (0..params_len) |param_i| {
28326 const dest_info = mod.typeToFunc(dest_ty).?;27907 const dest_param_ty = dest_info.param_types.get(ip)[param_i].toType();
28327 const src_info = mod.typeToFunc(src_ty).?;27908 const src_param_ty = src_info.param_types.get(ip)[param_i].toType();
28328
28329 const dest_param_ty = dest_info.param_types[param_i].toType();
28330 const src_param_ty = src_info.param_types[param_i].toType();
2833127909
28332 const param_i_small = @as(u5, @intCast(param_i));27910 const param_i_small: u5 = @intCast(param_i);
28333 if (dest_info.paramIsComptime(param_i_small) != src_info.paramIsComptime(param_i_small)) {27911 if (dest_info.paramIsComptime(param_i_small) != src_info.paramIsComptime(param_i_small)) {
28334 return InMemoryCoercionResult{ .fn_param_comptime = .{27912 return InMemoryCoercionResult{ .fn_param_comptime = .{
28335 .index = param_i,27913 .index = param_i,
...@@ -30471,6 +30049,7 @@ fn addReferencedBy(...@@ -30471,6 +30049,7 @@ fn addReferencedBy(
3047130049
30472fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {30050fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
30473 const mod = sema.mod;30051 const mod = sema.mod;
30052 const ip = &mod.intern_pool;
30474 const decl = mod.declPtr(decl_index);30053 const decl = mod.declPtr(decl_index);
30475 if (decl.analysis == .in_progress) {30054 if (decl.analysis == .in_progress) {
30476 const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(mod), "dependency loop detected", .{});30055 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 {...@@ -30478,8 +30057,8 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
30478 }30057 }
3047930058
30480 mod.ensureDeclAnalyzed(decl_index) catch |err| {30059 mod.ensureDeclAnalyzed(decl_index) catch |err| {
30481 if (sema.owner_func) |owner_func| {30060 if (sema.owner_func_index != .none) {
30482 owner_func.state = .dependency_failure;30061 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
30483 } else {30062 } else {
30484 sema.owner_decl.analysis = .dependency_failure;30063 sema.owner_decl.analysis = .dependency_failure;
30485 }30064 }
...@@ -30487,10 +30066,12 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {...@@ -30487,10 +30066,12 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
30487 };30066 };
30488}30067}
3048930068
30490fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void {30069fn ensureFuncBodyAnalyzed(sema: *Sema, func: InternPool.Index) CompileError!void {
30491 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {30070 const mod = sema.mod;
30492 if (sema.owner_func) |owner_func| {30071 const ip = &mod.intern_pool;
30493 owner_func.state = .dependency_failure;30072 mod.ensureFuncBodyAnalyzed(func) catch |err| {
30073 if (sema.owner_func_index != .none) {
30074 ip.funcAnalysis(sema.owner_func_index).state = .dependency_failure;
30494 } else {30075 } else {
30495 sema.owner_decl.analysis = .dependency_failure;30076 sema.owner_decl.analysis = .dependency_failure;
30496 }30077 }
...@@ -30566,7 +30147,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {...@@ -30566,7 +30147,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {
30566 const tv = try decl.typedValue();30147 const tv = try decl.typedValue();
30567 if (tv.ty.zigTypeTag(mod) != .Fn) return;30148 if (tv.ty.zigTypeTag(mod) != .Fn) return;
30568 if (!try sema.fnHasRuntimeBits(tv.ty)) return;30149 if (!try sema.fnHasRuntimeBits(tv.ty)) return;
30569 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn30150 const func_index = tv.val.toIntern();
30151 if (!mod.intern_pool.isFuncBody(func_index)) return; // undef or extern function
30570 try mod.ensureFuncBodyAnalysisQueued(func_index);30152 try mod.ensureFuncBodyAnalysisQueued(func_index);
30571}30153}
3057230154
...@@ -30582,7 +30164,7 @@ fn analyzeRef(...@@ -30582,7 +30164,7 @@ fn analyzeRef(
30582 if (try sema.resolveMaybeUndefVal(operand)) |val| {30164 if (try sema.resolveMaybeUndefVal(operand)) |val| {
30583 switch (mod.intern_pool.indexToKey(val.toIntern())) {30165 switch (mod.intern_pool.indexToKey(val.toIntern())) {
30584 .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),30166 .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),
30586 else => {},30168 else => {},
30587 }30169 }
30588 var anon_decl = try block.startAnonDecl();30170 var anon_decl = try block.startAnonDecl();
...@@ -30810,7 +30392,7 @@ fn analyzeIsNonErrComptimeOnly(...@@ -30810,7 +30392,7 @@ fn analyzeIsNonErrComptimeOnly(
3081030392
30811 if (other_ies.errors.count() != 0) break :blk;30393 if (other_ies.errors.count() != 0) break :blk;
30812 }30394 }
30813 if (ies.func == sema.owner_func_index.unwrap()) {30395 if (ies.func == sema.owner_func_index) {
30814 // We're checking the inferred errorset of the current function and none of30396 // We're checking the inferred errorset of the current function and none of
30815 // its child inferred error sets contained any errors meaning that any value30397 // its child inferred error sets contained any errors meaning that any value
30816 // so far with this type can't contain errors either.30398 // so far with this type can't contain errors either.
...@@ -33275,15 +32857,17 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike {...@@ -33275,15 +32857,17 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike {
3327532857
33276pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {32858pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
33277 const mod = sema.mod;32859 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)) {
33281 // Ensure the type exists so that backends can assume that.32865 // Ensure the type exists so that backends can assume that.
33282 _ = try sema.getBuiltinType("StackTrace");32866 _ = try sema.getBuiltinType("StackTrace");
33283 }32867 }
3328432868
33285 for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| {32869 for (0..fn_ty_info.param_types.len) |i| {
33286 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType());32870 try sema.resolveTypeFully(fn_ty_info.param_types.get(ip)[i].toType());
33287 }32871 }
33288}32872}
3328932873
...@@ -33448,7 +33032,9 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -33448,7 +33032,9 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
33448 // the function is instantiated.33032 // the function is instantiated.
33449 return;33033 return;
33450 }33034 }
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];
33452 try sema.resolveTypeLayout(param_ty.toType());33038 try sema.resolveTypeLayout(param_ty.toType());
33453 }33039 }
33454 try sema.resolveTypeLayout(info.return_type.toType());33040 try sema.resolveTypeLayout(info.return_type.toType());
...@@ -33578,10 +33164,8 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -33578,10 +33164,8 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
33578 .code = zir,33164 .code = zir,
33579 .owner_decl = decl,33165 .owner_decl = decl,
33580 .owner_decl_index = decl_index,33166 .owner_decl_index = decl_index,
33581 .func = null,
33582 .func_index = .none,33167 .func_index = .none,
33583 .fn_ret_ty = Type.void,33168 .fn_ret_ty = Type.void,
33584 .owner_func = null,
33585 .owner_func_index = .none,33169 .owner_func_index = .none,
33586 .comptime_mutable_decls = &comptime_mutable_decls,33170 .comptime_mutable_decls = &comptime_mutable_decls,
33587 };33171 };
...@@ -33600,10 +33184,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -33600,10 +33184,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
33600 .inlining = null,33184 .inlining = null,
33601 .is_comptime = true,33185 .is_comptime = true,
33602 };33186 };
33603 defer {33187 defer assert(block.instructions.items.len == 0);
33604 assert(block.instructions.items.len == 0);
33605 block.params.deinit(gpa);
33606 }
3360733188
33608 const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 };33189 const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 };
33609 const backing_int_ty = blk: {33190 const backing_int_ty = blk: {
...@@ -33633,10 +33214,8 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -33633,10 +33214,8 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
33633 .code = zir,33214 .code = zir,
33634 .owner_decl = decl,33215 .owner_decl = decl,
33635 .owner_decl_index = decl_index,33216 .owner_decl_index = decl_index,
33636 .func = null,
33637 .func_index = .none,33217 .func_index = .none,
33638 .fn_ret_ty = Type.void,33218 .fn_ret_ty = Type.void,
33639 .owner_func = null,
33640 .owner_func_index = .none,33219 .owner_func_index = .none,
33641 .comptime_mutable_decls = undefined,33220 .comptime_mutable_decls = undefined,
33642 };33221 };
...@@ -33943,7 +33522,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {...@@ -33943,7 +33522,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
33943 // the function is instantiated.33522 // the function is instantiated.
33944 return;33523 return;
33945 }33524 }
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];
33947 try sema.resolveTypeFully(param_ty.toType());33528 try sema.resolveTypeFully(param_ty.toType());
33948 }33529 }
33949 try sema.resolveTypeFully(info.return_type.toType());33530 try sema.resolveTypeFully(info.return_type.toType());
...@@ -34213,15 +33794,16 @@ fn resolveInferredErrorSet(...@@ -34213,15 +33794,16 @@ fn resolveInferredErrorSet(
34213 sema: *Sema,33794 sema: *Sema,
34214 block: *Block,33795 block: *Block,
34215 src: LazySrcLoc,33796 src: LazySrcLoc,
34216 ies_index: Module.Fn.InferredErrorSet.Index,33797 ies_index: Module.InferredErrorSet.Index,
34217) CompileError!void {33798) CompileError!void {
34218 const mod = sema.mod;33799 const mod = sema.mod;
33800 const ip = &mod.intern_pool;
34219 const ies = mod.inferredErrorSetPtr(ies_index);33801 const ies = mod.inferredErrorSetPtr(ies_index);
3422033802
34221 if (ies.is_resolved) return;33803 if (ies.is_resolved) return;
3422233804
34223 const func = mod.funcPtr(ies.func);33805 const func = mod.funcInfo(ies.func);
34224 if (func.state == .in_progress) {33806 if (func.analysis(ip).state == .in_progress) {
34225 return sema.fail(block, src, "unable to resolve inferred error set", .{});33807 return sema.fail(block, src, "unable to resolve inferred error set", .{});
34226 }33808 }
3422733809
...@@ -34229,7 +33811,7 @@ fn resolveInferredErrorSet(...@@ -34229,7 +33811,7 @@ fn resolveInferredErrorSet(
34229 // need to ensure the function body is analyzed of the inferred error set.33811 // need to ensure the function body is analyzed of the inferred error set.
34230 // However, in the case of comptime/inline function calls with inferred error sets,33812 // However, in the case of comptime/inline function calls with inferred error sets,
34231 // each call gets a new InferredErrorSet object, which contains the same33813 // 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 set33814 // `InternPool.Index`. Not only is the function not relevant to the inferred error set
34233 // in this case, it may be a generic function which would cause an assertion failure33815 // in this case, it may be a generic function which would cause an assertion failure
34234 // if we called `ensureFuncBodyAnalyzed` on it here.33816 // if we called `ensureFuncBodyAnalyzed` on it here.
34235 const ies_func_owner_decl = mod.declPtr(func.owner_decl);33817 const ies_func_owner_decl = mod.declPtr(func.owner_decl);
...@@ -34346,10 +33928,8 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -34346,10 +33928,8 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
34346 .code = zir,33928 .code = zir,
34347 .owner_decl = decl,33929 .owner_decl = decl,
34348 .owner_decl_index = decl_index,33930 .owner_decl_index = decl_index,
34349 .func = null,
34350 .func_index = .none,33931 .func_index = .none,
34351 .fn_ret_ty = Type.void,33932 .fn_ret_ty = Type.void,
34352 .owner_func = null,
34353 .owner_func_index = .none,33933 .owner_func_index = .none,
34354 .comptime_mutable_decls = &comptime_mutable_decls,33934 .comptime_mutable_decls = &comptime_mutable_decls,
34355 };33935 };
...@@ -34693,10 +34273,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -34693,10 +34273,8 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
34693 .code = zir,34273 .code = zir,
34694 .owner_decl = decl,34274 .owner_decl = decl,
34695 .owner_decl_index = decl_index,34275 .owner_decl_index = decl_index,
34696 .func = null,
34697 .func_index = .none,34276 .func_index = .none,
34698 .fn_ret_ty = Type.void,34277 .fn_ret_ty = Type.void,
34699 .owner_func = null,
34700 .owner_func_index = .none,34278 .owner_func_index = .none,
34701 .comptime_mutable_decls = &comptime_mutable_decls,34279 .comptime_mutable_decls = &comptime_mutable_decls,
34702 };34280 };
...@@ -35148,10 +34726,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {...@@ -35148,10 +34726,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
35148 .inlining = null,34726 .inlining = null,
35149 .is_comptime = true,34727 .is_comptime = true,
35150 };34728 };
35151 defer {34729 defer block.instructions.deinit(gpa);
35152 block.instructions.deinit(gpa);
35153 block.params.deinit(gpa);
35154 }
3515534730
35156 const decl_index = try getBuiltinDecl(sema, &block, name);34731 const decl_index = try getBuiltinDecl(sema, &block, name);
35157 return sema.analyzeDeclVal(&block, src, decl_index);34732 return sema.analyzeDeclVal(&block, src, decl_index);
...@@ -35202,10 +34777,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {...@@ -35202,10 +34777,7 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
35202 .inlining = null,34777 .inlining = null,
35203 .is_comptime = true,34778 .is_comptime = true,
35204 };34779 };
35205 defer {34780 defer block.instructions.deinit(sema.gpa);
35206 block.instructions.deinit(sema.gpa);
35207 block.params.deinit(sema.gpa);
35208 }
35209 const src = LazySrcLoc.nodeOffset(0);34781 const src = LazySrcLoc.nodeOffset(0);
3521034782
35211 const result_ty = sema.analyzeAsType(&block, src, ty_inst) catch |err| switch (err) {34783 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 {...@@ -35327,6 +34899,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35327 .type_opaque,34899 .type_opaque,
35328 .type_function,34900 .type_function,
35329 => null,34901 => null,
34902
35330 .simple_type, // handled above34903 .simple_type, // handled above
35331 // values, not types34904 // values, not types
35332 .undef,34905 .undef,
...@@ -35370,7 +34943,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -35370,7 +34943,8 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35370 .float_comptime_float,34943 .float_comptime_float,
35371 .variable,34944 .variable,
35372 .extern_func,34945 .extern_func,
35373 .func,34946 .func_decl,
34947 .func_instance,
35374 .only_possible_value,34948 .only_possible_value,
35375 .union_value,34949 .union_value,
35376 .bytes,34950 .bytes,
...@@ -35379,6 +34953,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -35379,6 +34953,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35379 // memoized value, not types34953 // memoized value, not types
35380 .memoized_call,34954 .memoized_call,
35381 => unreachable,34955 => unreachable,
34956
35382 .type_array_big,34957 .type_array_big,
35383 .type_array_small,34958 .type_array_small,
35384 .type_vector,34959 .type_vector,
...@@ -36772,7 +36347,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {...@@ -36772,7 +36347,7 @@ fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {
36772 const arena = sema.arena;36347 const arena = sema.arena;
36773 const lhs_names = lhs.errorSetNames(mod);36348 const lhs_names = lhs.errorSetNames(mod);
36774 const rhs_names = rhs.errorSetNames(mod);36349 const rhs_names = rhs.errorSetNames(mod);
36775 var names: Module.Fn.InferredErrorSet.NameMap = .{};36350 var names: Module.InferredErrorSet.NameMap = .{};
36776 try names.ensureUnusedCapacity(arena, lhs_names.len);36351 try names.ensureUnusedCapacity(arena, lhs_names.len);
3677736352
36778 for (lhs_names) |name| {36353 for (lhs_names) |name| {
src/TypedValue.zig+1-1
...@@ -205,7 +205,7 @@ pub fn print(...@@ -205,7 +205,7 @@ pub fn print(
205 mod.declPtr(extern_func.decl).name.fmt(ip),205 mod.declPtr(extern_func.decl).name.fmt(ip),
206 }),206 }),
207 .func => |func| return writer.print("(function '{}')", .{207 .func => |func| return writer.print("(function '{}')", .{
208 mod.declPtr(mod.funcPtr(func.index).owner_decl).name.fmt(ip),208 mod.declPtr(func.owner_decl).name.fmt(ip),
209 }),209 }),
210 .int => |int| switch (int.storage) {210 .int => |int| switch (int.storage) {
211 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),211 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
src/Zir.zig+14-3
...@@ -90,13 +90,24 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en...@@ -90,13 +90,24 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
90 };90 };
91}91}
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
94pub fn nullTerminatedString(code: Zir, index: usize) [:0]const u8 {99pub 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;
96 while (code.string_bytes[end] != 0) {107 while (code.string_bytes[end] != 0) {
97 end += 1;108 end += 1;
98 }109 }
99 return code.string_bytes[index..end :0];110 return code.string_bytes[start..end :0];
100}111}
101112
102pub fn refSlice(code: Zir, start: usize, len: usize) []Inst.Ref {113pub 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;...@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
13const TypedValue = @import("../../TypedValue.zig");13const TypedValue = @import("../../TypedValue.zig");
14const link = @import("../../link.zig");14const link = @import("../../link.zig");
15const Module = @import("../../Module.zig");15const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");
16const Compilation = @import("../../Compilation.zig");17const Compilation = @import("../../Compilation.zig");
17const ErrorMsg = Module.ErrorMsg;18const ErrorMsg = Module.ErrorMsg;
18const Target = std.Target;19const Target = std.Target;
...@@ -49,7 +50,8 @@ liveness: Liveness,...@@ -49,7 +50,8 @@ liveness: Liveness,
49bin_file: *link.File,50bin_file: *link.File,
50debug_output: DebugInfoOutput,51debug_output: DebugInfoOutput,
51target: *const std.Target,52target: *const std.Target,
52mod_fn: *const Module.Fn,53func_index: InternPool.Index,
54owner_decl: Module.Decl.Index,
53err_msg: ?*ErrorMsg,55err_msg: ?*ErrorMsg,
54args: []MCValue,56args: []MCValue,
55ret_mcv: MCValue,57ret_mcv: MCValue,
...@@ -199,7 +201,7 @@ const DbgInfoReloc = struct {...@@ -199,7 +201,7 @@ const DbgInfoReloc = struct {
199 else => unreachable, // not a possible argument201 else => unreachable, // not a possible argument
200202
201 };203 };
202 try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc);204 try dw.genArgDbgInfo(reloc.name, reloc.ty, function.owner_decl, loc);
203 },205 },
204 .plan9 => {},206 .plan9 => {},
205 .none => {},207 .none => {},
...@@ -245,7 +247,7 @@ const DbgInfoReloc = struct {...@@ -245,7 +247,7 @@ const DbgInfoReloc = struct {
245 break :blk .nop;247 break :blk .nop;
246 },248 },
247 };249 };
248 try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc);250 try dw.genVarDbgInfo(reloc.name, reloc.ty, function.owner_decl, is_ptr, loc);
249 },251 },
250 .plan9 => {},252 .plan9 => {},
251 .none => {},253 .none => {},
...@@ -328,7 +330,7 @@ const Self = @This();...@@ -328,7 +330,7 @@ const Self = @This();
328pub fn generate(330pub fn generate(
329 bin_file: *link.File,331 bin_file: *link.File,
330 src_loc: Module.SrcLoc,332 src_loc: Module.SrcLoc,
331 module_fn_index: Module.Fn.Index,333 func_index: InternPool.Index,
332 air: Air,334 air: Air,
333 liveness: Liveness,335 liveness: Liveness,
334 code: *std.ArrayList(u8),336 code: *std.ArrayList(u8),
...@@ -339,8 +341,8 @@ pub fn generate(...@@ -339,8 +341,8 @@ pub fn generate(
339 }341 }
340342
341 const mod = bin_file.options.module.?;343 const mod = bin_file.options.module.?;
342 const module_fn = mod.funcPtr(module_fn_index);344 const func = mod.funcInfo(func_index);
343 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);345 const fn_owner_decl = mod.declPtr(func.owner_decl);
344 assert(fn_owner_decl.has_tv);346 assert(fn_owner_decl.has_tv);
345 const fn_type = fn_owner_decl.ty;347 const fn_type = fn_owner_decl.ty;
346348
...@@ -359,7 +361,8 @@ pub fn generate(...@@ -359,7 +361,8 @@ pub fn generate(
359 .debug_output = debug_output,361 .debug_output = debug_output,
360 .target = &bin_file.options.target,362 .target = &bin_file.options.target,
361 .bin_file = bin_file,363 .bin_file = bin_file,
362 .mod_fn = module_fn,364 .func_index = func_index,
365 .owner_decl = func.owner_decl,
363 .err_msg = null,366 .err_msg = null,
364 .args = undefined, // populated after `resolveCallingConventionValues`367 .args = undefined, // populated after `resolveCallingConventionValues`
365 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`368 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
...@@ -368,8 +371,8 @@ pub fn generate(...@@ -368,8 +371,8 @@ pub fn generate(
368 .branch_stack = &branch_stack,371 .branch_stack = &branch_stack,
369 .src_loc = src_loc,372 .src_loc = src_loc,
370 .stack_align = undefined,373 .stack_align = undefined,
371 .end_di_line = module_fn.rbrace_line,374 .end_di_line = func.rbrace_line,
372 .end_di_column = module_fn.rbrace_column,375 .end_di_column = func.rbrace_column,
373 };376 };
374 defer function.stack.deinit(bin_file.allocator);377 defer function.stack.deinit(bin_file.allocator);
375 defer function.blocks.deinit(bin_file.allocator);378 defer function.blocks.deinit(bin_file.allocator);
...@@ -416,8 +419,8 @@ pub fn generate(...@@ -416,8 +419,8 @@ pub fn generate(
416 .src_loc = src_loc,419 .src_loc = src_loc,
417 .code = code,420 .code = code,
418 .prev_di_pc = 0,421 .prev_di_pc = 0,
419 .prev_di_line = module_fn.lbrace_line,422 .prev_di_line = func.lbrace_line,
420 .prev_di_column = module_fn.lbrace_column,423 .prev_di_column = func.lbrace_column,
421 .stack_size = function.max_end_stack,424 .stack_size = function.max_end_stack,
422 .saved_regs_stack_space = function.saved_regs_stack_space,425 .saved_regs_stack_space = function.saved_regs_stack_space,
423 };426 };
...@@ -4011,12 +4014,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -4011,12 +4014,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
4011 const atom_index = switch (self.bin_file.tag) {4014 const atom_index = switch (self.bin_file.tag) {
4012 .macho => blk: {4015 .macho => blk: {
4013 const macho_file = self.bin_file.cast(link.File.MachO).?;4016 const macho_file = self.bin_file.cast(link.File.MachO).?;
4014 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4017 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
4015 break :blk macho_file.getAtom(atom).getSymbolIndex().?;4018 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
4016 },4019 },
4017 .coff => blk: {4020 .coff => blk: {
4018 const coff_file = self.bin_file.cast(link.File.Coff).?;4021 const coff_file = self.bin_file.cast(link.File.Coff).?;
4019 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4022 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
4020 break :blk coff_file.getAtom(atom).getSymbolIndex().?;4023 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
4021 },4024 },
4022 else => unreachable, // unsupported target format4025 else => unreachable, // unsupported target format
...@@ -4190,10 +4193,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -4190,10 +4193,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
4190 while (self.args[arg_index] == .none) arg_index += 1;4193 while (self.args[arg_index] == .none) arg_index += 1;
4191 self.arg_index = arg_index + 1;4194 self.arg_index = arg_index + 1;
41924195
4196 const mod = self.bin_file.options.module.?;
4193 const ty = self.typeOfIndex(inst);4197 const ty = self.typeOfIndex(inst);
4194 const tag = self.air.instructions.items(.tag)[inst];4198 const tag = self.air.instructions.items(.tag)[inst];
4195 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;4199 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4196 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);4200 const name = mod.getParamName(self.func_index, src_index);
41974201
4198 try self.dbg_info_relocs.append(self.gpa, .{4202 try self.dbg_info_relocs.append(self.gpa, .{
4199 .tag = tag,4203 .tag = tag,
...@@ -4348,7 +4352,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4348,7 +4352,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4348 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);4352 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
4349 if (self.bin_file.cast(link.File.MachO)) |macho_file| {4353 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4350 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);4354 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
4351 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);4355 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
4352 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;4356 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
4353 _ = try self.addInst(.{4357 _ = try self.addInst(.{
4354 .tag = .call_extern,4358 .tag = .call_extern,
...@@ -4617,9 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4617,9 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
4617fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {4621fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4618 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;4622 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
4619 const mod = self.bin_file.options.module.?;4623 const mod = self.bin_file.options.module.?;
4620 const function = mod.funcPtr(ty_fn.func);4624 const func = mod.funcInfo(ty_fn.func);
4621 // TODO emit debug info for function change4625 // TODO emit debug info for function change
4622 _ = function;4626 _ = func;
4623 return self.finishAir(inst, .dead, .{ .none, .none, .none });4627 return self.finishAir(inst, .dead, .{ .none, .none, .none });
4624}4628}
46254629
...@@ -5529,12 +5533,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5529,12 +5533,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5529 const atom_index = switch (self.bin_file.tag) {5533 const atom_index = switch (self.bin_file.tag) {
5530 .macho => blk: {5534 .macho => blk: {
5531 const macho_file = self.bin_file.cast(link.File.MachO).?;5535 const macho_file = self.bin_file.cast(link.File.MachO).?;
5532 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5536 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
5533 break :blk macho_file.getAtom(atom).getSymbolIndex().?;5537 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5534 },5538 },
5535 .coff => blk: {5539 .coff => blk: {
5536 const coff_file = self.bin_file.cast(link.File.Coff).?;5540 const coff_file = self.bin_file.cast(link.File.Coff).?;
5537 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5541 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
5538 break :blk coff_file.getAtom(atom).getSymbolIndex().?;5542 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
5539 },5543 },
5540 else => unreachable, // unsupported target format5544 else => unreachable, // unsupported target format
...@@ -5650,12 +5654,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5650,12 +5654,12 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5650 const atom_index = switch (self.bin_file.tag) {5654 const atom_index = switch (self.bin_file.tag) {
5651 .macho => blk: {5655 .macho => blk: {
5652 const macho_file = self.bin_file.cast(link.File.MachO).?;5656 const macho_file = self.bin_file.cast(link.File.MachO).?;
5653 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5657 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
5654 break :blk macho_file.getAtom(atom).getSymbolIndex().?;5658 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5655 },5659 },
5656 .coff => blk: {5660 .coff => blk: {
5657 const coff_file = self.bin_file.cast(link.File.Coff).?;5661 const coff_file = self.bin_file.cast(link.File.Coff).?;
5658 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5662 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
5659 break :blk coff_file.getAtom(atom).getSymbolIndex().?;5663 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
5660 },5664 },
5661 else => unreachable, // unsupported target format5665 else => unreachable, // unsupported target format
...@@ -5847,12 +5851,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5847,12 +5851,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5847 const atom_index = switch (self.bin_file.tag) {5851 const atom_index = switch (self.bin_file.tag) {
5848 .macho => blk: {5852 .macho => blk: {
5849 const macho_file = self.bin_file.cast(link.File.MachO).?;5853 const macho_file = self.bin_file.cast(link.File.MachO).?;
5850 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5854 const atom = try macho_file.getOrCreateAtomForDecl(self.owner_decl);
5851 break :blk macho_file.getAtom(atom).getSymbolIndex().?;5855 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5852 },5856 },
5853 .coff => blk: {5857 .coff => blk: {
5854 const coff_file = self.bin_file.cast(link.File.Coff).?;5858 const coff_file = self.bin_file.cast(link.File.Coff).?;
5855 const atom = try coff_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);5859 const atom = try coff_file.getOrCreateAtomForDecl(self.owner_decl);
5856 break :blk coff_file.getAtom(atom).getSymbolIndex().?;5860 break :blk coff_file.getAtom(atom).getSymbolIndex().?;
5857 },5861 },
5858 else => unreachable, // unsupported target format5862 else => unreachable, // unsupported target format
...@@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {...@@ -6164,7 +6168,7 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6164 self.bin_file,6168 self.bin_file,
6165 self.src_loc,6169 self.src_loc,
6166 arg_tv,6170 arg_tv,
6167 self.mod_fn.owner_decl,6171 self.owner_decl,
6168 )) {6172 )) {
6169 .mcv => |mcv| switch (mcv) {6173 .mcv => |mcv| switch (mcv) {
6170 .none => .none,6174 .none => .none,
...@@ -6198,6 +6202,7 @@ const CallMCValues = struct {...@@ -6198,6 +6202,7 @@ const CallMCValues = struct {
6198/// Caller must call `CallMCValues.deinit`.6202/// Caller must call `CallMCValues.deinit`.
6199fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {6203fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6200 const mod = self.bin_file.options.module.?;6204 const mod = self.bin_file.options.module.?;
6205 const ip = &mod.intern_pool;
6201 const fn_info = mod.typeToFunc(fn_ty).?;6206 const fn_info = mod.typeToFunc(fn_ty).?;
6202 const cc = fn_info.cc;6207 const cc = fn_info.cc;
6203 var result: CallMCValues = .{6208 var result: CallMCValues = .{
...@@ -6240,10 +6245,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6240,10 +6245,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6240 }6245 }
6241 }6246 }
62426247
6243 for (fn_info.param_types, 0..) |ty, i| {6248 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
6244 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));6249 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
6245 if (param_size == 0) {6250 if (param_size == 0) {
6246 result.args[i] = .{ .none = {} };6251 result_arg.* = .{ .none = {} };
6247 continue;6252 continue;
6248 }6253 }
62496254
...@@ -6256,7 +6261,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6256,7 +6261,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62566261
6257 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {6262 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
6258 if (param_size <= 8) {6263 if (param_size <= 8) {
6259 result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };6264 result_arg.* = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };
6260 ncrn += 1;6265 ncrn += 1;
6261 } else {6266 } else {
6262 return self.fail("TODO MCValues with multiple registers", .{});6267 return self.fail("TODO MCValues with multiple registers", .{});
...@@ -6273,7 +6278,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6273,7 +6278,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6273 }6278 }
6274 }6279 }
62756280
6276 result.args[i] = .{ .stack_argument_offset = nsaa };6281 result_arg.* = .{ .stack_argument_offset = nsaa };
6277 nsaa += param_size;6282 nsaa += param_size;
6278 }6283 }
6279 }6284 }
...@@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6305,16 +6310,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
63056310
6306 var stack_offset: u32 = 0;6311 var stack_offset: u32 = 0;
63076312
6308 for (fn_info.param_types, 0..) |ty, i| {6313 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
6309 if (ty.toType().abiSize(mod) > 0) {6314 if (ty.toType().abiSize(mod) > 0) {
6310 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));6315 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
6311 const param_alignment = ty.toType().abiAlignment(mod);6316 const param_alignment = ty.toType().abiAlignment(mod);
63126317
6313 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);6318 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
6314 result.args[i] = .{ .stack_argument_offset = stack_offset };6319 result_arg.* = .{ .stack_argument_offset = stack_offset };
6315 stack_offset += param_size;6320 stack_offset += param_size;
6316 } else {6321 } else {
6317 result.args[i] = .{ .none = {} };6322 result_arg.* = .{ .none = {} };
6318 }6323 }
6319 }6324 }
63206325
src/arch/arm/CodeGen.zig+27-21
...@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;...@@ -13,6 +13,7 @@ const Value = @import("../../value.zig").Value;
13const TypedValue = @import("../../TypedValue.zig");13const TypedValue = @import("../../TypedValue.zig");
14const link = @import("../../link.zig");14const link = @import("../../link.zig");
15const Module = @import("../../Module.zig");15const Module = @import("../../Module.zig");
16const InternPool = @import("../../InternPool.zig");
16const Compilation = @import("../../Compilation.zig");17const Compilation = @import("../../Compilation.zig");
17const ErrorMsg = Module.ErrorMsg;18const ErrorMsg = Module.ErrorMsg;
18const Target = std.Target;19const Target = std.Target;
...@@ -50,7 +51,7 @@ liveness: Liveness,...@@ -50,7 +51,7 @@ liveness: Liveness,
50bin_file: *link.File,51bin_file: *link.File,
51debug_output: DebugInfoOutput,52debug_output: DebugInfoOutput,
52target: *const std.Target,53target: *const std.Target,
53mod_fn: *const Module.Fn,54func_index: InternPool.Index,
54err_msg: ?*ErrorMsg,55err_msg: ?*ErrorMsg,
55args: []MCValue,56args: []MCValue,
56ret_mcv: MCValue,57ret_mcv: MCValue,
...@@ -258,6 +259,7 @@ const DbgInfoReloc = struct {...@@ -258,6 +259,7 @@ const DbgInfoReloc = struct {
258 }259 }
259260
260 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {261 fn genArgDbgInfo(reloc: DbgInfoReloc, function: Self) error{OutOfMemory}!void {
262 const mod = function.bin_file.options.module.?;
261 switch (function.debug_output) {263 switch (function.debug_output) {
262 .dwarf => |dw| {264 .dwarf => |dw| {
263 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {265 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (reloc.mcv) {
...@@ -278,7 +280,7 @@ const DbgInfoReloc = struct {...@@ -278,7 +280,7 @@ const DbgInfoReloc = struct {
278 else => unreachable, // not a possible argument280 else => unreachable, // not a possible argument
279 };281 };
280282
281 try dw.genArgDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, loc);283 try dw.genArgDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), loc);
282 },284 },
283 .plan9 => {},285 .plan9 => {},
284 .none => {},286 .none => {},
...@@ -286,6 +288,7 @@ const DbgInfoReloc = struct {...@@ -286,6 +288,7 @@ const DbgInfoReloc = struct {
286 }288 }
287289
288 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {290 fn genVarDbgInfo(reloc: DbgInfoReloc, function: Self) !void {
291 const mod = function.bin_file.options.module.?;
289 const is_ptr = switch (reloc.tag) {292 const is_ptr = switch (reloc.tag) {
290 .dbg_var_ptr => true,293 .dbg_var_ptr => true,
291 .dbg_var_val => false,294 .dbg_var_val => false,
...@@ -321,7 +324,7 @@ const DbgInfoReloc = struct {...@@ -321,7 +324,7 @@ const DbgInfoReloc = struct {
321 break :blk .nop;324 break :blk .nop;
322 },325 },
323 };326 };
324 try dw.genVarDbgInfo(reloc.name, reloc.ty, function.mod_fn.owner_decl, is_ptr, loc);327 try dw.genVarDbgInfo(reloc.name, reloc.ty, mod.funcOwnerDeclIndex(function.func_index), is_ptr, loc);
325 },328 },
326 .plan9 => {},329 .plan9 => {},
327 .none => {},330 .none => {},
...@@ -334,7 +337,7 @@ const Self = @This();...@@ -334,7 +337,7 @@ const Self = @This();
334pub fn generate(337pub fn generate(
335 bin_file: *link.File,338 bin_file: *link.File,
336 src_loc: Module.SrcLoc,339 src_loc: Module.SrcLoc,
337 module_fn_index: Module.Fn.Index,340 func_index: InternPool.Index,
338 air: Air,341 air: Air,
339 liveness: Liveness,342 liveness: Liveness,
340 code: *std.ArrayList(u8),343 code: *std.ArrayList(u8),
...@@ -345,8 +348,8 @@ pub fn generate(...@@ -345,8 +348,8 @@ pub fn generate(
345 }348 }
346349
347 const mod = bin_file.options.module.?;350 const mod = bin_file.options.module.?;
348 const module_fn = mod.funcPtr(module_fn_index);351 const func = mod.funcInfo(func_index);
349 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);352 const fn_owner_decl = mod.declPtr(func.owner_decl);
350 assert(fn_owner_decl.has_tv);353 assert(fn_owner_decl.has_tv);
351 const fn_type = fn_owner_decl.ty;354 const fn_type = fn_owner_decl.ty;
352355
...@@ -365,7 +368,7 @@ pub fn generate(...@@ -365,7 +368,7 @@ pub fn generate(
365 .target = &bin_file.options.target,368 .target = &bin_file.options.target,
366 .bin_file = bin_file,369 .bin_file = bin_file,
367 .debug_output = debug_output,370 .debug_output = debug_output,
368 .mod_fn = module_fn,371 .func_index = func_index,
369 .err_msg = null,372 .err_msg = null,
370 .args = undefined, // populated after `resolveCallingConventionValues`373 .args = undefined, // populated after `resolveCallingConventionValues`
371 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`374 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
...@@ -374,8 +377,8 @@ pub fn generate(...@@ -374,8 +377,8 @@ pub fn generate(
374 .branch_stack = &branch_stack,377 .branch_stack = &branch_stack,
375 .src_loc = src_loc,378 .src_loc = src_loc,
376 .stack_align = undefined,379 .stack_align = undefined,
377 .end_di_line = module_fn.rbrace_line,380 .end_di_line = func.rbrace_line,
378 .end_di_column = module_fn.rbrace_column,381 .end_di_column = func.rbrace_column,
379 };382 };
380 defer function.stack.deinit(bin_file.allocator);383 defer function.stack.deinit(bin_file.allocator);
381 defer function.blocks.deinit(bin_file.allocator);384 defer function.blocks.deinit(bin_file.allocator);
...@@ -422,8 +425,8 @@ pub fn generate(...@@ -422,8 +425,8 @@ pub fn generate(
422 .src_loc = src_loc,425 .src_loc = src_loc,
423 .code = code,426 .code = code,
424 .prev_di_pc = 0,427 .prev_di_pc = 0,
425 .prev_di_line = module_fn.lbrace_line,428 .prev_di_line = func.lbrace_line,
426 .prev_di_column = module_fn.lbrace_column,429 .prev_di_column = func.lbrace_column,
427 .stack_size = function.max_end_stack,430 .stack_size = function.max_end_stack,
428 .saved_regs_stack_space = function.saved_regs_stack_space,431 .saved_regs_stack_space = function.saved_regs_stack_space,
429 };432 };
...@@ -4163,10 +4166,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -4163,10 +4166,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
4163 while (self.args[arg_index] == .none) arg_index += 1;4166 while (self.args[arg_index] == .none) arg_index += 1;
4164 self.arg_index = arg_index + 1;4167 self.arg_index = arg_index + 1;
41654168
4169 const mod = self.bin_file.options.module.?;
4166 const ty = self.typeOfIndex(inst);4170 const ty = self.typeOfIndex(inst);
4167 const tag = self.air.instructions.items(.tag)[inst];4171 const tag = self.air.instructions.items(.tag)[inst];
4168 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;4172 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
4169 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);4173 const name = mod.getParamName(self.func_index, src_index);
41704174
4171 try self.dbg_info_relocs.append(self.gpa, .{4175 try self.dbg_info_relocs.append(self.gpa, .{
4172 .tag = tag,4176 .tag = tag,
...@@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -4569,9 +4573,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
4569fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {4573fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4570 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;4574 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
4571 const mod = self.bin_file.options.module.?;4575 const mod = self.bin_file.options.module.?;
4572 const function = mod.funcPtr(ty_fn.func);4576 const func = mod.funcInfo(ty_fn.func);
4573 // TODO emit debug info for function change4577 // TODO emit debug info for function change
4574 _ = function;4578 _ = func;
4575 return self.finishAir(inst, .dead, .{ .none, .none, .none });4579 return self.finishAir(inst, .dead, .{ .none, .none, .none });
4576}4580}
45774581
...@@ -6113,11 +6117,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -6113,11 +6117,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
6113}6117}
61146118
6115fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {6119fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
6120 const mod = self.bin_file.options.module.?;
6116 const mcv: MCValue = switch (try codegen.genTypedValue(6121 const mcv: MCValue = switch (try codegen.genTypedValue(
6117 self.bin_file,6122 self.bin_file,
6118 self.src_loc,6123 self.src_loc,
6119 arg_tv,6124 arg_tv,
6120 self.mod_fn.owner_decl,6125 mod.funcOwnerDeclIndex(self.func_index),
6121 )) {6126 )) {
6122 .mcv => |mcv| switch (mcv) {6127 .mcv => |mcv| switch (mcv) {
6123 .none => .none,6128 .none => .none,
...@@ -6149,6 +6154,7 @@ const CallMCValues = struct {...@@ -6149,6 +6154,7 @@ const CallMCValues = struct {
6149/// Caller must call `CallMCValues.deinit`.6154/// Caller must call `CallMCValues.deinit`.
6150fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {6155fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6151 const mod = self.bin_file.options.module.?;6156 const mod = self.bin_file.options.module.?;
6157 const ip = &mod.intern_pool;
6152 const fn_info = mod.typeToFunc(fn_ty).?;6158 const fn_info = mod.typeToFunc(fn_ty).?;
6153 const cc = fn_info.cc;6159 const cc = fn_info.cc;
6154 var result: CallMCValues = .{6160 var result: CallMCValues = .{
...@@ -6194,14 +6200,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6194,14 +6200,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6194 }6200 }
6195 }6201 }
61966202
6197 for (fn_info.param_types, 0..) |ty, i| {6203 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
6198 if (ty.toType().abiAlignment(mod) == 8)6204 if (ty.toType().abiAlignment(mod) == 8)
6199 ncrn = std.mem.alignForward(usize, ncrn, 2);6205 ncrn = std.mem.alignForward(usize, ncrn, 2);
62006206
6201 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));6207 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
6202 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {6208 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
6203 if (param_size <= 4) {6209 if (param_size <= 4) {
6204 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };6210 result_arg.* = .{ .register = c_abi_int_param_regs[ncrn] };
6205 ncrn += 1;6211 ncrn += 1;
6206 } else {6212 } else {
6207 return self.fail("TODO MCValues with multiple registers", .{});6213 return self.fail("TODO MCValues with multiple registers", .{});
...@@ -6213,7 +6219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6213,7 +6219,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6213 if (ty.toType().abiAlignment(mod) == 8)6219 if (ty.toType().abiAlignment(mod) == 8)
6214 nsaa = std.mem.alignForward(u32, nsaa, 8);6220 nsaa = std.mem.alignForward(u32, nsaa, 8);
62156221
6216 result.args[i] = .{ .stack_argument_offset = nsaa };6222 result_arg.* = .{ .stack_argument_offset = nsaa };
6217 nsaa += param_size;6223 nsaa += param_size;
6218 }6224 }
6219 }6225 }
...@@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6244,16 +6250,16 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62446250
6245 var stack_offset: u32 = 0;6251 var stack_offset: u32 = 0;
62466252
6247 for (fn_info.param_types, 0..) |ty, i| {6253 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
6248 if (ty.toType().abiSize(mod) > 0) {6254 if (ty.toType().abiSize(mod) > 0) {
6249 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));6255 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
6250 const param_alignment = ty.toType().abiAlignment(mod);6256 const param_alignment = ty.toType().abiAlignment(mod);
62516257
6252 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);6258 stack_offset = std.mem.alignForward(u32, stack_offset, param_alignment);
6253 result.args[i] = .{ .stack_argument_offset = stack_offset };6259 result_arg.* = .{ .stack_argument_offset = stack_offset };
6254 stack_offset += param_size;6260 stack_offset += param_size;
6255 } else {6261 } else {
6256 result.args[i] = .{ .none = {} };6262 result_arg.* = .{ .none = {} };
6257 }6263 }
6258 }6264 }
62596265
src/arch/riscv64/CodeGen.zig+46-37
...@@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value;...@@ -12,6 +12,7 @@ const Value = @import("../../value.zig").Value;
12const TypedValue = @import("../../TypedValue.zig");12const TypedValue = @import("../../TypedValue.zig");
13const link = @import("../../link.zig");13const link = @import("../../link.zig");
14const Module = @import("../../Module.zig");14const Module = @import("../../Module.zig");
15const InternPool = @import("../../InternPool.zig");
15const Compilation = @import("../../Compilation.zig");16const Compilation = @import("../../Compilation.zig");
16const ErrorMsg = Module.ErrorMsg;17const ErrorMsg = Module.ErrorMsg;
17const Target = std.Target;18const Target = std.Target;
...@@ -43,7 +44,7 @@ air: Air,...@@ -43,7 +44,7 @@ air: Air,
43liveness: Liveness,44liveness: Liveness,
44bin_file: *link.File,45bin_file: *link.File,
45target: *const std.Target,46target: *const std.Target,
46mod_fn: *const Module.Fn,47func_index: InternPool.Index,
47code: *std.ArrayList(u8),48code: *std.ArrayList(u8),
48debug_output: DebugInfoOutput,49debug_output: DebugInfoOutput,
49err_msg: ?*ErrorMsg,50err_msg: ?*ErrorMsg,
...@@ -217,7 +218,7 @@ const Self = @This();...@@ -217,7 +218,7 @@ const Self = @This();
217pub fn generate(218pub fn generate(
218 bin_file: *link.File,219 bin_file: *link.File,
219 src_loc: Module.SrcLoc,220 src_loc: Module.SrcLoc,
220 module_fn_index: Module.Fn.Index,221 func_index: InternPool.Index,
221 air: Air,222 air: Air,
222 liveness: Liveness,223 liveness: Liveness,
223 code: *std.ArrayList(u8),224 code: *std.ArrayList(u8),
...@@ -228,8 +229,8 @@ pub fn generate(...@@ -228,8 +229,8 @@ pub fn generate(
228 }229 }
229230
230 const mod = bin_file.options.module.?;231 const mod = bin_file.options.module.?;
231 const module_fn = mod.funcPtr(module_fn_index);232 const func = mod.funcInfo(func_index);
232 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);233 const fn_owner_decl = mod.declPtr(func.owner_decl);
233 assert(fn_owner_decl.has_tv);234 assert(fn_owner_decl.has_tv);
234 const fn_type = fn_owner_decl.ty;235 const fn_type = fn_owner_decl.ty;
235236
...@@ -247,7 +248,7 @@ pub fn generate(...@@ -247,7 +248,7 @@ pub fn generate(
247 .liveness = liveness,248 .liveness = liveness,
248 .target = &bin_file.options.target,249 .target = &bin_file.options.target,
249 .bin_file = bin_file,250 .bin_file = bin_file,
250 .mod_fn = module_fn,251 .func_index = func_index,
251 .code = code,252 .code = code,
252 .debug_output = debug_output,253 .debug_output = debug_output,
253 .err_msg = null,254 .err_msg = null,
...@@ -258,8 +259,8 @@ pub fn generate(...@@ -258,8 +259,8 @@ pub fn generate(
258 .branch_stack = &branch_stack,259 .branch_stack = &branch_stack,
259 .src_loc = src_loc,260 .src_loc = src_loc,
260 .stack_align = undefined,261 .stack_align = undefined,
261 .end_di_line = module_fn.rbrace_line,262 .end_di_line = func.rbrace_line,
262 .end_di_column = module_fn.rbrace_column,263 .end_di_column = func.rbrace_column,
263 };264 };
264 defer function.stack.deinit(bin_file.allocator);265 defer function.stack.deinit(bin_file.allocator);
265 defer function.blocks.deinit(bin_file.allocator);266 defer function.blocks.deinit(bin_file.allocator);
...@@ -301,8 +302,8 @@ pub fn generate(...@@ -301,8 +302,8 @@ pub fn generate(
301 .src_loc = src_loc,302 .src_loc = src_loc,
302 .code = code,303 .code = code,
303 .prev_di_pc = 0,304 .prev_di_pc = 0,
304 .prev_di_line = module_fn.lbrace_line,305 .prev_di_line = func.lbrace_line,
305 .prev_di_column = module_fn.lbrace_column,306 .prev_di_column = func.lbrace_column,
306 };307 };
307 defer emit.deinit();308 defer emit.deinit();
308309
...@@ -1627,13 +1628,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1627,13 +1628,15 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
1627}1628}
16281629
1629fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {1630fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
1631 const mod = self.bin_file.options.module.?;
1630 const arg = self.air.instructions.items(.data)[inst].arg;1632 const arg = self.air.instructions.items(.data)[inst].arg;
1631 const ty = self.air.getRefType(arg.ty);1633 const ty = self.air.getRefType(arg.ty);
1632 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);1634 const owner_decl = mod.funcOwnerDeclIndex(self.func_index);
1635 const name = mod.getParamName(self.func_index, arg.src_index);
16331636
1634 switch (self.debug_output) {1637 switch (self.debug_output) {
1635 .dwarf => |dw| switch (mcv) {1638 .dwarf => |dw| switch (mcv) {
1636 .register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{1639 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
1637 .register = reg.dwarfLocOp(),1640 .register = reg.dwarfLocOp(),
1638 }),1641 }),
1639 .stack_offset => {},1642 .stack_offset => {},
...@@ -1742,24 +1745,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1742,24 +1745,28 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1742 }1745 }
17431746
1744 if (try self.air.value(callee, mod)) |func_value| {1747 if (try self.air.value(callee, mod)) |func_value| {
1745 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {1748 switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
1746 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);1749 .func => |func| {
1747 const atom = elf_file.getAtom(atom_index);1750 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1748 _ = try atom.getOrCreateOffsetTableEntry(elf_file);1751 const atom = elf_file.getAtom(atom_index);
1749 const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));1752 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1750 try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });1753 const got_addr = @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1751 _ = try self.addInst(.{1754 try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
1752 .tag = .jalr,1755 _ = try self.addInst(.{
1753 .data = .{ .i_type = .{1756 .tag = .jalr,
1754 .rd = .ra,1757 .data = .{ .i_type = .{
1755 .rs1 = .ra,1758 .rd = .ra,
1756 .imm12 = 0,1759 .rs1 = .ra,
1757 } },1760 .imm12 = 0,
1758 });1761 } },
1759 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {1762 });
1760 return self.fail("TODO implement calling extern functions", .{});1763 },
1761 } else {1764 .extern_func => {
1762 return self.fail("TODO implement calling bitcasted functions", .{});1765 return self.fail("TODO implement calling extern functions", .{});
1766 },
1767 else => {
1768 return self.fail("TODO implement calling bitcasted functions", .{});
1769 },
1763 }1770 }
1764 } else {1771 } else {
1765 return self.fail("TODO implement calling runtime-known function pointer", .{});1772 return self.fail("TODO implement calling runtime-known function pointer", .{});
...@@ -1876,9 +1883,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -1876,9 +1883,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
1876fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {1883fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1877 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;1884 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
1878 const mod = self.bin_file.options.module.?;1885 const mod = self.bin_file.options.module.?;
1879 const function = mod.funcPtr(ty_fn.func);1886 const func = mod.funcInfo(ty_fn.func);
1880 // TODO emit debug info for function change1887 // TODO emit debug info for function change
1881 _ = function;1888 _ = func;
1882 return self.finishAir(inst, .dead, .{ .none, .none, .none });1889 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1883}1890}
18841891
...@@ -2569,11 +2576,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -2569,11 +2576,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
2569}2576}
25702577
2571fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {2578fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
2579 const mod = self.bin_file.options.module.?;
2572 const mcv: MCValue = switch (try codegen.genTypedValue(2580 const mcv: MCValue = switch (try codegen.genTypedValue(
2573 self.bin_file,2581 self.bin_file,
2574 self.src_loc,2582 self.src_loc,
2575 typed_value,2583 typed_value,
2576 self.mod_fn.owner_decl,2584 mod.funcOwnerDeclIndex(self.func_index),
2577 )) {2585 )) {
2578 .mcv => |mcv| switch (mcv) {2586 .mcv => |mcv| switch (mcv) {
2579 .none => .none,2587 .none => .none,
...@@ -2605,6 +2613,7 @@ const CallMCValues = struct {...@@ -2605,6 +2613,7 @@ const CallMCValues = struct {
2605/// Caller must call `CallMCValues.deinit`.2613/// Caller must call `CallMCValues.deinit`.
2606fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {2614fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2607 const mod = self.bin_file.options.module.?;2615 const mod = self.bin_file.options.module.?;
2616 const ip = &mod.intern_pool;
2608 const fn_info = mod.typeToFunc(fn_ty).?;2617 const fn_info = mod.typeToFunc(fn_ty).?;
2609 const cc = fn_info.cc;2618 const cc = fn_info.cc;
2610 var result: CallMCValues = .{2619 var result: CallMCValues = .{
...@@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -2636,14 +2645,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2636 var next_stack_offset: u32 = 0;2645 var next_stack_offset: u32 = 0;
2637 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };2646 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
26382647
2639 for (fn_info.param_types, 0..) |ty, i| {2648 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
2640 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));2649 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
2641 if (param_size <= 8) {2650 if (param_size <= 8) {
2642 if (next_register < argument_registers.len) {2651 if (next_register < argument_registers.len) {
2643 result.args[i] = .{ .register = argument_registers[next_register] };2652 result_arg.* = .{ .register = argument_registers[next_register] };
2644 next_register += 1;2653 next_register += 1;
2645 } else {2654 } else {
2646 result.args[i] = .{ .stack_offset = next_stack_offset };2655 result_arg.* = .{ .stack_offset = next_stack_offset };
2647 next_register += next_stack_offset;2656 next_register += next_stack_offset;
2648 }2657 }
2649 } else if (param_size <= 16) {2658 } else if (param_size <= 16) {
...@@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -2652,11 +2661,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2652 } else if (next_register < argument_registers.len) {2661 } else if (next_register < argument_registers.len) {
2653 return self.fail("TODO MCValues split register + stack", .{});2662 return self.fail("TODO MCValues split register + stack", .{});
2654 } else {2663 } else {
2655 result.args[i] = .{ .stack_offset = next_stack_offset };2664 result_arg.* = .{ .stack_offset = next_stack_offset };
2656 next_register += next_stack_offset;2665 next_register += next_stack_offset;
2657 }2666 }
2658 } else {2667 } else {
2659 result.args[i] = .{ .stack_offset = next_stack_offset };2668 result_arg.* = .{ .stack_offset = next_stack_offset };
2660 next_register += next_stack_offset;2669 next_register += next_stack_offset;
2661 }2670 }
2662 }2671 }
src/arch/sparc64/CodeGen.zig+55-46
...@@ -11,6 +11,7 @@ const Allocator = mem.Allocator;...@@ -11,6 +11,7 @@ const Allocator = mem.Allocator;
11const builtin = @import("builtin");11const builtin = @import("builtin");
12const link = @import("../../link.zig");12const link = @import("../../link.zig");
13const Module = @import("../../Module.zig");13const Module = @import("../../Module.zig");
14const InternPool = @import("../../InternPool.zig");
14const TypedValue = @import("../../TypedValue.zig");15const TypedValue = @import("../../TypedValue.zig");
15const ErrorMsg = Module.ErrorMsg;16const ErrorMsg = Module.ErrorMsg;
16const codegen = @import("../../codegen.zig");17const codegen = @import("../../codegen.zig");
...@@ -52,7 +53,7 @@ air: Air,...@@ -52,7 +53,7 @@ air: Air,
52liveness: Liveness,53liveness: Liveness,
53bin_file: *link.File,54bin_file: *link.File,
54target: *const std.Target,55target: *const std.Target,
55mod_fn: *const Module.Fn,56func_index: InternPool.Index,
56code: *std.ArrayList(u8),57code: *std.ArrayList(u8),
57debug_output: DebugInfoOutput,58debug_output: DebugInfoOutput,
58err_msg: ?*ErrorMsg,59err_msg: ?*ErrorMsg,
...@@ -260,7 +261,7 @@ const BigTomb = struct {...@@ -260,7 +261,7 @@ const BigTomb = struct {
260pub fn generate(261pub fn generate(
261 bin_file: *link.File,262 bin_file: *link.File,
262 src_loc: Module.SrcLoc,263 src_loc: Module.SrcLoc,
263 module_fn_index: Module.Fn.Index,264 func_index: InternPool.Index,
264 air: Air,265 air: Air,
265 liveness: Liveness,266 liveness: Liveness,
266 code: *std.ArrayList(u8),267 code: *std.ArrayList(u8),
...@@ -271,8 +272,8 @@ pub fn generate(...@@ -271,8 +272,8 @@ pub fn generate(
271 }272 }
272273
273 const mod = bin_file.options.module.?;274 const mod = bin_file.options.module.?;
274 const module_fn = mod.funcPtr(module_fn_index);275 const func = mod.funcInfo(func_index);
275 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);276 const fn_owner_decl = mod.declPtr(func.owner_decl);
276 assert(fn_owner_decl.has_tv);277 assert(fn_owner_decl.has_tv);
277 const fn_type = fn_owner_decl.ty;278 const fn_type = fn_owner_decl.ty;
278279
...@@ -289,8 +290,8 @@ pub fn generate(...@@ -289,8 +290,8 @@ pub fn generate(
289 .air = air,290 .air = air,
290 .liveness = liveness,291 .liveness = liveness,
291 .target = &bin_file.options.target,292 .target = &bin_file.options.target,
293 .func_index = func_index,
292 .bin_file = bin_file,294 .bin_file = bin_file,
293 .mod_fn = module_fn,
294 .code = code,295 .code = code,
295 .debug_output = debug_output,296 .debug_output = debug_output,
296 .err_msg = null,297 .err_msg = null,
...@@ -301,8 +302,8 @@ pub fn generate(...@@ -301,8 +302,8 @@ pub fn generate(
301 .branch_stack = &branch_stack,302 .branch_stack = &branch_stack,
302 .src_loc = src_loc,303 .src_loc = src_loc,
303 .stack_align = undefined,304 .stack_align = undefined,
304 .end_di_line = module_fn.rbrace_line,305 .end_di_line = func.rbrace_line,
305 .end_di_column = module_fn.rbrace_column,306 .end_di_column = func.rbrace_column,
306 };307 };
307 defer function.stack.deinit(bin_file.allocator);308 defer function.stack.deinit(bin_file.allocator);
308 defer function.blocks.deinit(bin_file.allocator);309 defer function.blocks.deinit(bin_file.allocator);
...@@ -344,8 +345,8 @@ pub fn generate(...@@ -344,8 +345,8 @@ pub fn generate(
344 .src_loc = src_loc,345 .src_loc = src_loc,
345 .code = code,346 .code = code,
346 .prev_di_pc = 0,347 .prev_di_pc = 0,
347 .prev_di_line = module_fn.lbrace_line,348 .prev_di_line = func.lbrace_line,
348 .prev_di_column = module_fn.lbrace_column,349 .prev_di_column = func.lbrace_column,
349 };350 };
350 defer emit.deinit();351 defer emit.deinit();
351352
...@@ -1345,37 +1346,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -1345,37 +1346,41 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1345 // on linking.1346 // on linking.
1346 if (try self.air.value(callee, mod)) |func_value| {1347 if (try self.air.value(callee, mod)) |func_value| {
1347 if (self.bin_file.tag == link.File.Elf.base_tag) {1348 if (self.bin_file.tag == link.File.Elf.base_tag) {
1348 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {1349 switch (mod.intern_pool.indexToKey(func_value.ip_index)) {
1349 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {1350 .func => |func| {
1350 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);1351 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1351 const atom = elf_file.getAtom(atom_index);1352 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
1352 _ = try atom.getOrCreateOffsetTableEntry(elf_file);1353 const atom = elf_file.getAtom(atom_index);
1353 break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));1354 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1354 } else unreachable;1355 break :blk @as(u32, @intCast(atom.getOffsetTableAddress(elf_file)));
1356 } else unreachable;
13551357
1356 try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });1358 try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });
13571359
1358 _ = try self.addInst(.{1360 _ = try self.addInst(.{
1359 .tag = .jmpl,1361 .tag = .jmpl,
1360 .data = .{1362 .data = .{
1361 .arithmetic_3op = .{1363 .arithmetic_3op = .{
1362 .is_imm = false,1364 .is_imm = false,
1363 .rd = .o7,1365 .rd = .o7,
1364 .rs1 = .o7,1366 .rs1 = .o7,
1365 .rs2_or_imm = .{ .rs2 = .g0 },1367 .rs2_or_imm = .{ .rs2 = .g0 },
1368 },
1366 },1369 },
1367 },1370 });
1368 });
13691371
1370 // TODO Find a way to fill this delay slot1372 // TODO Find a way to fill this delay slot
1371 _ = try self.addInst(.{1373 _ = try self.addInst(.{
1372 .tag = .nop,1374 .tag = .nop,
1373 .data = .{ .nop = {} },1375 .data = .{ .nop = {} },
1374 });1376 });
1375 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {1377 },
1376 return self.fail("TODO implement calling extern functions", .{});1378 .extern_func => {
1377 } else {1379 return self.fail("TODO implement calling extern functions", .{});
1378 return self.fail("TODO implement calling bitcasted functions", .{});1380 },
1381 else => {
1382 return self.fail("TODO implement calling bitcasted functions", .{});
1383 },
1379 }1384 }
1380 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");1385 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
1381 } else {1386 } else {
...@@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -1660,9 +1665,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
1660fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {1665fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1661 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;1666 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
1662 const mod = self.bin_file.options.module.?;1667 const mod = self.bin_file.options.module.?;
1663 const function = mod.funcPtr(ty_fn.func);1668 const func = mod.funcInfo(ty_fn.func);
1664 // TODO emit debug info for function change1669 // TODO emit debug info for function change
1665 _ = function;1670 _ = func;
1666 return self.finishAir(inst, .dead, .{ .none, .none, .none });1671 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1667}1672}
16681673
...@@ -3595,13 +3600,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live...@@ -3595,13 +3600,15 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
3595}3600}
35963601
3597fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {3602fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
3603 const mod = self.bin_file.options.module.?;
3598 const arg = self.air.instructions.items(.data)[inst].arg;3604 const arg = self.air.instructions.items(.data)[inst].arg;
3599 const ty = self.air.getRefType(arg.ty);3605 const ty = self.air.getRefType(arg.ty);
3600 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg.src_index);3606 const owner_decl = mod.funcOwnerDeclIndex(self.func_index);
3607 const name = mod.getParamName(self.func_index, arg.src_index);
36013608
3602 switch (self.debug_output) {3609 switch (self.debug_output) {
3603 .dwarf => |dw| switch (mcv) {3610 .dwarf => |dw| switch (mcv) {
3604 .register => |reg| try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, .{3611 .register => |reg| try dw.genArgDbgInfo(name, ty, owner_decl, .{
3605 .register = reg.dwarfLocOp(),3612 .register = reg.dwarfLocOp(),
3606 }),3613 }),
3607 else => {},3614 else => {},
...@@ -4127,11 +4134,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re...@@ -4127,11 +4134,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re
4127}4134}
41284135
4129fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {4136fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
4137 const mod = self.bin_file.options.module.?;
4130 const mcv: MCValue = switch (try codegen.genTypedValue(4138 const mcv: MCValue = switch (try codegen.genTypedValue(
4131 self.bin_file,4139 self.bin_file,
4132 self.src_loc,4140 self.src_loc,
4133 typed_value,4141 typed_value,
4134 self.mod_fn.owner_decl,4142 mod.funcOwnerDeclIndex(self.func_index),
4135 )) {4143 )) {
4136 .mcv => |mcv| switch (mcv) {4144 .mcv => |mcv| switch (mcv) {
4137 .none => .none,4145 .none => .none,
...@@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 {...@@ -4452,6 +4460,7 @@ fn realStackOffset(off: u32) u32 {
4452/// Caller must call `CallMCValues.deinit`.4460/// Caller must call `CallMCValues.deinit`.
4453fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {4461fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
4454 const mod = self.bin_file.options.module.?;4462 const mod = self.bin_file.options.module.?;
4463 const ip = &mod.intern_pool;
4455 const fn_info = mod.typeToFunc(fn_ty).?;4464 const fn_info = mod.typeToFunc(fn_ty).?;
4456 const cc = fn_info.cc;4465 const cc = fn_info.cc;
4457 var result: CallMCValues = .{4466 var result: CallMCValues = .{
...@@ -4486,14 +4495,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4486,14 +4495,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4486 .callee => abi.c_abi_int_param_regs_callee_view,4495 .callee => abi.c_abi_int_param_regs_callee_view,
4487 };4496 };
44884497
4489 for (fn_info.param_types, 0..) |ty, i| {4498 for (fn_info.param_types.get(ip), result.args) |ty, *result_arg| {
4490 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));4499 const param_size = @as(u32, @intCast(ty.toType().abiSize(mod)));
4491 if (param_size <= 8) {4500 if (param_size <= 8) {
4492 if (next_register < argument_registers.len) {4501 if (next_register < argument_registers.len) {
4493 result.args[i] = .{ .register = argument_registers[next_register] };4502 result_arg.* = .{ .register = argument_registers[next_register] };
4494 next_register += 1;4503 next_register += 1;
4495 } else {4504 } else {
4496 result.args[i] = .{ .stack_offset = next_stack_offset };4505 result_arg.* = .{ .stack_offset = next_stack_offset };
4497 next_register += next_stack_offset;4506 next_register += next_stack_offset;
4498 }4507 }
4499 } else if (param_size <= 16) {4508 } else if (param_size <= 16) {
...@@ -4502,11 +4511,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4502,11 +4511,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4502 } else if (next_register < argument_registers.len) {4511 } else if (next_register < argument_registers.len) {
4503 return self.fail("TODO MCValues split register + stack", .{});4512 return self.fail("TODO MCValues split register + stack", .{});
4504 } else {4513 } else {
4505 result.args[i] = .{ .stack_offset = next_stack_offset };4514 result_arg.* = .{ .stack_offset = next_stack_offset };
4506 next_register += next_stack_offset;4515 next_register += next_stack_offset;
4507 }4516 }
4508 } else {4517 } else {
4509 result.args[i] = .{ .stack_offset = next_stack_offset };4518 result_arg.* = .{ .stack_offset = next_stack_offset };
4510 next_register += next_stack_offset;4519 next_register += next_stack_offset;
4511 }4520 }
4512 }4521 }
src/arch/wasm/CodeGen.zig+16-12
...@@ -650,7 +650,7 @@ air: Air,...@@ -650,7 +650,7 @@ air: Air,
650liveness: Liveness,650liveness: Liveness,
651gpa: mem.Allocator,651gpa: mem.Allocator,
652debug_output: codegen.DebugInfoOutput,652debug_output: codegen.DebugInfoOutput,
653mod_fn: *const Module.Fn,653func_index: InternPool.Index,
654/// Contains a list of current branches.654/// Contains a list of current branches.
655/// When we return from a branch, the branch will be popped from this list,655/// When we return from a branch, the branch will be popped from this list,
656/// which means branches can only contain references from within its own branch,656/// which means branches can only contain references from within its own branch,
...@@ -1202,7 +1202,7 @@ fn genFunctype(...@@ -1202,7 +1202,7 @@ fn genFunctype(
1202pub fn generate(1202pub fn generate(
1203 bin_file: *link.File,1203 bin_file: *link.File,
1204 src_loc: Module.SrcLoc,1204 src_loc: Module.SrcLoc,
1205 func_index: Module.Fn.Index,1205 func_index: InternPool.Index,
1206 air: Air,1206 air: Air,
1207 liveness: Liveness,1207 liveness: Liveness,
1208 code: *std.ArrayList(u8),1208 code: *std.ArrayList(u8),
...@@ -1210,7 +1210,7 @@ pub fn generate(...@@ -1210,7 +1210,7 @@ pub fn generate(
1210) codegen.CodeGenError!codegen.Result {1210) codegen.CodeGenError!codegen.Result {
1211 _ = src_loc;1211 _ = src_loc;
1212 const mod = bin_file.options.module.?;1212 const mod = bin_file.options.module.?;
1213 const func = mod.funcPtr(func_index);1213 const func = mod.funcInfo(func_index);
1214 var code_gen: CodeGen = .{1214 var code_gen: CodeGen = .{
1215 .gpa = bin_file.allocator,1215 .gpa = bin_file.allocator,
1216 .air = air,1216 .air = air,
...@@ -1223,7 +1223,7 @@ pub fn generate(...@@ -1223,7 +1223,7 @@ pub fn generate(
1223 .target = bin_file.options.target,1223 .target = bin_file.options.target,
1224 .bin_file = bin_file.cast(link.File.Wasm).?,1224 .bin_file = bin_file.cast(link.File.Wasm).?,
1225 .debug_output = debug_output,1225 .debug_output = debug_output,
1226 .mod_fn = func,1226 .func_index = func_index,
1227 };1227 };
1228 defer code_gen.deinit();1228 defer code_gen.deinit();
12291229
...@@ -1237,8 +1237,9 @@ pub fn generate(...@@ -1237,8 +1237,9 @@ pub fn generate(
12371237
1238fn genFunc(func: *CodeGen) InnerError!void {1238fn genFunc(func: *CodeGen) InnerError!void {
1239 const mod = func.bin_file.base.options.module.?;1239 const mod = func.bin_file.base.options.module.?;
1240 const ip = &mod.intern_pool;
1240 const fn_info = mod.typeToFunc(func.decl.ty).?;1241 const fn_info = mod.typeToFunc(func.decl.ty).?;
1241 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);1242 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod);
1242 defer func_type.deinit(func.gpa);1243 defer func_type.deinit(func.gpa);
1243 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);1244 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);
12441245
...@@ -1347,6 +1348,7 @@ const CallWValues = struct {...@@ -1347,6 +1348,7 @@ const CallWValues = struct {
13471348
1348fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {1349fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
1349 const mod = func.bin_file.base.options.module.?;1350 const mod = func.bin_file.base.options.module.?;
1351 const ip = &mod.intern_pool;
1350 const fn_info = mod.typeToFunc(fn_ty).?;1352 const fn_info = mod.typeToFunc(fn_ty).?;
1351 const cc = fn_info.cc;1353 const cc = fn_info.cc;
1352 var result: CallWValues = .{1354 var result: CallWValues = .{
...@@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1369,7 +1371,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13691371
1370 switch (cc) {1372 switch (cc) {
1371 .Unspecified => {1373 .Unspecified => {
1372 for (fn_info.param_types) |ty| {1374 for (fn_info.param_types.get(ip)) |ty| {
1373 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {1375 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
1374 continue;1376 continue;
1375 }1377 }
...@@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1379,7 +1381,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
1379 }1381 }
1380 },1382 },
1381 .C => {1383 .C => {
1382 for (fn_info.param_types) |ty| {1384 for (fn_info.param_types.get(ip)) |ty| {
1383 const ty_classes = abi.classifyType(ty.toType(), mod);1385 const ty_classes = abi.classifyType(ty.toType(), mod);
1384 for (ty_classes) |class| {1386 for (ty_classes) |class| {
1385 if (class == .none) continue;1387 if (class == .none) continue;
...@@ -2185,6 +2187,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2185,6 +2187,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2185 const ty = func.typeOf(pl_op.operand);2187 const ty = func.typeOf(pl_op.operand);
21862188
2187 const mod = func.bin_file.base.options.module.?;2189 const mod = func.bin_file.base.options.module.?;
2190 const ip = &mod.intern_pool;
2188 const fn_ty = switch (ty.zigTypeTag(mod)) {2191 const fn_ty = switch (ty.zigTypeTag(mod)) {
2189 .Fn => ty,2192 .Fn => ty,
2190 .Pointer => ty.childType(mod),2193 .Pointer => ty.childType(mod),
...@@ -2203,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2203,7 +2206,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2203 } else if (func_val.getExternFunc(mod)) |extern_func| {2206 } else if (func_val.getExternFunc(mod)) |extern_func| {
2204 const ext_decl = mod.declPtr(extern_func.decl);2207 const ext_decl = mod.declPtr(extern_func.decl);
2205 const ext_info = mod.typeToFunc(ext_decl.ty).?;2208 const ext_info = mod.typeToFunc(ext_decl.ty).?;
2206 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);2209 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types.get(ip), ext_info.return_type.toType(), mod);
2207 defer func_type.deinit(func.gpa);2210 defer func_type.deinit(func.gpa);
2208 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);2211 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
2209 const atom = func.bin_file.getAtomPtr(atom_index);2212 const atom = func.bin_file.getAtomPtr(atom_index);
...@@ -2253,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2253,7 +2256,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2253 const operand = try func.resolveInst(pl_op.operand);2256 const operand = try func.resolveInst(pl_op.operand);
2254 try func.emitWValue(operand);2257 try func.emitWValue(operand);
22552258
2256 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);2259 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types.get(ip), fn_info.return_type.toType(), mod);
2257 defer fn_type.deinit(func.gpa);2260 defer fn_type.deinit(func.gpa);
22582261
2259 const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);2262 const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);
...@@ -2564,8 +2567,8 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2564,8 +2567,8 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2564 switch (func.debug_output) {2567 switch (func.debug_output) {
2565 .dwarf => |dwarf| {2568 .dwarf => |dwarf| {
2566 const src_index = func.air.instructions.items(.data)[inst].arg.src_index;2569 const src_index = func.air.instructions.items(.data)[inst].arg.src_index;
2567 const name = func.mod_fn.getParamName(func.bin_file.base.options.module.?, src_index);2570 const name = mod.getParamName(func.func_index, src_index);
2568 try dwarf.genArgDbgInfo(name, arg_ty, func.mod_fn.owner_decl, .{2571 try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{
2569 .wasm_local = arg.local.value,2572 .wasm_local = arg.local.value,
2570 });2573 });
2571 },2574 },
...@@ -6198,6 +6201,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6198,6 +6201,7 @@ fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6198fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {6201fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
6199 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});6202 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
62006203
6204 const mod = func.bin_file.base.options.module.?;
6201 const pl_op = func.air.instructions.items(.data)[inst].pl_op;6205 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
6202 const ty = func.typeOf(pl_op.operand);6206 const ty = func.typeOf(pl_op.operand);
6203 const operand = try func.resolveInst(pl_op.operand);6207 const operand = try func.resolveInst(pl_op.operand);
...@@ -6214,7 +6218,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {...@@ -6214,7 +6218,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
6214 break :blk .nop;6218 break :blk .nop;
6215 },6219 },
6216 };6220 };
6217 try func.debug_output.dwarf.genVarDbgInfo(name, ty, func.mod_fn.owner_decl, is_ptr, loc);6221 try func.debug_output.dwarf.genVarDbgInfo(name, ty, mod.funcOwnerDeclIndex(func.func_index), is_ptr, loc);
62186222
6219 func.finishAir(inst, .none, &.{});6223 func.finishAir(inst, .none, &.{});
6220}6224}
src/arch/x86_64/CodeGen.zig+23-22
...@@ -110,20 +110,21 @@ const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };...@@ -110,20 +110,21 @@ const FrameAddr = struct { index: FrameIndex, off: i32 = 0 };
110const RegisterOffset = struct { reg: Register, off: i32 = 0 };110const RegisterOffset = struct { reg: Register, off: i32 = 0 };
111111
112const Owner = union(enum) {112const Owner = union(enum) {
113 mod_fn: *const Module.Fn,113 func_index: InternPool.Index,
114 lazy_sym: link.File.LazySymbol,114 lazy_sym: link.File.LazySymbol,
115115
116 fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {116 fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {
117 return switch (owner) {117 return switch (owner) {
118 .mod_fn => |mod_fn| mod_fn.owner_decl,118 .func_index => |func_index| mod.funcOwnerDeclIndex(func_index),
119 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod),119 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod),
120 };120 };
121 }121 }
122122
123 fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 {123 fn getSymbolIndex(owner: Owner, ctx: *Self) !u32 {
124 switch (owner) {124 switch (owner) {
125 .mod_fn => |mod_fn| {125 .func_index => |func_index| {
126 const decl_index = mod_fn.owner_decl;126 const mod = ctx.bin_file.options.module.?;
127 const decl_index = mod.funcOwnerDeclIndex(func_index);
127 if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {128 if (ctx.bin_file.cast(link.File.MachO)) |macho_file| {
128 const atom = try macho_file.getOrCreateAtomForDecl(decl_index);129 const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
129 return macho_file.getAtom(atom).getSymbolIndex().?;130 return macho_file.getAtom(atom).getSymbolIndex().?;
...@@ -638,7 +639,7 @@ const Self = @This();...@@ -638,7 +639,7 @@ const Self = @This();
638pub fn generate(639pub fn generate(
639 bin_file: *link.File,640 bin_file: *link.File,
640 src_loc: Module.SrcLoc,641 src_loc: Module.SrcLoc,
641 module_fn_index: Module.Fn.Index,642 func_index: InternPool.Index,
642 air: Air,643 air: Air,
643 liveness: Liveness,644 liveness: Liveness,
644 code: *std.ArrayList(u8),645 code: *std.ArrayList(u8),
...@@ -649,8 +650,8 @@ pub fn generate(...@@ -649,8 +650,8 @@ pub fn generate(
649 }650 }
650651
651 const mod = bin_file.options.module.?;652 const mod = bin_file.options.module.?;
652 const module_fn = mod.funcPtr(module_fn_index);653 const func = mod.funcInfo(func_index);
653 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);654 const fn_owner_decl = mod.declPtr(func.owner_decl);
654 assert(fn_owner_decl.has_tv);655 assert(fn_owner_decl.has_tv);
655 const fn_type = fn_owner_decl.ty;656 const fn_type = fn_owner_decl.ty;
656657
...@@ -662,15 +663,15 @@ pub fn generate(...@@ -662,15 +663,15 @@ pub fn generate(
662 .target = &bin_file.options.target,663 .target = &bin_file.options.target,
663 .bin_file = bin_file,664 .bin_file = bin_file,
664 .debug_output = debug_output,665 .debug_output = debug_output,
665 .owner = .{ .mod_fn = module_fn },666 .owner = .{ .func_index = func_index },
666 .err_msg = null,667 .err_msg = null,
667 .args = undefined, // populated after `resolveCallingConventionValues`668 .args = undefined, // populated after `resolveCallingConventionValues`
668 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`669 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
669 .fn_type = fn_type,670 .fn_type = fn_type,
670 .arg_index = 0,671 .arg_index = 0,
671 .src_loc = src_loc,672 .src_loc = src_loc,
672 .end_di_line = module_fn.rbrace_line,673 .end_di_line = func.rbrace_line,
673 .end_di_column = module_fn.rbrace_column,674 .end_di_column = func.rbrace_column,
674 };675 };
675 defer {676 defer {
676 function.frame_allocs.deinit(gpa);677 function.frame_allocs.deinit(gpa);
...@@ -687,17 +688,16 @@ pub fn generate(...@@ -687,17 +688,16 @@ pub fn generate(
687 if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa);688 if (builtin.mode == .Debug) function.mir_to_air_map.deinit(gpa);
688 }689 }
689690
690 wip_mir_log.debug("{}:", .{function.fmtDecl(module_fn.owner_decl)});691 wip_mir_log.debug("{}:", .{function.fmtDecl(func.owner_decl)});
692
693 const ip = &mod.intern_pool;
691694
692 try function.frame_allocs.resize(gpa, FrameIndex.named_count);695 try function.frame_allocs.resize(gpa, FrameIndex.named_count);
693 function.frame_allocs.set(696 function.frame_allocs.set(
694 @intFromEnum(FrameIndex.stack_frame),697 @intFromEnum(FrameIndex.stack_frame),
695 FrameAlloc.init(.{698 FrameAlloc.init(.{
696 .size = 0,699 .size = 0,
697 .alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack|700 .alignment = @intCast(func.analysis(ip).stack_alignment.toByteUnitsOptional() orelse 1),
698 @intCast(set_align_stack.alignment.toByteUnitsOptional().?)
699 else
700 1,
701 }),701 }),
702 );702 );
703 function.frame_allocs.set(703 function.frame_allocs.set(
...@@ -761,8 +761,8 @@ pub fn generate(...@@ -761,8 +761,8 @@ pub fn generate(
761 .debug_output = debug_output,761 .debug_output = debug_output,
762 .code = code,762 .code = code,
763 .prev_di_pc = 0,763 .prev_di_pc = 0,
764 .prev_di_line = module_fn.lbrace_line,764 .prev_di_line = func.lbrace_line,
765 .prev_di_column = module_fn.lbrace_column,765 .prev_di_column = func.lbrace_column,
766 };766 };
767 defer emit.deinit();767 defer emit.deinit();
768 emit.emitMir() catch |err| switch (err) {768 emit.emitMir() catch |err| switch (err) {
...@@ -7942,7 +7942,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -7942,7 +7942,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
79427942
7943 const ty = self.typeOfIndex(inst);7943 const ty = self.typeOfIndex(inst);
7944 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;7944 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
7945 const name = self.owner.mod_fn.getParamName(mod, src_index);7945 const name = mod.getParamName(self.owner.func_index, src_index);
7946 try self.genArgDbgInfo(ty, name, dst_mcv);7946 try self.genArgDbgInfo(ty, name, dst_mcv);
79477947
7948 break :result dst_mcv;7948 break :result dst_mcv;
...@@ -8139,7 +8139,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8139,7 +8139,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8139 if (try self.air.value(callee, mod)) |func_value| {8139 if (try self.air.value(callee, mod)) |func_value| {
8140 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);8140 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
8141 if (switch (func_key) {8141 if (switch (func_key) {
8142 .func => |func| mod.funcPtr(func.index).owner_decl,8142 .func => |func| func.owner_decl,
8143 .ptr => |ptr| switch (ptr.addr) {8143 .ptr => |ptr| switch (ptr.addr) {
8144 .decl => |decl| decl,8144 .decl => |decl| decl,
8145 else => null,8145 else => null,
...@@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {...@@ -8582,9 +8582,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
8582fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {8582fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
8583 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;8583 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
8584 const mod = self.bin_file.options.module.?;8584 const mod = self.bin_file.options.module.?;
8585 const function = mod.funcPtr(ty_fn.func);8585 const func = mod.funcInfo(ty_fn.func);
8586 // TODO emit debug info for function change8586 // TODO emit debug info for function change
8587 _ = function;8587 _ = func;
8588 return self.finishAir(inst, .unreach, .{ .none, .none, .none });8588 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
8589}8589}
85908590
...@@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues(...@@ -11719,11 +11719,12 @@ fn resolveCallingConventionValues(
11719 stack_frame_base: FrameIndex,11719 stack_frame_base: FrameIndex,
11720) !CallMCValues {11720) !CallMCValues {
11721 const mod = self.bin_file.options.module.?;11721 const mod = self.bin_file.options.module.?;
11722 const ip = &mod.intern_pool;
11722 const cc = fn_info.cc;11723 const cc = fn_info.cc;
11723 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);11724 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
11724 defer self.gpa.free(param_types);11725 defer self.gpa.free(param_types);
1172511726
11726 for (param_types[0..fn_info.param_types.len], fn_info.param_types) |*dest, src| {11727 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {
11727 dest.* = src.toType();11728 dest.* = src.toType();
11728 }11729 }
11729 // TODO: promote var arg types11730 // TODO: promote var arg types
src/codegen.zig+1-1
...@@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {...@@ -67,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
67pub fn generateFunction(67pub fn generateFunction(
68 bin_file: *link.File,68 bin_file: *link.File,
69 src_loc: Module.SrcLoc,69 src_loc: Module.SrcLoc,
70 func_index: Module.Fn.Index,70 func_index: InternPool.Index,
71 air: Air,71 air: Air,
72 liveness: Liveness,72 liveness: Liveness,
73 code: *std.ArrayList(u8),73 code: *std.ArrayList(u8),
src/codegen/c.zig+9-7
...@@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {...@@ -257,7 +257,8 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
257 return .{ .data = ident };257 return .{ .data = ident };
258}258}
259259
260/// This data is available when outputting .c code for a `Module.Fn.Index`.260/// This data is available when outputting .c code for a `InternPool.Index`
261/// that corresponds to `func`.
261/// It is not available when generating .h file.262/// It is not available when generating .h file.
262pub const Function = struct {263pub const Function = struct {
263 air: Air,264 air: Air,
...@@ -268,7 +269,7 @@ pub const Function = struct {...@@ -268,7 +269,7 @@ pub const Function = struct {
268 next_block_index: usize = 0,269 next_block_index: usize = 0,
269 object: Object,270 object: Object,
270 lazy_fns: LazyFnMap,271 lazy_fns: LazyFnMap,
271 func_index: Module.Fn.Index,272 func_index: InternPool.Index,
272 /// All the locals, to be emitted at the top of the function.273 /// All the locals, to be emitted at the top of the function.
273 locals: std.ArrayListUnmanaged(Local) = .{},274 locals: std.ArrayListUnmanaged(Local) = .{},
274 /// Which locals are available for reuse, based on Type.275 /// Which locals are available for reuse, based on Type.
...@@ -1487,6 +1488,7 @@ pub const DeclGen = struct {...@@ -1487,6 +1488,7 @@ pub const DeclGen = struct {
1487 ) !void {1488 ) !void {
1488 const store = &dg.ctypes.set;1489 const store = &dg.ctypes.set;
1489 const mod = dg.module;1490 const mod = dg.module;
1491 const ip = &mod.intern_pool;
14901492
1491 const fn_decl = mod.declPtr(fn_decl_index);1493 const fn_decl = mod.declPtr(fn_decl_index);
1492 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);1494 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);
...@@ -1499,7 +1501,7 @@ pub const DeclGen = struct {...@@ -1499,7 +1501,7 @@ pub const DeclGen = struct {
1499 else => unreachable,1501 else => unreachable,
1500 }1502 }
1501 }1503 }
1502 if (fn_decl.val.getFunction(mod)) |func| if (func.is_cold) try w.writeAll("zig_cold ");1504 if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold) try w.writeAll("zig_cold ");
1503 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");1505 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
15041506
1505 const trailing = try renderTypePrefix(1507 const trailing = try renderTypePrefix(
...@@ -1744,7 +1746,7 @@ pub const DeclGen = struct {...@@ -1744,7 +1746,7 @@ pub const DeclGen = struct {
1744 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {1746 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
1745 .variable => |variable| mod.decl_exports.contains(variable.decl),1747 .variable => |variable| mod.decl_exports.contains(variable.decl),
1746 .extern_func => true,1748 .extern_func => true,
1747 .func => |func| mod.decl_exports.contains(mod.funcPtr(func.index).owner_decl),1749 .func => |func| mod.decl_exports.contains(func.owner_decl),
1748 else => unreachable,1750 else => unreachable,
1749 };1751 };
1750 }1752 }
...@@ -4161,7 +4163,7 @@ fn airCall(...@@ -4161,7 +4163,7 @@ fn airCall(
4161 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;4163 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
4162 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {4164 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
4163 .extern_func => |extern_func| extern_func.decl,4165 .extern_func => |extern_func| extern_func.decl,
4164 .func => |func| mod.funcPtr(func.index).owner_decl,4166 .func => |func| func.owner_decl,
4165 .ptr => |ptr| switch (ptr.addr) {4167 .ptr => |ptr| switch (ptr.addr) {
4166 .decl => |decl| decl,4168 .decl => |decl| decl,
4167 else => break :known,4169 else => break :known,
...@@ -4238,9 +4240,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4238,9 +4240,9 @@ fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
4238 const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;4240 const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;
4239 const mod = f.object.dg.module;4241 const mod = f.object.dg.module;
4240 const writer = f.object.writer();4242 const writer = f.object.writer();
4241 const function = mod.funcPtr(ty_fn.func);4243 const owner_decl = mod.funcOwnerDeclPtr(ty_fn.func);
4242 try writer.print("/* dbg func:{s} */\n", .{4244 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),
4244 });4246 });
4245 return .none;4247 return .none;
4246}4248}
src/codegen/c/type.zig+9-5
...@@ -1722,6 +1722,7 @@ pub const CType = extern union {...@@ -1722,6 +1722,7 @@ pub const CType = extern union {
17221722
1723 .Fn => {1723 .Fn => {
1724 const info = mod.typeToFunc(ty).?;1724 const info = mod.typeToFunc(ty).?;
1725 const ip = &mod.intern_pool;
1725 if (!info.is_generic) {1726 if (!info.is_generic) {
1726 if (lookup.isMutable()) {1727 if (lookup.isMutable()) {
1727 const param_kind: Kind = switch (kind) {1728 const param_kind: Kind = switch (kind) {
...@@ -1730,7 +1731,7 @@ pub const CType = extern union {...@@ -1730,7 +1731,7 @@ pub const CType = extern union {
1730 .payload => unreachable,1731 .payload => unreachable,
1731 };1732 };
1732 _ = try lookup.typeToIndex(info.return_type.toType(), param_kind);1733 _ = try lookup.typeToIndex(info.return_type.toType(), param_kind);
1733 for (info.param_types) |param_type| {1734 for (info.param_types.get(ip)) |param_type| {
1734 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;1735 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
1735 _ = try lookup.typeToIndex(param_type.toType(), param_kind);1736 _ = try lookup.typeToIndex(param_type.toType(), param_kind);
1736 }1737 }
...@@ -2014,6 +2015,7 @@ pub const CType = extern union {...@@ -2014,6 +2015,7 @@ pub const CType = extern union {
2014 .function,2015 .function,
2015 .varargs_function,2016 .varargs_function,
2016 => {2017 => {
2018 const ip = &mod.intern_pool;
2017 const info = mod.typeToFunc(ty).?;2019 const info = mod.typeToFunc(ty).?;
2018 assert(!info.is_generic);2020 assert(!info.is_generic);
2019 const param_kind: Kind = switch (kind) {2021 const param_kind: Kind = switch (kind) {
...@@ -2023,14 +2025,14 @@ pub const CType = extern union {...@@ -2023,14 +2025,14 @@ pub const CType = extern union {
2023 };2025 };
20242026
2025 var c_params_len: usize = 0;2027 var c_params_len: usize = 0;
2026 for (info.param_types) |param_type| {2028 for (info.param_types.get(ip)) |param_type| {
2027 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;2029 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2028 c_params_len += 1;2030 c_params_len += 1;
2029 }2031 }
20302032
2031 const params_pl = try arena.alloc(Index, c_params_len);2033 const params_pl = try arena.alloc(Index, c_params_len);
2032 var c_param_i: usize = 0;2034 var c_param_i: usize = 0;
2033 for (info.param_types) |param_type| {2035 for (info.param_types.get(ip)) |param_type| {
2034 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;2036 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2035 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;2037 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
2036 c_param_i += 1;2038 c_param_i += 1;
...@@ -2147,6 +2149,7 @@ pub const CType = extern union {...@@ -2147,6 +2149,7 @@ pub const CType = extern union {
2147 => {2149 => {
2148 if (ty.zigTypeTag(mod) != .Fn) return false;2150 if (ty.zigTypeTag(mod) != .Fn) return false;
21492151
2152 const ip = &mod.intern_pool;
2150 const info = mod.typeToFunc(ty).?;2153 const info = mod.typeToFunc(ty).?;
2151 assert(!info.is_generic);2154 assert(!info.is_generic);
2152 const data = cty.cast(Payload.Function).?.data;2155 const data = cty.cast(Payload.Function).?.data;
...@@ -2160,7 +2163,7 @@ pub const CType = extern union {...@@ -2160,7 +2163,7 @@ pub const CType = extern union {
2160 return false;2163 return false;
21612164
2162 var c_param_i: usize = 0;2165 var c_param_i: usize = 0;
2163 for (info.param_types) |param_type| {2166 for (info.param_types.get(ip)) |param_type| {
2164 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;2167 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
21652168
2166 if (c_param_i >= data.param_types.len) return false;2169 if (c_param_i >= data.param_types.len) return false;
...@@ -2202,6 +2205,7 @@ pub const CType = extern union {...@@ -2202,6 +2205,7 @@ pub const CType = extern union {
2202 autoHash(hasher, t);2205 autoHash(hasher, t);
22032206
2204 const mod = self.lookup.getModule();2207 const mod = self.lookup.getModule();
2208 const ip = &mod.intern_pool;
2205 switch (t) {2209 switch (t) {
2206 .fwd_anon_struct,2210 .fwd_anon_struct,
2207 .fwd_anon_union,2211 .fwd_anon_union,
...@@ -2270,7 +2274,7 @@ pub const CType = extern union {...@@ -2270,7 +2274,7 @@ pub const CType = extern union {
2270 };2274 };
22712275
2272 self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);2276 self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);
2273 for (info.param_types) |param_type| {2277 for (info.param_types.get(ip)) |param_type| {
2274 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;2278 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2275 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);2279 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
2276 }2280 }
src/codegen/llvm.zig+63-55
...@@ -867,14 +867,15 @@ pub const Object = struct {...@@ -867,14 +867,15 @@ pub const Object = struct {
867 pub fn updateFunc(867 pub fn updateFunc(
868 o: *Object,868 o: *Object,
869 mod: *Module,869 mod: *Module,
870 func_index: Module.Fn.Index,870 func_index: InternPool.Index,
871 air: Air,871 air: Air,
872 liveness: Liveness,872 liveness: Liveness,
873 ) !void {873 ) !void {
874 const func = mod.funcPtr(func_index);874 const func = mod.funcInfo(func_index);
875 const decl_index = func.owner_decl;875 const decl_index = func.owner_decl;
876 const decl = mod.declPtr(decl_index);876 const decl = mod.declPtr(decl_index);
877 const target = mod.getTarget();877 const target = mod.getTarget();
878 const ip = &mod.intern_pool;
878879
879 var dg: DeclGen = .{880 var dg: DeclGen = .{
880 .object = o,881 .object = o,
...@@ -885,24 +886,23 @@ pub const Object = struct {...@@ -885,24 +886,23 @@ pub const Object = struct {
885886
886 const llvm_func = try o.resolveLlvmFunction(decl_index);887 const llvm_func = try o.resolveLlvmFunction(decl_index);
887888
888 if (mod.align_stack_fns.get(func_index)) |align_info| {889 if (func.analysis(ip).is_noinline) {
889 o.addFnAttrInt(llvm_func, "alignstack", align_info.alignment.toByteUnitsOptional().?);
890 o.addFnAttr(llvm_func, "noinline");890 o.addFnAttr(llvm_func, "noinline");
891 } else {891 } else {
892 Object.removeFnAttr(llvm_func, "alignstack");892 Object.removeFnAttr(llvm_func, "noinline");
893 if (!func.is_noinline) Object.removeFnAttr(llvm_func, "noinline");
894 }893 }
895894
896 if (func.is_cold) {895 if (func.analysis(ip).stack_alignment.toByteUnitsOptional()) |alignment| {
897 o.addFnAttr(llvm_func, "cold");896 o.addFnAttrInt(llvm_func, "alignstack", alignment);
897 o.addFnAttr(llvm_func, "noinline");
898 } else {898 } else {
899 Object.removeFnAttr(llvm_func, "cold");899 Object.removeFnAttr(llvm_func, "alignstack");
900 }900 }
901901
902 if (func.is_noinline) {902 if (func.analysis(ip).is_cold) {
903 o.addFnAttr(llvm_func, "noinline");903 o.addFnAttr(llvm_func, "cold");
904 } else {904 } else {
905 Object.removeFnAttr(llvm_func, "noinline");905 Object.removeFnAttr(llvm_func, "cold");
906 }906 }
907907
908 // TODO: disable this if safety is off for the function scope908 // TODO: disable this if safety is off for the function scope
...@@ -921,7 +921,7 @@ pub const Object = struct {...@@ -921,7 +921,7 @@ pub const Object = struct {
921 o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");921 o.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
922 }922 }
923923
924 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|924 if (ip.stringToSliceUnwrap(decl.@"linksection")) |section|
925 llvm_func.setSection(section);925 llvm_func.setSection(section);
926926
927 // Remove all the basic blocks of a function in order to start over, generating927 // Remove all the basic blocks of a function in order to start over, generating
...@@ -968,7 +968,7 @@ pub const Object = struct {...@@ -968,7 +968,7 @@ pub const Object = struct {
968 .byval => {968 .byval => {
969 assert(!it.byval_attr);969 assert(!it.byval_attr);
970 const param_index = it.zig_index - 1;970 const param_index = it.zig_index - 1;
971 const param_ty = fn_info.param_types[param_index].toType();971 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
972 const param = llvm_func.getParam(llvm_arg_i);972 const param = llvm_func.getParam(llvm_arg_i);
973 try args.ensureUnusedCapacity(1);973 try args.ensureUnusedCapacity(1);
974974
...@@ -987,7 +987,7 @@ pub const Object = struct {...@@ -987,7 +987,7 @@ pub const Object = struct {
987 llvm_arg_i += 1;987 llvm_arg_i += 1;
988 },988 },
989 .byref => {989 .byref => {
990 const param_ty = fn_info.param_types[it.zig_index - 1].toType();990 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
991 const param_llvm_ty = try o.lowerType(param_ty);991 const param_llvm_ty = try o.lowerType(param_ty);
992 const param = llvm_func.getParam(llvm_arg_i);992 const param = llvm_func.getParam(llvm_arg_i);
993 const alignment = param_ty.abiAlignment(mod);993 const alignment = param_ty.abiAlignment(mod);
...@@ -1006,7 +1006,7 @@ pub const Object = struct {...@@ -1006,7 +1006,7 @@ pub const Object = struct {
1006 }1006 }
1007 },1007 },
1008 .byref_mut => {1008 .byref_mut => {
1009 const param_ty = fn_info.param_types[it.zig_index - 1].toType();1009 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1010 const param_llvm_ty = try o.lowerType(param_ty);1010 const param_llvm_ty = try o.lowerType(param_ty);
1011 const param = llvm_func.getParam(llvm_arg_i);1011 const param = llvm_func.getParam(llvm_arg_i);
1012 const alignment = param_ty.abiAlignment(mod);1012 const alignment = param_ty.abiAlignment(mod);
...@@ -1026,7 +1026,7 @@ pub const Object = struct {...@@ -1026,7 +1026,7 @@ pub const Object = struct {
1026 },1026 },
1027 .abi_sized_int => {1027 .abi_sized_int => {
1028 assert(!it.byval_attr);1028 assert(!it.byval_attr);
1029 const param_ty = fn_info.param_types[it.zig_index - 1].toType();1029 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1030 const param = llvm_func.getParam(llvm_arg_i);1030 const param = llvm_func.getParam(llvm_arg_i);
1031 llvm_arg_i += 1;1031 llvm_arg_i += 1;
10321032
...@@ -1053,7 +1053,7 @@ pub const Object = struct {...@@ -1053,7 +1053,7 @@ pub const Object = struct {
1053 },1053 },
1054 .slice => {1054 .slice => {
1055 assert(!it.byval_attr);1055 assert(!it.byval_attr);
1056 const param_ty = fn_info.param_types[it.zig_index - 1].toType();1056 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1057 const ptr_info = param_ty.ptrInfo(mod);1057 const ptr_info = param_ty.ptrInfo(mod);
10581058
1059 if (math.cast(u5, it.zig_index - 1)) |i| {1059 if (math.cast(u5, it.zig_index - 1)) |i| {
...@@ -1083,7 +1083,7 @@ pub const Object = struct {...@@ -1083,7 +1083,7 @@ pub const Object = struct {
1083 .multiple_llvm_types => {1083 .multiple_llvm_types => {
1084 assert(!it.byval_attr);1084 assert(!it.byval_attr);
1085 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];1085 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];
1086 const param_ty = fn_info.param_types[it.zig_index - 1].toType();1086 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1087 const param_llvm_ty = try o.lowerType(param_ty);1087 const param_llvm_ty = try o.lowerType(param_ty);
1088 const param_alignment = param_ty.abiAlignment(mod);1088 const param_alignment = param_ty.abiAlignment(mod);
1089 const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);1089 const arg_ptr = buildAllocaInner(o.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
...@@ -1114,7 +1114,7 @@ pub const Object = struct {...@@ -1114,7 +1114,7 @@ pub const Object = struct {
1114 args.appendAssumeCapacity(casted);1114 args.appendAssumeCapacity(casted);
1115 },1115 },
1116 .float_array => {1116 .float_array => {
1117 const param_ty = fn_info.param_types[it.zig_index - 1].toType();1117 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1118 const param_llvm_ty = try o.lowerType(param_ty);1118 const param_llvm_ty = try o.lowerType(param_ty);
1119 const param = llvm_func.getParam(llvm_arg_i);1119 const param = llvm_func.getParam(llvm_arg_i);
1120 llvm_arg_i += 1;1120 llvm_arg_i += 1;
...@@ -1132,7 +1132,7 @@ pub const Object = struct {...@@ -1132,7 +1132,7 @@ pub const Object = struct {
1132 }1132 }
1133 },1133 },
1134 .i32_array, .i64_array => {1134 .i32_array, .i64_array => {
1135 const param_ty = fn_info.param_types[it.zig_index - 1].toType();1135 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
1136 const param_llvm_ty = try o.lowerType(param_ty);1136 const param_llvm_ty = try o.lowerType(param_ty);
1137 const param = llvm_func.getParam(llvm_arg_i);1137 const param = llvm_func.getParam(llvm_arg_i);
1138 llvm_arg_i += 1;1138 llvm_arg_i += 1;
...@@ -1168,7 +1168,7 @@ pub const Object = struct {...@@ -1168,7 +1168,7 @@ pub const Object = struct {
1168 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);1168 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
1169 const subprogram = dib.createFunction(1169 const subprogram = dib.createFunction(
1170 di_file.?.toScope(),1170 di_file.?.toScope(),
1171 mod.intern_pool.stringToSlice(decl.name),1171 ip.stringToSlice(decl.name),
1172 llvm_func.getValueName(),1172 llvm_func.getValueName(),
1173 di_file.?,1173 di_file.?,
1174 line_number,1174 line_number,
...@@ -1460,6 +1460,7 @@ pub const Object = struct {...@@ -1460,6 +1460,7 @@ pub const Object = struct {
1460 const target = o.target;1460 const target = o.target;
1461 const dib = o.di_builder.?;1461 const dib = o.di_builder.?;
1462 const mod = o.module;1462 const mod = o.module;
1463 const ip = &mod.intern_pool;
1463 switch (ty.zigTypeTag(mod)) {1464 switch (ty.zigTypeTag(mod)) {
1464 .Void, .NoReturn => {1465 .Void, .NoReturn => {
1465 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);1466 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
...@@ -1492,7 +1493,6 @@ pub const Object = struct {...@@ -1492,7 +1493,6 @@ pub const Object = struct {
1492 return enum_di_ty;1493 return enum_di_ty;
1493 }1494 }
14941495
1495 const ip = &mod.intern_pool;
1496 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;1496 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
14971497
1498 const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);1498 const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);
...@@ -1518,7 +1518,7 @@ pub const Object = struct {...@@ -1518,7 +1518,7 @@ pub const Object = struct {
1518 if (@sizeOf(usize) == @sizeOf(u64)) {1518 if (@sizeOf(usize) == @sizeOf(u64)) {
1519 enumerators[i] = dib.createEnumerator2(1519 enumerators[i] = dib.createEnumerator2(
1520 field_name_z,1520 field_name_z,
1521 @as(c_uint, @intCast(bigint.limbs.len)),1521 @intCast(bigint.limbs.len),
1522 bigint.limbs.ptr,1522 bigint.limbs.ptr,
1523 int_info.bits,1523 int_info.bits,
1524 int_info.signedness == .unsigned,1524 int_info.signedness == .unsigned,
...@@ -2320,8 +2320,8 @@ pub const Object = struct {...@@ -2320,8 +2320,8 @@ pub const Object = struct {
2320 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));2320 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2321 }2321 }
23222322
2323 for (0..mod.typeToFunc(ty).?.param_types.len) |i| {2323 for (0..fn_info.param_types.len) |i| {
2324 const param_ty = mod.typeToFunc(ty).?.param_types[i].toType();2324 const param_ty = fn_info.param_types.get(ip)[i].toType();
2325 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;2325 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
23262326
2327 if (isByRef(param_ty, mod)) {2327 if (isByRef(param_ty, mod)) {
...@@ -2475,9 +2475,10 @@ pub const Object = struct {...@@ -2475,9 +2475,10 @@ pub const Object = struct {
2475 const fn_type = try o.lowerType(zig_fn_type);2475 const fn_type = try o.lowerType(zig_fn_type);
24762476
2477 const fqn = try decl.getFullyQualifiedName(mod);2477 const fqn = try decl.getFullyQualifiedName(mod);
2478 const ip = &mod.intern_pool;
24782479
2479 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);2480 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
2480 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(mod.intern_pool.stringToSlice(fqn), fn_type, llvm_addrspace);2481 const llvm_fn = o.llvm_module.addFunctionInAddressSpace(ip.stringToSlice(fqn), fn_type, llvm_addrspace);
2481 gop.value_ptr.* = llvm_fn;2482 gop.value_ptr.* = llvm_fn;
24822483
2483 const is_extern = decl.isExtern(mod);2484 const is_extern = decl.isExtern(mod);
...@@ -2486,8 +2487,8 @@ pub const Object = struct {...@@ -2486,8 +2487,8 @@ pub const Object = struct {
2486 llvm_fn.setUnnamedAddr(.True);2487 llvm_fn.setUnnamedAddr(.True);
2487 } else {2488 } else {
2488 if (target.isWasm()) {2489 if (target.isWasm()) {
2489 o.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name));2490 o.addFnAttrString(llvm_fn, "wasm-import-name", ip.stringToSlice(decl.name));
2490 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {2491 if (ip.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
2491 if (!std.mem.eql(u8, lib_name, "c")) {2492 if (!std.mem.eql(u8, lib_name, "c")) {
2492 o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);2493 o.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
2493 }2494 }
...@@ -2546,13 +2547,13 @@ pub const Object = struct {...@@ -2546,13 +2547,13 @@ pub const Object = struct {
2546 while (it.next()) |lowering| switch (lowering) {2547 while (it.next()) |lowering| switch (lowering) {
2547 .byval => {2548 .byval => {
2548 const param_index = it.zig_index - 1;2549 const param_index = it.zig_index - 1;
2549 const param_ty = fn_info.param_types[param_index].toType();2550 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
2550 if (!isByRef(param_ty, mod)) {2551 if (!isByRef(param_ty, mod)) {
2551 o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);2552 o.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
2552 }2553 }
2553 },2554 },
2554 .byref => {2555 .byref => {
2555 const param_ty = fn_info.param_types[it.zig_index - 1];2556 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1];
2556 const param_llvm_ty = try o.lowerType(param_ty.toType());2557 const param_llvm_ty = try o.lowerType(param_ty.toType());
2557 const alignment = param_ty.toType().abiAlignment(mod);2558 const alignment = param_ty.toType().abiAlignment(mod);
2558 o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);2559 o.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
...@@ -3031,6 +3032,7 @@ pub const Object = struct {...@@ -3031,6 +3032,7 @@ pub const Object = struct {
30313032
3032 fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {3033 fn lowerTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type {
3033 const mod = o.module;3034 const mod = o.module;
3035 const ip = &mod.intern_pool;
3034 const fn_info = mod.typeToFunc(fn_ty).?;3036 const fn_info = mod.typeToFunc(fn_ty).?;
3035 const llvm_ret_ty = try lowerFnRetTy(o, fn_info);3037 const llvm_ret_ty = try lowerFnRetTy(o, fn_info);
30363038
...@@ -3052,19 +3054,19 @@ pub const Object = struct {...@@ -3052,19 +3054,19 @@ pub const Object = struct {
3052 while (it.next()) |lowering| switch (lowering) {3054 while (it.next()) |lowering| switch (lowering) {
3053 .no_bits => continue,3055 .no_bits => continue,
3054 .byval => {3056 .byval => {
3055 const param_ty = fn_info.param_types[it.zig_index - 1].toType();3057 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3056 try llvm_params.append(try o.lowerType(param_ty));3058 try llvm_params.append(try o.lowerType(param_ty));
3057 },3059 },
3058 .byref, .byref_mut => {3060 .byref, .byref_mut => {
3059 try llvm_params.append(o.context.pointerType(0));3061 try llvm_params.append(o.context.pointerType(0));
3060 },3062 },
3061 .abi_sized_int => {3063 .abi_sized_int => {
3062 const param_ty = fn_info.param_types[it.zig_index - 1].toType();3064 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3063 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));3065 const abi_size = @as(c_uint, @intCast(param_ty.abiSize(mod)));
3064 try llvm_params.append(o.context.intType(abi_size * 8));3066 try llvm_params.append(o.context.intType(abi_size * 8));
3065 },3067 },
3066 .slice => {3068 .slice => {
3067 const param_ty = fn_info.param_types[it.zig_index - 1].toType();3069 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3068 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)3070 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
3069 param_ty.optionalChild(mod).slicePtrFieldType(mod)3071 param_ty.optionalChild(mod).slicePtrFieldType(mod)
3070 else3072 else
...@@ -3083,7 +3085,7 @@ pub const Object = struct {...@@ -3083,7 +3085,7 @@ pub const Object = struct {
3083 try llvm_params.append(o.context.intType(16));3085 try llvm_params.append(o.context.intType(16));
3084 },3086 },
3085 .float_array => |count| {3087 .float_array => |count| {
3086 const param_ty = fn_info.param_types[it.zig_index - 1].toType();3088 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
3087 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);3089 const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
3088 const field_count = @as(c_uint, @intCast(count));3090 const field_count = @as(c_uint, @intCast(count));
3089 const arr_ty = float_ty.arrayType(field_count);3091 const arr_ty = float_ty.arrayType(field_count);
...@@ -3137,8 +3139,7 @@ pub const Object = struct {...@@ -3137,8 +3139,7 @@ pub const Object = struct {
3137 return llvm_type.getUndef();3139 return llvm_type.getUndef();
3138 }3140 }
31393141
3140 const val_key = mod.intern_pool.indexToKey(tv.val.toIntern());3142 switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
3141 switch (val_key) {
3142 .int_type,3143 .int_type,
3143 .ptr_type,3144 .ptr_type,
3144 .array_type,3145 .array_type,
...@@ -3175,12 +3176,14 @@ pub const Object = struct {...@@ -3175,12 +3176,14 @@ pub const Object = struct {
3175 .enum_literal,3176 .enum_literal,
3176 .empty_enum_value,3177 .empty_enum_value,
3177 => unreachable, // non-runtime values3178 => unreachable, // non-runtime values
3178 .extern_func, .func => {3179 .extern_func => |extern_func| {
3179 const fn_decl_index = switch (val_key) {3180 const fn_decl_index = extern_func.decl;
3180 .extern_func => |extern_func| extern_func.decl,3181 const fn_decl = mod.declPtr(fn_decl_index);
3181 .func => |func| mod.funcPtr(func.index).owner_decl,3182 try mod.markDeclAlive(fn_decl);
3182 else => unreachable,3183 return o.resolveLlvmFunction(fn_decl_index);
3183 };3184 },
3185 .func => |func| {
3186 const fn_decl_index = func.owner_decl;
3184 const fn_decl = mod.declPtr(fn_decl_index);3187 const fn_decl = mod.declPtr(fn_decl_index);
3185 try mod.markDeclAlive(fn_decl);3188 try mod.markDeclAlive(fn_decl);
3186 return o.resolveLlvmFunction(fn_decl_index);3189 return o.resolveLlvmFunction(fn_decl_index);
...@@ -4598,6 +4601,7 @@ pub const FuncGen = struct {...@@ -4598,6 +4601,7 @@ pub const FuncGen = struct {
4598 const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));4601 const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]));
4599 const o = self.dg.object;4602 const o = self.dg.object;
4600 const mod = o.module;4603 const mod = o.module;
4604 const ip = &mod.intern_pool;
4601 const callee_ty = self.typeOf(pl_op.operand);4605 const callee_ty = self.typeOf(pl_op.operand);
4602 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {4606 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
4603 .Fn => callee_ty,4607 .Fn => callee_ty,
...@@ -4801,14 +4805,14 @@ pub const FuncGen = struct {...@@ -4801,14 +4805,14 @@ pub const FuncGen = struct {
4801 while (it.next()) |lowering| switch (lowering) {4805 while (it.next()) |lowering| switch (lowering) {
4802 .byval => {4806 .byval => {
4803 const param_index = it.zig_index - 1;4807 const param_index = it.zig_index - 1;
4804 const param_ty = fn_info.param_types[param_index].toType();4808 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
4805 if (!isByRef(param_ty, mod)) {4809 if (!isByRef(param_ty, mod)) {
4806 o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);4810 o.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
4807 }4811 }
4808 },4812 },
4809 .byref => {4813 .byref => {
4810 const param_index = it.zig_index - 1;4814 const param_index = it.zig_index - 1;
4811 const param_ty = fn_info.param_types[param_index].toType();4815 const param_ty = fn_info.param_types.get(ip)[param_index].toType();
4812 const param_llvm_ty = try o.lowerType(param_ty);4816 const param_llvm_ty = try o.lowerType(param_ty);
4813 const alignment = param_ty.abiAlignment(mod);4817 const alignment = param_ty.abiAlignment(mod);
4814 o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);4818 o.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
...@@ -4828,7 +4832,7 @@ pub const FuncGen = struct {...@@ -4828,7 +4832,7 @@ pub const FuncGen = struct {
48284832
4829 .slice => {4833 .slice => {
4830 assert(!it.byval_attr);4834 assert(!it.byval_attr);
4831 const param_ty = fn_info.param_types[it.zig_index - 1].toType();4835 const param_ty = fn_info.param_types.get(ip)[it.zig_index - 1].toType();
4832 const ptr_info = param_ty.ptrInfo(mod);4836 const ptr_info = param_ty.ptrInfo(mod);
4833 const llvm_arg_i = it.llvm_index - 2;4837 const llvm_arg_i = it.llvm_index - 2;
48344838
...@@ -4930,7 +4934,7 @@ pub const FuncGen = struct {...@@ -4930,7 +4934,7 @@ pub const FuncGen = struct {
4930 fg.context.pointerType(0).constNull(),4934 fg.context.pointerType(0).constNull(),
4931 null_opt_addr_global,4935 null_opt_addr_global,
4932 };4936 };
4933 const panic_func = mod.funcPtrUnwrap(mod.panic_func_index).?;4937 const panic_func = mod.funcInfo(mod.panic_func_index);
4934 const panic_decl = mod.declPtr(panic_func.owner_decl);4938 const panic_decl = mod.declPtr(panic_func.owner_decl);
4935 const fn_info = mod.typeToFunc(panic_decl.ty).?;4939 const fn_info = mod.typeToFunc(panic_decl.ty).?;
4936 const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);4940 const panic_global = try o.resolveLlvmFunction(panic_func.owner_decl);
...@@ -6030,7 +6034,7 @@ pub const FuncGen = struct {...@@ -6030,7 +6034,7 @@ pub const FuncGen = struct {
6030 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;6034 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
60316035
6032 const mod = o.module;6036 const mod = o.module;
6033 const func = mod.funcPtr(ty_fn.func);6037 const func = mod.funcInfo(ty_fn.func);
6034 const decl_index = func.owner_decl;6038 const decl_index = func.owner_decl;
6035 const decl = mod.declPtr(decl_index);6039 const decl = mod.declPtr(decl_index);
6036 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);6040 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
...@@ -6039,7 +6043,7 @@ pub const FuncGen = struct {...@@ -6039,7 +6043,7 @@ pub const FuncGen = struct {
6039 const cur_debug_location = self.builder.getCurrentDebugLocation2();6043 const cur_debug_location = self.builder.getCurrentDebugLocation2();
60406044
6041 try self.dbg_inlined.append(self.gpa, .{6045 try self.dbg_inlined.append(self.gpa, .{
6042 .loc = @as(*llvm.DILocation, @ptrCast(cur_debug_location)),6046 .loc = @ptrCast(cur_debug_location),
6043 .scope = self.di_scope.?,6047 .scope = self.di_scope.?,
6044 .base_line = self.base_line,6048 .base_line = self.base_line,
6045 });6049 });
...@@ -6090,8 +6094,7 @@ pub const FuncGen = struct {...@@ -6090,8 +6094,7 @@ pub const FuncGen = struct {
6090 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;6094 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
60916095
6092 const mod = o.module;6096 const mod = o.module;
6093 const func = mod.funcPtr(ty_fn.func);6097 const decl = mod.funcOwnerDeclPtr(ty_fn.func);
6094 const decl = mod.declPtr(func.owner_decl);
6095 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);6098 const di_file = try o.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
6096 self.di_file = di_file;6099 self.di_file = di_file;
6097 const old = self.dbg_inlined.pop();6100 const old = self.dbg_inlined.pop();
...@@ -8137,12 +8140,13 @@ pub const FuncGen = struct {...@@ -8137,12 +8140,13 @@ pub const FuncGen = struct {
8137 }8140 }
81388141
8139 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;8142 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);
8141 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;8145 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
8142 const lbrace_col = func.lbrace_column + 1;8146 const lbrace_col = func.lbrace_column + 1;
8143 const di_local_var = dib.createParameterVariable(8147 const di_local_var = dib.createParameterVariable(
8144 self.di_scope.?,8148 self.di_scope.?,
8145 func.getParamName(mod, src_index).ptr, // TODO test 0 bit args8149 mod.getParamName(func_index, src_index).ptr, // TODO test 0 bit args
8146 self.di_file.?,8150 self.di_file.?,
8147 lbrace_line,8151 lbrace_line,
8148 try o.lowerDebugType(inst_ty, .full),8152 try o.lowerDebugType(inst_ty, .full),
...@@ -10888,13 +10892,17 @@ const ParamTypeIterator = struct {...@@ -10888,13 +10892,17 @@ const ParamTypeIterator = struct {
1088810892
10889 pub fn next(it: *ParamTypeIterator) ?Lowering {10893 pub fn next(it: *ParamTypeIterator) ?Lowering {
10890 if (it.zig_index >= it.fn_info.param_types.len) return null;10894 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];
10892 it.byval_attr = false;10898 it.byval_attr = false;
10893 return nextInner(it, ty.toType());10899 return nextInner(it, ty.toType());
10894 }10900 }
1089510901
10896 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.10902 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
10897 pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) ?Lowering {10903 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;
10898 if (it.zig_index >= it.fn_info.param_types.len) {10906 if (it.zig_index >= it.fn_info.param_types.len) {
10899 if (it.zig_index >= args.len) {10907 if (it.zig_index >= args.len) {
10900 return null;10908 return null;
...@@ -10902,7 +10910,7 @@ const ParamTypeIterator = struct {...@@ -10902,7 +10910,7 @@ const ParamTypeIterator = struct {
10902 return nextInner(it, fg.typeOf(args[it.zig_index]));10910 return nextInner(it, fg.typeOf(args[it.zig_index]));
10903 }10911 }
10904 } else {10912 } 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());
10906 }10914 }
10907 }10915 }
1090810916
src/codegen/spirv.zig+12-8
...@@ -238,7 +238,7 @@ pub const DeclGen = struct {...@@ -238,7 +238,7 @@ pub const DeclGen = struct {
238 if (ty.zigTypeTag(mod) == .Fn) {238 if (ty.zigTypeTag(mod) == .Fn) {
239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
240 .extern_func => |extern_func| extern_func.decl,240 .extern_func => |extern_func| extern_func.decl,
241 .func => |func| mod.funcPtr(func.index).owner_decl,241 .func => |func| func.owner_decl,
242 else => unreachable,242 else => unreachable,
243 };243 };
244 const spv_decl_index = try self.resolveDecl(fn_decl_index);244 const spv_decl_index = try self.resolveDecl(fn_decl_index);
...@@ -255,13 +255,14 @@ pub const DeclGen = struct {...@@ -255,13 +255,14 @@ pub const DeclGen = struct {
255 /// Fetch or allocate a result id for decl index. This function also marks the decl as alive.255 /// Fetch or allocate a result id for decl index. This function also marks the decl as alive.
256 /// Note: Function does not actually generate the decl.256 /// Note: Function does not actually generate the decl.
257 fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {257 fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
258 const decl = self.module.declPtr(decl_index);258 const mod = self.module;
259 try self.module.markDeclAlive(decl);259 const decl = mod.declPtr(decl_index);
260 try mod.markDeclAlive(decl);
260261
261 const entry = try self.decl_link.getOrPut(decl_index);262 const entry = try self.decl_link.getOrPut(decl_index);
262 if (!entry.found_existing) {263 if (!entry.found_existing) {
263 // TODO: Extern fn?264 // TODO: Extern fn?
264 const kind: SpvModule.DeclKind = if (decl.val.getFunctionIndex(self.module) != .none)265 const kind: SpvModule.DeclKind = if (decl.val.isFuncBody(mod))
265 .func266 .func
266 else267 else
267 .global;268 .global;
...@@ -1268,6 +1269,7 @@ pub const DeclGen = struct {...@@ -1268,6 +1269,7 @@ pub const DeclGen = struct {
1268 },1269 },
1269 .Fn => switch (repr) {1270 .Fn => switch (repr) {
1270 .direct => {1271 .direct => {
1272 const ip = &mod.intern_pool;
1271 const fn_info = mod.typeToFunc(ty).?;1273 const fn_info = mod.typeToFunc(ty).?;
1272 // TODO: Put this somewhere in Sema.zig1274 // TODO: Put this somewhere in Sema.zig
1273 if (fn_info.is_var_args)1275 if (fn_info.is_var_args)
...@@ -1275,8 +1277,8 @@ pub const DeclGen = struct {...@@ -1275,8 +1277,8 @@ pub const DeclGen = struct {
12751277
1276 const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);1278 const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);
1277 defer self.gpa.free(param_ty_refs);1279 defer self.gpa.free(param_ty_refs);
1278 for (param_ty_refs, 0..) |*param_type, i| {1280 for (param_ty_refs, fn_info.param_types.get(ip)) |*param_type, fn_param_type| {
1279 param_type.* = try self.resolveType(fn_info.param_types[i].toType(), .direct);1281 param_type.* = try self.resolveType(fn_param_type.toType(), .direct);
1280 }1282 }
1281 const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct);1283 const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct);
12821284
...@@ -1576,6 +1578,7 @@ pub const DeclGen = struct {...@@ -1576,6 +1578,7 @@ pub const DeclGen = struct {
15761578
1577 fn genDecl(self: *DeclGen) !void {1579 fn genDecl(self: *DeclGen) !void {
1578 const mod = self.module;1580 const mod = self.module;
1581 const ip = &mod.intern_pool;
1579 const decl = mod.declPtr(self.decl_index);1582 const decl = mod.declPtr(self.decl_index);
1580 const spv_decl_index = try self.resolveDecl(self.decl_index);1583 const spv_decl_index = try self.resolveDecl(self.decl_index);
15811584
...@@ -1594,7 +1597,8 @@ pub const DeclGen = struct {...@@ -1594,7 +1597,8 @@ pub const DeclGen = struct {
1594 const fn_info = mod.typeToFunc(decl.ty).?;1597 const fn_info = mod.typeToFunc(decl.ty).?;
15951598
1596 try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);1599 try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
1597 for (fn_info.param_types) |param_type| {1600 for (0..fn_info.param_types.len) |i| {
1601 const param_type = fn_info.param_types.get(ip)[i];
1598 const param_type_id = try self.resolveTypeId(param_type.toType());1602 const param_type_id = try self.resolveTypeId(param_type.toType());
1599 const arg_result_id = self.spv.allocId();1603 const arg_result_id = self.spv.allocId();
1600 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{1604 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
...@@ -1621,7 +1625,7 @@ pub const DeclGen = struct {...@@ -1621,7 +1625,7 @@ pub const DeclGen = struct {
1621 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});1625 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
1622 try self.spv.addFunction(spv_decl_index, self.func);1626 try self.spv.addFunction(spv_decl_index, self.func);
16231627
1624 const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(self.module));1628 const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module));
16251629
1626 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{1630 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
1627 .target = decl_id,1631 .target = decl_id,
src/link.zig+2-1
...@@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig");...@@ -16,6 +16,7 @@ const Compilation = @import("Compilation.zig");
16const LibCInstallation = @import("libc_installation.zig").LibCInstallation;16const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
17const Liveness = @import("Liveness.zig");17const Liveness = @import("Liveness.zig");
18const Module = @import("Module.zig");18const Module = @import("Module.zig");
19const InternPool = @import("InternPool.zig");
19const Package = @import("Package.zig");20const Package = @import("Package.zig");
20const Type = @import("type.zig").Type;21const Type = @import("type.zig").Type;
21const TypedValue = @import("TypedValue.zig");22const TypedValue = @import("TypedValue.zig");
...@@ -562,7 +563,7 @@ pub const File = struct {...@@ -562,7 +563,7 @@ pub const File = struct {
562 }563 }
563564
564 /// May be called before or after updateDeclExports for any given Decl.565 /// May be called before or after updateDeclExports for any given Decl.
565 pub fn updateFunc(base: *File, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) UpdateDeclError!void {566 pub fn updateFunc(base: *File, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
566 if (build_options.only_c) {567 if (build_options.only_c) {
567 assert(base.tag == .c);568 assert(base.tag == .c);
568 return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness);569 return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness);
src/link/C.zig+2-2
...@@ -88,13 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {...@@ -88,13 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
88 }88 }
89}89}
9090
91pub fn updateFunc(self: *C, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {91pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
92 const tracy = trace(@src());92 const tracy = trace(@src());
93 defer tracy.end();93 defer tracy.end();
9494
95 const gpa = self.base.allocator;95 const gpa = self.base.allocator;
9696
97 const func = module.funcPtr(func_index);97 const func = module.funcInfo(func_index);
98 const decl_index = func.owner_decl;98 const decl_index = func.owner_decl;
99 const gop = try self.decl_table.getOrPut(gpa, decl_index);99 const gop = try self.decl_table.getOrPut(gpa, decl_index);
100 if (!gop.found_existing) {100 if (!gop.found_existing) {
src/link/Coff.zig+3-3
...@@ -1032,7 +1032,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {...@@ -1032,7 +1032,7 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
1032 self.getAtomPtr(atom_index).sym_index = 0;1032 self.getAtomPtr(atom_index).sym_index = 0;
1033}1033}
10341034
1035pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {1035pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
1036 if (build_options.skip_non_native and builtin.object_format != .coff) {1036 if (build_options.skip_non_native and builtin.object_format != .coff) {
1037 @panic("Attempted to compile for object format that was disabled by build configuration");1037 @panic("Attempted to compile for object format that was disabled by build configuration");
1038 }1038 }
...@@ -1044,7 +1044,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: A...@@ -1044,7 +1044,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: A
1044 const tracy = trace(@src());1044 const tracy = trace(@src());
1045 defer tracy.end();1045 defer tracy.end();
10461046
1047 const func = mod.funcPtr(func_index);1047 const func = mod.funcInfo(func_index);
1048 const decl_index = func.owner_decl;1048 const decl_index = func.owner_decl;
1049 const decl = mod.declPtr(decl_index);1049 const decl = mod.declPtr(decl_index);
10501050
...@@ -1424,7 +1424,7 @@ pub fn updateDeclExports(...@@ -1424,7 +1424,7 @@ pub fn updateDeclExports(
1424 // detect the default subsystem.1424 // detect the default subsystem.
1425 for (exports) |exp| {1425 for (exports) |exp| {
1426 const exported_decl = mod.declPtr(exp.exported_decl);1426 const exported_decl = mod.declPtr(exp.exported_decl);
1427 if (exported_decl.getOwnedFunctionIndex(mod) == .none) continue;1427 if (exported_decl.getOwnedFunctionIndex() == .none) continue;
1428 const winapi_cc = switch (self.base.options.target.cpu.arch) {1428 const winapi_cc = switch (self.base.options.target.cpu.arch) {
1429 .x86 => std.builtin.CallingConvention.Stdcall,1429 .x86 => std.builtin.CallingConvention.Stdcall,
1430 else => std.builtin.CallingConvention.C,1430 else => std.builtin.CallingConvention.C,
src/link/Elf.zig+2-2
...@@ -2575,7 +2575,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s...@@ -2575,7 +2575,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
2575 return local_sym;2575 return local_sym;
2576}2576}
25772577
2578pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {2578pub fn updateFunc(self: *Elf, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
2579 if (build_options.skip_non_native and builtin.object_format != .elf) {2579 if (build_options.skip_non_native and builtin.object_format != .elf) {
2580 @panic("Attempted to compile for object format that was disabled by build configuration");2580 @panic("Attempted to compile for object format that was disabled by build configuration");
2581 }2581 }
...@@ -2586,7 +2586,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Ai...@@ -2586,7 +2586,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Ai
2586 const tracy = trace(@src());2586 const tracy = trace(@src());
2587 defer tracy.end();2587 defer tracy.end();
25882588
2589 const func = mod.funcPtr(func_index);2589 const func = mod.funcInfo(func_index);
2590 const decl_index = func.owner_decl;2590 const decl_index = func.owner_decl;
2591 const decl = mod.declPtr(decl_index);2591 const decl = mod.declPtr(decl_index);
25922592
src/link/MachO.zig+2-2
...@@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {...@@ -1845,7 +1845,7 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
1845 self.markRelocsDirtyByTarget(target);1845 self.markRelocsDirtyByTarget(target);
1846}1846}
18471847
1848pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {1848pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
1849 if (build_options.skip_non_native and builtin.object_format != .macho) {1849 if (build_options.skip_non_native and builtin.object_format != .macho) {
1850 @panic("Attempted to compile for object format that was disabled by build configuration");1850 @panic("Attempted to compile for object format that was disabled by build configuration");
1851 }1851 }
...@@ -1855,7 +1855,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air:...@@ -1855,7 +1855,7 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air:
1855 const tracy = trace(@src());1855 const tracy = trace(@src());
1856 defer tracy.end();1856 defer tracy.end();
18571857
1858 const func = mod.funcPtr(func_index);1858 const func = mod.funcInfo(func_index);
1859 const decl_index = func.owner_decl;1859 const decl_index = func.owner_decl;
1860 const decl = mod.declPtr(decl_index);1860 const decl = mod.declPtr(decl_index);
18611861
src/link/NvPtx.zig+2-1
...@@ -13,6 +13,7 @@ const assert = std.debug.assert;...@@ -13,6 +13,7 @@ const assert = std.debug.assert;
13const log = std.log.scoped(.link);13const log = std.log.scoped(.link);
1414
15const Module = @import("../Module.zig");15const Module = @import("../Module.zig");
16const InternPool = @import("../InternPool.zig");
16const Compilation = @import("../Compilation.zig");17const Compilation = @import("../Compilation.zig");
17const link = @import("../link.zig");18const link = @import("../link.zig");
18const trace = @import("../tracy.zig").trace;19const trace = @import("../tracy.zig").trace;
...@@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void {...@@ -68,7 +69,7 @@ pub fn deinit(self: *NvPtx) void {
68 self.base.allocator.free(self.ptx_file_name);69 self.base.allocator.free(self.ptx_file_name);
69}70}
7071
71pub fn updateFunc(self: *NvPtx, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {72pub fn updateFunc(self: *NvPtx, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
72 if (!build_options.have_llvm) return;73 if (!build_options.have_llvm) return;
73 try self.llvm_object.updateFunc(module, func_index, air, liveness);74 try self.llvm_object.updateFunc(module, func_index, air, liveness);
74}75}
src/link/Plan9.zig+4-3
...@@ -4,6 +4,7 @@...@@ -4,6 +4,7 @@
4const Plan9 = @This();4const Plan9 = @This();
5const link = @import("../link.zig");5const link = @import("../link.zig");
6const Module = @import("../Module.zig");6const Module = @import("../Module.zig");
7const InternPool = @import("../InternPool.zig");
7const Compilation = @import("../Compilation.zig");8const Compilation = @import("../Compilation.zig");
8const aout = @import("Plan9/aout.zig");9const aout = @import("Plan9/aout.zig");
9const codegen = @import("../codegen.zig");10const codegen = @import("../codegen.zig");
...@@ -344,12 +345,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi...@@ -344,12 +345,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi
344 }345 }
345}346}
346347
347pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {348pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
348 if (build_options.skip_non_native and builtin.object_format != .plan9) {349 if (build_options.skip_non_native and builtin.object_format != .plan9) {
349 @panic("Attempted to compile for object format that was disabled by build configuration");350 @panic("Attempted to compile for object format that was disabled by build configuration");
350 }351 }
351352
352 const func = mod.funcPtr(func_index);353 const func = mod.funcInfo(func_index);
353 const decl_index = func.owner_decl;354 const decl_index = func.owner_decl;
354 const decl = mod.declPtr(decl_index);355 const decl = mod.declPtr(decl_index);
355 self.freeUnnamedConsts(decl_index);356 self.freeUnnamedConsts(decl_index);
...@@ -908,7 +909,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {...@@ -908,7 +909,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
908 // in the deleteUnusedDecl function.909 // in the deleteUnusedDecl function.
909 const mod = self.base.options.module.?;910 const mod = self.base.options.module.?;
910 const decl = mod.declPtr(decl_index);911 const decl = mod.declPtr(decl_index);
911 const is_fn = decl.val.getFunctionIndex(mod) != .none;912 const is_fn = decl.val.isFuncBody(mod);
912 if (is_fn) {913 if (is_fn) {
913 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;914 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
914 var submap = symidx_and_submap.functions;915 var submap = symidx_and_submap.functions;
src/link/SpirV.zig+4-3
...@@ -29,6 +29,7 @@ const assert = std.debug.assert;...@@ -29,6 +29,7 @@ const assert = std.debug.assert;
29const log = std.log.scoped(.link);29const log = std.log.scoped(.link);
3030
31const Module = @import("../Module.zig");31const Module = @import("../Module.zig");
32const InternPool = @import("../InternPool.zig");
32const Compilation = @import("../Compilation.zig");33const Compilation = @import("../Compilation.zig");
33const link = @import("../link.zig");34const link = @import("../link.zig");
34const codegen = @import("../codegen/spirv.zig");35const codegen = @import("../codegen/spirv.zig");
...@@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void {...@@ -103,12 +104,12 @@ pub fn deinit(self: *SpirV) void {
103 self.decl_link.deinit();104 self.decl_link.deinit();
104}105}
105106
106pub fn updateFunc(self: *SpirV, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {107pub fn updateFunc(self: *SpirV, module: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
107 if (build_options.skip_non_native) {108 if (build_options.skip_non_native) {
108 @panic("Attempted to compile for architecture that was disabled by build configuration");109 @panic("Attempted to compile for architecture that was disabled by build configuration");
109 }110 }
110111
111 const func = module.funcPtr(func_index);112 const func = module.funcInfo(func_index);
112113
113 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);114 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
114 defer decl_gen.deinit();115 defer decl_gen.deinit();
...@@ -138,7 +139,7 @@ pub fn updateDeclExports(...@@ -138,7 +139,7 @@ pub fn updateDeclExports(
138 exports: []const *Module.Export,139 exports: []const *Module.Export,
139) !void {140) !void {
140 const decl = mod.declPtr(decl_index);141 const decl = mod.declPtr(decl_index);
141 if (decl.val.getFunctionIndex(mod) != .none and decl.ty.fnCallingConvention(mod) == .Kernel) {142 if (decl.val.isFuncBody(mod) and decl.ty.fnCallingConvention(mod) == .Kernel) {
142 // TODO: Unify with resolveDecl in spirv.zig.143 // TODO: Unify with resolveDecl in spirv.zig.
143 const entry = try self.decl_link.getOrPut(decl_index);144 const entry = try self.decl_link.getOrPut(decl_index);
144 if (!entry.found_existing) {145 if (!entry.found_existing) {
src/link/Wasm.zig+3-2
...@@ -12,6 +12,7 @@ const log = std.log.scoped(.link);...@@ -12,6 +12,7 @@ const log = std.log.scoped(.link);
12pub const Atom = @import("Wasm/Atom.zig");12pub const Atom = @import("Wasm/Atom.zig");
13const Dwarf = @import("Dwarf.zig");13const Dwarf = @import("Dwarf.zig");
14const Module = @import("../Module.zig");14const Module = @import("../Module.zig");
15const InternPool = @import("../InternPool.zig");
15const Compilation = @import("../Compilation.zig");16const Compilation = @import("../Compilation.zig");
16const CodeGen = @import("../arch/wasm/CodeGen.zig");17const CodeGen = @import("../arch/wasm/CodeGen.zig");
17const codegen = @import("../codegen.zig");18const codegen = @import("../codegen.zig");
...@@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {...@@ -1338,7 +1339,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
1338 return index;1339 return index;
1339}1340}
13401341
1341pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {1342pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air: Air, liveness: Liveness) !void {
1342 if (build_options.skip_non_native and builtin.object_format != .wasm) {1343 if (build_options.skip_non_native and builtin.object_format != .wasm) {
1343 @panic("Attempted to compile for object format that was disabled by build configuration");1344 @panic("Attempted to compile for object format that was disabled by build configuration");
1344 }1345 }
...@@ -1349,7 +1350,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: A...@@ -1349,7 +1350,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: A
1349 const tracy = trace(@src());1350 const tracy = trace(@src());
1350 defer tracy.end();1351 defer tracy.end();
13511352
1352 const func = mod.funcPtr(func_index);1353 const func = mod.funcInfo(func_index);
1353 const decl_index = func.owner_decl;1354 const decl_index = func.owner_decl;
1354 const decl = mod.declPtr(decl_index);1355 const decl = mod.declPtr(decl_index);
1355 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);1356 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
src/print_air.zig+1-1
...@@ -665,7 +665,7 @@ const Writer = struct {...@@ -665,7 +665,7 @@ const Writer = struct {
665 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {665 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
666 const ty_fn = w.air.instructions.items(.data)[inst].ty_fn;666 const ty_fn = w.air.instructions.items(.data)[inst].ty_fn;
667 const func_index = ty_fn.func;667 const func_index = ty_fn.func;
668 const owner_decl = w.module.declPtr(w.module.funcPtr(func_index).owner_decl);668 const owner_decl = w.module.funcOwnerDeclPtr(func_index);
669 try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});669 try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});
670 }670 }
671671
src/type.zig+4-3
...@@ -255,7 +255,7 @@ pub const Type = struct {...@@ -255,7 +255,7 @@ pub const Type = struct {
255 const func = ies.func;255 const func = ies.func;
256256
257 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");257 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
258 const owner_decl = mod.declPtr(mod.funcPtr(func).owner_decl);258 const owner_decl = mod.funcOwnerDeclPtr(func);
259 try owner_decl.renderFullyQualifiedName(mod, writer);259 try owner_decl.renderFullyQualifiedName(mod, writer);
260 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");260 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
261 },261 },
...@@ -367,7 +367,8 @@ pub const Type = struct {...@@ -367,7 +367,8 @@ pub const Type = struct {
367 try writer.writeAll("noinline ");367 try writer.writeAll("noinline ");
368 }368 }
369 try writer.writeAll("fn(");369 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| {
371 if (i != 0) try writer.writeAll(", ");372 if (i != 0) try writer.writeAll(", ");
372 if (std.math.cast(u5, i)) |index| {373 if (std.math.cast(u5, i)) |index| {
373 if (fn_info.paramIsComptime(index)) {374 if (fn_info.paramIsComptime(index)) {
...@@ -384,7 +385,7 @@ pub const Type = struct {...@@ -384,7 +385,7 @@ pub const Type = struct {
384 }385 }
385 }386 }
386 if (fn_info.is_var_args) {387 if (fn_info.is_var_args) {
387 if (fn_info.param_types.len != 0) {388 if (param_types.len != 0) {
388 try writer.writeAll(", ");389 try writer.writeAll(", ");
389 }390 }
390 try writer.writeAll("...");391 try writer.writeAll("...");
src/value.zig+8-5
...@@ -473,12 +473,15 @@ pub const Value = struct {...@@ -473,12 +473,15 @@ pub const Value = struct {
473 };473 };
474 }474 }
475475
476 pub fn getFunction(val: Value, mod: *Module) ?*Module.Fn {476 pub fn isFuncBody(val: Value, mod: *Module) bool {
477 return mod.funcPtrUnwrap(val.getFunctionIndex(mod));477 return mod.intern_pool.isFuncBody(val.toIntern());
478 }478 }
479479
480 pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex {480 pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func {
481 return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.toIntern()) else .none;481 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
482 .func => |x| x,
483 else => null,
484 };
482 }485 }
483486
484 pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {487 pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
...@@ -1462,7 +1465,7 @@ pub const Value = struct {...@@ -1462,7 +1465,7 @@ pub const Value = struct {
1462 return switch (mod.intern_pool.indexToKey(val.toIntern())) {1465 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1463 .variable => |variable| variable.decl,1466 .variable => |variable| variable.decl,
1464 .extern_func => |extern_func| extern_func.decl,1467 .extern_func => |extern_func| extern_func.decl,
1465 .func => |func| mod.funcPtr(func.index).owner_decl,1468 .func => |func| func.owner_decl,
1466 .ptr => |ptr| switch (ptr.addr) {1469 .ptr => |ptr| switch (ptr.addr) {
1467 .decl => |decl| decl,1470 .decl => |decl| decl,
1468 .mut_decl => |mut_decl| mut_decl.decl,1471 .mut_decl => |mut_decl| mut_decl.decl,