authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-15 20:09:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:53-07:00
log17882162b3be5542b4e289e5ddc6535a4bb4c6b1
tree678a9762bd5894e487ff808562eba690918c23ba
parent6a9a918fbe4adc23dd7d7573c6f1e499f4be074e

stage2: move function types to InternPool


23 files changed, 821 insertions(+), 791 deletions(-)

lib/std/builtin.zig+1-1
......@@ -143,7 +143,7 @@ pub const Mode = OptimizeMode;
143143
144144/// This data structure is used by the Zig language code generation and
145145/// therefore must be kept in sync with the compiler implementation.
146pub const CallingConvention = enum {
146pub const CallingConvention = enum(u8) {
147147 /// This is the default Zig calling convention used when not using `export` on `fn`
148148 /// and no other calling convention is specified.
149149 Unspecified,
src/Air.zig+3-4
......@@ -845,7 +845,6 @@ pub const Inst = struct {
845845
846846 pub const Ref = enum(u32) {
847847 u1_type = @enumToInt(InternPool.Index.u1_type),
848 u5_type = @enumToInt(InternPool.Index.u5_type),
849848 u8_type = @enumToInt(InternPool.Index.u8_type),
850849 i8_type = @enumToInt(InternPool.Index.i8_type),
851850 u16_type = @enumToInt(InternPool.Index.u16_type),
......@@ -914,8 +913,8 @@ pub const Inst = struct {
914913 zero_u8 = @enumToInt(InternPool.Index.zero_u8),
915914 one = @enumToInt(InternPool.Index.one),
916915 one_usize = @enumToInt(InternPool.Index.one_usize),
917 one_u5 = @enumToInt(InternPool.Index.one_u5),
918 four_u5 = @enumToInt(InternPool.Index.four_u5),
916 one_u8 = @enumToInt(InternPool.Index.one_u8),
917 four_u8 = @enumToInt(InternPool.Index.four_u8),
919918 negative_one = @enumToInt(InternPool.Index.negative_one),
920919 calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c),
921920 calling_convention_inline = @enumToInt(InternPool.Index.calling_convention_inline),
......@@ -1383,7 +1382,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
13831382
13841383 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
13851384 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1386 return callee_ty.fnReturnType();
1385 return callee_ty.fnReturnTypeIp(ip);
13871386 },
13881387
13891388 .slice_elem_val, .ptr_elem_val, .array_elem_val => {
src/InternPool.zig+204-40
......@@ -148,6 +148,7 @@ pub const Key = union(enum) {
148148 union_type: UnionType,
149149 opaque_type: OpaqueType,
150150 enum_type: EnumType,
151 func_type: FuncType,
151152
152153 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
153154 /// via `simple_value` and has a named `Index` tag for it.
......@@ -185,6 +186,13 @@ pub const Key = union(enum) {
185186 /// If zero use pointee_type.abiAlignment()
186187 /// When creating pointer types, if alignment is equal to pointee type
187188 /// abi alignment, this value should be set to 0 instead.
189 ///
190 /// Please don't change this to u32 or u29. If you want to save bits,
191 /// migrate the rest of the codebase to use the `Alignment` type rather
192 /// than using byte units. The LLVM backend can only handle `c_uint`
193 /// byte units; we can emit a semantic analysis error if alignment that
194 /// overflows that amount is attempted to be used, but it shouldn't
195 /// affect the other backends.
188196 alignment: u64 = 0,
189197 /// If this is non-zero it means the pointer points to a sub-byte
190198 /// range of data, which is backed by a "host integer" with this
......@@ -358,6 +366,44 @@ pub const Key = union(enum) {
358366 }
359367 };
360368
369 pub const FuncType = struct {
370 param_types: []Index,
371 return_type: Index,
372 /// Tells whether a parameter is comptime. See `paramIsComptime` helper
373 /// method for accessing this.
374 comptime_bits: u32,
375 /// Tells whether a parameter is noalias. See `paramIsNoalias` helper
376 /// method for accessing this.
377 noalias_bits: u32,
378 /// If zero use default target function code alignment.
379 ///
380 /// Please don't change this to u32 or u29. If you want to save bits,
381 /// migrate the rest of the codebase to use the `Alignment` type rather
382 /// than using byte units. The LLVM backend can only handle `c_uint`
383 /// byte units; we can emit a semantic analysis error if alignment that
384 /// overflows that amount is attempted to be used, but it shouldn't
385 /// affect the other backends.
386 alignment: u64,
387 cc: std.builtin.CallingConvention,
388 is_var_args: bool,
389 is_generic: bool,
390 is_noinline: bool,
391 align_is_generic: bool,
392 cc_is_generic: bool,
393 section_is_generic: bool,
394 addrspace_is_generic: bool,
395
396 pub fn paramIsComptime(self: @This(), i: u5) bool {
397 assert(i < self.param_types.len);
398 return @truncate(u1, self.comptime_bits >> i) != 0;
399 }
400
401 pub fn paramIsNoalias(self: @This(), i: u5) bool {
402 assert(i < self.param_types.len);
403 return @truncate(u1, self.noalias_bits >> i) != 0;
404 }
405 };
406
361407 pub const Int = struct {
362408 ty: Index,
363409 storage: Storage,
......@@ -512,6 +558,18 @@ pub const Key = union(enum) {
512558 for (anon_struct_type.values) |elem| std.hash.autoHash(hasher, elem);
513559 for (anon_struct_type.names) |elem| std.hash.autoHash(hasher, elem);
514560 },
561
562 .func_type => |func_type| {
563 for (func_type.param_types) |param_type| std.hash.autoHash(hasher, param_type);
564 std.hash.autoHash(hasher, func_type.return_type);
565 std.hash.autoHash(hasher, func_type.comptime_bits);
566 std.hash.autoHash(hasher, func_type.noalias_bits);
567 std.hash.autoHash(hasher, func_type.alignment);
568 std.hash.autoHash(hasher, func_type.cc);
569 std.hash.autoHash(hasher, func_type.is_var_args);
570 std.hash.autoHash(hasher, func_type.is_generic);
571 std.hash.autoHash(hasher, func_type.is_noinline);
572 },
515573 }
516574 }
517575
......@@ -670,6 +728,20 @@ pub const Key = union(enum) {
670728 std.mem.eql(Index, a_info.values, b_info.values) and
671729 std.mem.eql(NullTerminatedString, a_info.names, b_info.names);
672730 },
731
732 .func_type => |a_info| {
733 const b_info = b.func_type;
734
735 return std.mem.eql(Index, a_info.param_types, b_info.param_types) and
736 a_info.return_type == b_info.return_type and
737 a_info.comptime_bits == b_info.comptime_bits and
738 a_info.noalias_bits == b_info.noalias_bits and
739 a_info.alignment == b_info.alignment and
740 a_info.cc == b_info.cc and
741 a_info.is_var_args == b_info.is_var_args and
742 a_info.is_generic == b_info.is_generic and
743 a_info.is_noinline == b_info.is_noinline;
744 },
673745 }
674746 }
675747
......@@ -687,6 +759,7 @@ pub const Key = union(enum) {
687759 .opaque_type,
688760 .enum_type,
689761 .anon_struct_type,
762 .func_type,
690763 => .type_type,
691764
692765 inline .ptr,
......@@ -734,7 +807,6 @@ pub const Index = enum(u32) {
734807 pub const last_value: Index = .empty_struct;
735808
736809 u1_type,
737 u5_type,
738810 u8_type,
739811 i8_type,
740812 u16_type,
......@@ -811,10 +883,10 @@ pub const Index = enum(u32) {
811883 one,
812884 /// `1` (usize)
813885 one_usize,
814 /// `1` (u5)
815 one_u5,
816 /// `4` (u5)
817 four_u5,
886 /// `1` (u8)
887 one_u8,
888 /// `4` (u8)
889 four_u8,
818890 /// `-1` (comptime_int)
819891 negative_one,
820892 /// `std.builtin.CallingConvention.C`
......@@ -880,12 +952,6 @@ pub const static_keys = [_]Key{
880952 .bits = 1,
881953 } },
882954
883 // u5_type
884 .{ .int_type = .{
885 .signedness = .unsigned,
886 .bits = 5,
887 } },
888
889955 .{ .int_type = .{
890956 .signedness = .unsigned,
891957 .bits = 8,
......@@ -1074,14 +1140,14 @@ pub const static_keys = [_]Key{
10741140 .storage = .{ .u64 = 1 },
10751141 } },
10761142
1077 // one_u5
1143 // one_u8
10781144 .{ .int = .{
1079 .ty = .u5_type,
1145 .ty = .u8_type,
10801146 .storage = .{ .u64 = 1 },
10811147 } },
1082 // four_u5
1148 // four_u8
10831149 .{ .int = .{
1084 .ty = .u5_type,
1150 .ty = .u8_type,
10851151 .storage = .{ .u64 = 4 },
10861152 } },
10871153 // negative_one
......@@ -1092,12 +1158,12 @@ pub const static_keys = [_]Key{
10921158 // calling_convention_c
10931159 .{ .enum_tag = .{
10941160 .ty = .calling_convention_type,
1095 .int = .one_u5,
1161 .int = .one_u8,
10961162 } },
10971163 // calling_convention_inline
10981164 .{ .enum_tag = .{
10991165 .ty = .calling_convention_type,
1100 .int = .four_u5,
1166 .int = .four_u8,
11011167 } },
11021168
11031169 .{ .simple_value = .void },
......@@ -1181,6 +1247,9 @@ pub const Tag = enum(u8) {
11811247 /// An untagged union type which has a safety tag.
11821248 /// `data` is `Module.Union.Index`.
11831249 type_union_safety,
1250 /// A function body type.
1251 /// `data` is extra index to `TypeFunction`.
1252 type_function,
11841253
11851254 /// Typed `undefined`.
11861255 /// `data` is `Index` of the type.
......@@ -1283,6 +1352,29 @@ pub const Tag = enum(u8) {
12831352 aggregate,
12841353};
12851354
1355/// Trailing:
1356/// 0. param_type: Index for each params_len
1357pub const TypeFunction = struct {
1358 params_len: u32,
1359 return_type: Index,
1360 comptime_bits: u32,
1361 noalias_bits: u32,
1362 flags: Flags,
1363
1364 pub const Flags = packed struct(u32) {
1365 alignment: Alignment,
1366 cc: std.builtin.CallingConvention,
1367 is_var_args: bool,
1368 is_generic: bool,
1369 is_noinline: bool,
1370 align_is_generic: bool,
1371 cc_is_generic: bool,
1372 section_is_generic: bool,
1373 addrspace_is_generic: bool,
1374 _: u11 = 0,
1375 };
1376};
1377
12861378/// Trailing:
12871379/// 0. element: Index for each len
12881380/// len is determined by the aggregate type.
......@@ -1371,24 +1463,6 @@ pub const Pointer = struct {
13711463 flags: Flags,
13721464 packed_offset: PackedOffset,
13731465
1374 /// Stored as a power-of-two, with one special value to indicate none.
1375 pub const Alignment = enum(u6) {
1376 none = std.math.maxInt(u6),
1377 _,
1378
1379 pub fn toByteUnits(a: Alignment, default: u64) u64 {
1380 return switch (a) {
1381 .none => default,
1382 _ => @as(u64, 1) << @enumToInt(a),
1383 };
1384 }
1385
1386 pub fn fromByteUnits(n: u64) Alignment {
1387 if (n == 0) return .none;
1388 return @intToEnum(Alignment, @ctz(n));
1389 }
1390 };
1391
13921466 pub const Flags = packed struct(u32) {
13931467 size: Size,
13941468 alignment: Alignment,
......@@ -1409,6 +1483,24 @@ pub const Pointer = struct {
14091483 pub const VectorIndex = Key.PtrType.VectorIndex;
14101484};
14111485
1486/// Stored as a power-of-two, with one special value to indicate none.
1487pub const Alignment = enum(u6) {
1488 none = std.math.maxInt(u6),
1489 _,
1490
1491 pub fn toByteUnits(a: Alignment, default: u64) u64 {
1492 return switch (a) {
1493 .none => default,
1494 _ => @as(u64, 1) << @enumToInt(a),
1495 };
1496 }
1497
1498 pub fn fromByteUnits(n: u64) Alignment {
1499 if (n == 0) return .none;
1500 return @intToEnum(Alignment, @ctz(n));
1501 }
1502};
1503
14121504/// Used for non-sentineled arrays that have length fitting in u32, as well as
14131505/// vectors.
14141506pub const Vector = struct {
......@@ -1765,6 +1857,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
17651857 },
17661858 .type_enum_explicit => indexToKeyEnum(ip, data, .explicit),
17671859 .type_enum_nonexhaustive => indexToKeyEnum(ip, data, .nonexhaustive),
1860 .type_function => .{ .func_type = indexToKeyFuncType(ip, data) },
17681861
17691862 .undef => .{ .undef = @intToEnum(Index, data) },
17701863 .opt_null => .{ .opt = .{
......@@ -1896,6 +1989,29 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
18961989 };
18971990}
18981991
1992fn indexToKeyFuncType(ip: InternPool, data: u32) Key.FuncType {
1993 const type_function = ip.extraDataTrail(TypeFunction, data);
1994 const param_types = @ptrCast(
1995 []Index,
1996 ip.extra.items[type_function.end..][0..type_function.data.params_len],
1997 );
1998 return .{
1999 .param_types = param_types,
2000 .return_type = type_function.data.return_type,
2001 .comptime_bits = type_function.data.comptime_bits,
2002 .noalias_bits = type_function.data.noalias_bits,
2003 .alignment = type_function.data.flags.alignment.toByteUnits(0),
2004 .cc = type_function.data.flags.cc,
2005 .is_var_args = type_function.data.flags.is_var_args,
2006 .is_generic = type_function.data.flags.is_generic,
2007 .is_noinline = type_function.data.flags.is_noinline,
2008 .align_is_generic = type_function.data.flags.align_is_generic,
2009 .cc_is_generic = type_function.data.flags.cc_is_generic,
2010 .section_is_generic = type_function.data.flags.section_is_generic,
2011 .addrspace_is_generic = type_function.data.flags.addrspace_is_generic,
2012 };
2013}
2014
18992015/// Asserts the integer tag type is already present in the InternPool.
19002016fn getEnumIntTagType(ip: InternPool, fields_len: u32) Index {
19012017 return ip.getAssumeExists(.{ .int_type = .{
......@@ -1977,7 +2093,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
19772093 .child = ptr_type.elem_type,
19782094 .sentinel = ptr_type.sentinel,
19792095 .flags = .{
1980 .alignment = Pointer.Alignment.fromByteUnits(ptr_type.alignment),
2096 .alignment = Alignment.fromByteUnits(ptr_type.alignment),
19812097 .is_const = ptr_type.is_const,
19822098 .is_volatile = ptr_type.is_volatile,
19832099 .is_allowzero = ptr_type.is_allowzero,
......@@ -2163,6 +2279,37 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
21632279 }
21642280 },
21652281
2282 .func_type => |func_type| {
2283 assert(func_type.return_type != .none);
2284 for (func_type.param_types) |param_type| assert(param_type != .none);
2285
2286 const params_len = @intCast(u32, func_type.param_types.len);
2287
2288 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(TypeFunction).Struct.fields.len +
2289 params_len);
2290 ip.items.appendAssumeCapacity(.{
2291 .tag = .type_function,
2292 .data = ip.addExtraAssumeCapacity(TypeFunction{
2293 .params_len = params_len,
2294 .return_type = func_type.return_type,
2295 .comptime_bits = func_type.comptime_bits,
2296 .noalias_bits = func_type.noalias_bits,
2297 .flags = .{
2298 .alignment = Alignment.fromByteUnits(func_type.alignment),
2299 .cc = func_type.cc,
2300 .is_var_args = func_type.is_var_args,
2301 .is_generic = func_type.is_generic,
2302 .is_noinline = func_type.is_noinline,
2303 .align_is_generic = func_type.align_is_generic,
2304 .cc_is_generic = func_type.cc_is_generic,
2305 .section_is_generic = func_type.section_is_generic,
2306 .addrspace_is_generic = func_type.addrspace_is_generic,
2307 },
2308 }),
2309 });
2310 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, func_type.param_types));
2311 },
2312
21662313 .extern_func => @panic("TODO"),
21672314
21682315 .ptr => |ptr| switch (ptr.addr) {
......@@ -2736,6 +2883,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
27362883 OptionalMapIndex => @enumToInt(@field(extra, field.name)),
27372884 i32 => @bitCast(u32, @field(extra, field.name)),
27382885 Pointer.Flags => @bitCast(u32, @field(extra, field.name)),
2886 TypeFunction.Flags => @bitCast(u32, @field(extra, field.name)),
27392887 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
27402888 Pointer.VectorIndex => @enumToInt(@field(extra, field.name)),
27412889 else => @compileError("bad field type: " ++ @typeName(field.type)),
......@@ -2797,6 +2945,7 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:
27972945 OptionalMapIndex => @intToEnum(OptionalMapIndex, int32),
27982946 i32 => @bitCast(i32, int32),
27992947 Pointer.Flags => @bitCast(Pointer.Flags, int32),
2948 TypeFunction.Flags => @bitCast(TypeFunction.Flags, int32),
28002949 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),
28012950 Pointer.VectorIndex => @intToEnum(Pointer.VectorIndex, int32),
28022951 else => @compileError("bad field type: " ++ @typeName(field.type)),
......@@ -2988,17 +3137,17 @@ pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Ind
29883137 }
29893138}
29903139
2991pub fn indexToStruct(ip: *InternPool, val: Index) Module.Struct.OptionalIndex {
3140pub fn indexToStructType(ip: InternPool, val: Index) Module.Struct.OptionalIndex {
3141 assert(val != .none);
29923142 const tags = ip.items.items(.tag);
2993 if (val == .none) return .none;
29943143 if (tags[@enumToInt(val)] != .type_struct) return .none;
29953144 const datas = ip.items.items(.data);
29963145 return @intToEnum(Module.Struct.Index, datas[@enumToInt(val)]).toOptional();
29973146}
29983147
2999pub fn indexToUnion(ip: *InternPool, val: Index) Module.Union.OptionalIndex {
3148pub fn indexToUnionType(ip: InternPool, val: Index) Module.Union.OptionalIndex {
3149 assert(val != .none);
30003150 const tags = ip.items.items(.tag);
3001 if (val == .none) return .none;
30023151 switch (tags[@enumToInt(val)]) {
30033152 .type_union_tagged, .type_union_untagged, .type_union_safety => {},
30043153 else => return .none,
......@@ -3007,6 +3156,16 @@ pub fn indexToUnion(ip: *InternPool, val: Index) Module.Union.OptionalIndex {
30073156 return @intToEnum(Module.Union.Index, datas[@enumToInt(val)]).toOptional();
30083157}
30093158
3159pub fn indexToFuncType(ip: InternPool, val: Index) ?Key.FuncType {
3160 assert(val != .none);
3161 const tags = ip.items.items(.tag);
3162 const datas = ip.items.items(.data);
3163 switch (tags[@enumToInt(val)]) {
3164 .type_function => return indexToKeyFuncType(ip, datas[@enumToInt(val)]),
3165 else => return null,
3166 }
3167}
3168
30103169pub fn isOptionalType(ip: InternPool, ty: Index) bool {
30113170 const tags = ip.items.items(.tag);
30123171 if (ty == .none) return false;
......@@ -3092,6 +3251,11 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
30923251 .type_union_safety,
30933252 => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),
30943253
3254 .type_function => b: {
3255 const info = ip.extraData(TypeFunction, data);
3256 break :b @sizeOf(TypeFunction) + (@sizeOf(u32) * info.params_len);
3257 },
3258
30953259 .undef => 0,
30963260 .simple_type => 0,
30973261 .simple_value => 0,
src/Module.zig+30-8
......@@ -846,7 +846,7 @@ pub const Decl = struct {
846846 pub fn getStructIndex(decl: *Decl, mod: *Module) Struct.OptionalIndex {
847847 if (!decl.owns_tv) return .none;
848848 const ty = (decl.val.castTag(.ty) orelse return .none).data;
849 return mod.intern_pool.indexToStruct(ty.ip_index);
849 return mod.intern_pool.indexToStructType(ty.ip_index);
850850 }
851851
852852 /// If the Decl has a value and it is a union, return it,
......@@ -4764,7 +4764,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47644764 decl.analysis = .complete;
47654765 decl.generation = mod.generation;
47664766
4767 const is_inline = decl.ty.fnCallingConvention() == .Inline;
4767 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
47684768 if (decl.is_exported) {
47694769 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
47704770 if (is_inline) {
......@@ -5617,6 +5617,9 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
56175617 const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);
56185618 defer decl.value_arena.?.release(&decl_arena);
56195619
5620 const fn_ty = decl.ty;
5621 const fn_ty_info = mod.typeToFunc(fn_ty).?;
5622
56205623 var sema: Sema = .{
56215624 .mod = mod,
56225625 .gpa = gpa,
......@@ -5626,7 +5629,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
56265629 .owner_decl = decl,
56275630 .owner_decl_index = decl_index,
56285631 .func = func,
5629 .fn_ret_ty = decl.ty.fnReturnType(),
5632 .fn_ret_ty = fn_ty_info.return_type.toType(),
56305633 .owner_func = func,
56315634 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
56325635 };
......@@ -5664,8 +5667,6 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
56645667 // This could be a generic function instantiation, however, in which case we need to
56655668 // map the comptime parameters to constant values and only emit arg AIR instructions
56665669 // for the runtime ones.
5667 const fn_ty = decl.ty;
5668 const fn_ty_info = fn_ty.fnInfo();
56695670 const runtime_params_len = @intCast(u32, fn_ty_info.param_types.len);
56705671 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
56715672 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
......@@ -5692,7 +5693,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
56925693 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
56935694 total_param_index += 1;
56945695 continue;
5695 } else fn_ty_info.param_types[runtime_param_index];
5696 } else fn_ty_info.param_types[runtime_param_index].toType();
56965697
56975698 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
56985699 error.NeededSourceLocation => unreachable,
......@@ -6864,6 +6865,10 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
68646865 return ptrType(mod, .{ .elem_type = child_type.ip_index, .is_const = true });
68656866}
68666867
6868pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Type {
6869 return (try intern(mod, .{ .func_type = info })).toType();
6870}
6871
68676872/// Supports optionals in addition to pointers.
68686873pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
68696874 if (ty.isPtrLikeOptional(mod)) {
......@@ -6996,6 +7001,16 @@ pub fn floatValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value {
69967001 return i.toValue();
69977002}
69987003
7004pub fn nullValue(mod: *Module, opt_ty: Type) Allocator.Error!Value {
7005 const ip = &mod.intern_pool;
7006 assert(ip.isOptionalType(opt_ty.ip_index));
7007 const result = try ip.get(mod.gpa, .{ .opt = .{
7008 .ty = opt_ty.ip_index,
7009 .val = .none,
7010 } });
7011 return result.toValue();
7012}
7013
69997014pub fn smallestUnsignedInt(mod: *Module, max: u64) Allocator.Error!Type {
70007015 return intType(mod, .unsigned, Type.smallestUnsignedBits(max));
70017016}
......@@ -7201,15 +7216,22 @@ pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.I
72017216/// * A struct which has no fields (`struct {}`).
72027217/// * Not a struct.
72037218pub fn typeToStruct(mod: *Module, ty: Type) ?*Struct {
7204 const struct_index = mod.intern_pool.indexToStruct(ty.ip_index).unwrap() orelse return null;
7219 if (ty.ip_index == .none) return null;
7220 const struct_index = mod.intern_pool.indexToStructType(ty.ip_index).unwrap() orelse return null;
72057221 return mod.structPtr(struct_index);
72067222}
72077223
72087224pub fn typeToUnion(mod: *Module, ty: Type) ?*Union {
7209 const union_index = mod.intern_pool.indexToUnion(ty.ip_index).unwrap() orelse return null;
7225 if (ty.ip_index == .none) return null;
7226 const union_index = mod.intern_pool.indexToUnionType(ty.ip_index).unwrap() orelse return null;
72107227 return mod.unionPtr(union_index);
72117228}
72127229
7230pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {
7231 if (ty.ip_index == .none) return null;
7232 return mod.intern_pool.indexToFuncType(ty.ip_index);
7233}
7234
72137235pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {
72147236 @setCold(true);
72157237 const owner_decl = mod.declPtr(owner_decl_index);
src/Sema.zig+166-168
......@@ -5850,6 +5850,7 @@ pub fn analyzeExport(
58505850}
58515851
58525852fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
5853 const mod = sema.mod;
58535854 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
58545855 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
58555856 const src = LazySrcLoc.nodeOffset(extra.node);
......@@ -5862,8 +5863,8 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
58625863 const func = sema.func orelse
58635864 return sema.fail(block, src, "@setAlignStack outside function body", .{});
58645865
5865 const fn_owner_decl = sema.mod.declPtr(func.owner_decl);
5866 switch (fn_owner_decl.ty.fnCallingConvention()) {
5866 const fn_owner_decl = mod.declPtr(func.owner_decl);
5867 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
58675868 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
58685869 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),
58695870 else => if (block.inlining != null) {
......@@ -5871,7 +5872,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
58715872 },
58725873 }
58735874
5874 const gop = try sema.mod.align_stack_fns.getOrPut(sema.mod.gpa, func);
5875 const gop = try mod.align_stack_fns.getOrPut(mod.gpa, func);
58755876 if (gop.found_existing) {
58765877 const msg = msg: {
58775878 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});
......@@ -6378,7 +6379,7 @@ fn zirCall(
63786379 var input_is_error = false;
63796380 const block_index = @intCast(Air.Inst.Index, block.instructions.items.len);
63806381
6381 const func_ty_info = func_ty.fnInfo();
6382 const func_ty_info = mod.typeToFunc(func_ty).?;
63826383 const fn_params_len = func_ty_info.param_types.len;
63836384 const parent_comptime = block.is_comptime;
63846385 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
......@@ -6393,7 +6394,7 @@ fn zirCall(
63936394
63946395 // Generate args to comptime params in comptime block.
63956396 defer block.is_comptime = parent_comptime;
6396 if (arg_index < fn_params_len and func_ty_info.comptime_params[arg_index]) {
6397 if (arg_index < fn_params_len and func_ty_info.paramIsComptime(@intCast(u5, arg_index))) {
63976398 block.is_comptime = true;
63986399 // TODO set comptime_reason
63996400 }
......@@ -6402,10 +6403,10 @@ fn zirCall(
64026403 if (arg_index >= fn_params_len)
64036404 break :inst Air.Inst.Ref.var_args_param_type;
64046405
6405 if (func_ty_info.param_types[arg_index].isGenericPoison())
6406 if (func_ty_info.param_types[arg_index] == .generic_poison_type)
64066407 break :inst Air.Inst.Ref.generic_poison_type;
64076408
6408 break :inst try sema.addType(func_ty_info.param_types[arg_index]);
6409 break :inst try sema.addType(func_ty_info.param_types[arg_index].toType());
64096410 });
64106411
64116412 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
......@@ -6506,7 +6507,7 @@ fn checkCallArgumentCount(
65066507 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(sema.mod)});
65076508 };
65086509
6509 const func_ty_info = func_ty.fnInfo();
6510 const func_ty_info = mod.typeToFunc(func_ty).?;
65106511 const fn_params_len = func_ty_info.param_types.len;
65116512 const args_len = total_args - @boolToInt(member_fn);
65126513 if (func_ty_info.is_var_args) {
......@@ -6562,7 +6563,7 @@ fn callBuiltin(
65626563 std.debug.panic("type '{}' is not a function calling builtin fn", .{callee_ty.fmt(sema.mod)});
65636564 };
65646565
6565 const func_ty_info = func_ty.fnInfo();
6566 const func_ty_info = mod.typeToFunc(func_ty).?;
65666567 const fn_params_len = func_ty_info.param_types.len;
65676568 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) {
65686569 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len });
......@@ -6573,7 +6574,7 @@ fn callBuiltin(
65736574const GenericCallAdapter = struct {
65746575 generic_fn: *Module.Fn,
65756576 precomputed_hash: u64,
6576 func_ty_info: Type.Payload.Function.Data,
6577 func_ty_info: InternPool.Key.FuncType,
65776578 args: []const Arg,
65786579 module: *Module,
65796580
......@@ -6656,7 +6657,7 @@ fn analyzeCall(
66566657 const mod = sema.mod;
66576658
66586659 const callee_ty = sema.typeOf(func);
6659 const func_ty_info = func_ty.fnInfo();
6660 const func_ty_info = mod.typeToFunc(func_ty).?;
66606661 const fn_params_len = func_ty_info.param_types.len;
66616662 const cc = func_ty_info.cc;
66626663 if (cc == .Naked) {
......@@ -6704,7 +6705,7 @@ fn analyzeCall(
67046705 var comptime_reason_buf: Block.ComptimeReason = undefined;
67056706 var comptime_reason: ?*const Block.ComptimeReason = null;
67066707 if (!is_comptime_call) {
6707 if (sema.typeRequiresComptime(func_ty_info.return_type)) |ct| {
6708 if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| {
67086709 is_comptime_call = ct;
67096710 if (ct) {
67106711 // stage1 can't handle doing this directly
......@@ -6712,7 +6713,7 @@ fn analyzeCall(
67126713 .block = block,
67136714 .func = func,
67146715 .func_src = func_src,
6715 .return_ty = func_ty_info.return_type,
6716 .return_ty = func_ty_info.return_type.toType(),
67166717 } };
67176718 comptime_reason = &comptime_reason_buf;
67186719 }
......@@ -6750,7 +6751,7 @@ fn analyzeCall(
67506751 .block = block,
67516752 .func = func,
67526753 .func_src = func_src,
6753 .return_ty = func_ty_info.return_type,
6754 .return_ty = func_ty_info.return_type.toType(),
67546755 } };
67556756 comptime_reason = &comptime_reason_buf;
67566757 },
......@@ -6875,9 +6876,9 @@ fn analyzeCall(
68756876 // comptime state.
68766877 var should_memoize = true;
68776878
6878 var new_fn_info = fn_owner_decl.ty.fnInfo();
6879 new_fn_info.param_types = try sema.arena.alloc(Type, new_fn_info.param_types.len);
6880 new_fn_info.comptime_params = (try sema.arena.alloc(bool, new_fn_info.param_types.len)).ptr;
6879 var new_fn_info = mod.typeToFunc(fn_owner_decl.ty).?;
6880 new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len);
6881 new_fn_info.comptime_bits = 0;
68816882
68826883 // This will have return instructions analyzed as break instructions to
68836884 // the block_inst above. Here we are performing "comptime/inline semantic analysis"
......@@ -6970,7 +6971,7 @@ fn analyzeCall(
69706971 }
69716972 break :blk bare_return_type;
69726973 };
6973 new_fn_info.return_type = fn_ret_ty;
6974 new_fn_info.return_type = fn_ret_ty.ip_index;
69746975 const parent_fn_ret_ty = sema.fn_ret_ty;
69756976 sema.fn_ret_ty = fn_ret_ty;
69766977 defer sema.fn_ret_ty = parent_fn_ret_ty;
......@@ -6993,7 +6994,7 @@ fn analyzeCall(
69936994 }
69946995 }
69956996
6996 const new_func_resolved_ty = try Type.Tag.function.create(sema.arena, new_fn_info);
6997 const new_func_resolved_ty = try mod.funcType(new_fn_info);
69976998 if (!is_comptime_call and !block.is_typeof) {
69986999 try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin);
69997000
......@@ -7081,13 +7082,14 @@ fn analyzeCall(
70817082 assert(!func_ty_info.is_generic);
70827083
70837084 const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len);
7085 const fn_info = mod.typeToFunc(func_ty).?;
70847086 for (uncasted_args, 0..) |uncasted_arg, i| {
70857087 if (i < fn_params_len) {
70867088 const opts: CoerceOpts = .{ .param_src = .{
70877089 .func_inst = func,
70887090 .param_i = @intCast(u32, i),
70897091 } };
7090 const param_ty = func_ty.fnParamType(i);
7092 const param_ty = fn_info.param_types[i].toType();
70917093 args[i] = sema.analyzeCallArg(
70927094 block,
70937095 .unneeded,
......@@ -7126,8 +7128,8 @@ fn analyzeCall(
71267128
71277129 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
71287130
7129 try sema.queueFullTypeResolution(func_ty_info.return_type);
7130 if (sema.owner_func != null and func_ty_info.return_type.isError(mod)) {
7131 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7132 if (sema.owner_func != null and func_ty_info.return_type.toType().isError(mod)) {
71317133 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
71327134 }
71337135
......@@ -7155,7 +7157,7 @@ fn analyzeCall(
71557157 try sema.ensureResultUsed(block, sema.typeOf(func_inst), call_src);
71567158 }
71577159 return sema.handleTailCall(block, call_src, func_ty, func_inst);
7158 } else if (block.wantSafety() and func_ty_info.return_type.isNoReturn()) {
7160 } else if (block.wantSafety() and func_ty_info.return_type == .noreturn_type) {
71597161 // Function pointers and extern functions aren't guaranteed to
71607162 // actually be noreturn so we add a safety check for them.
71617163 check: {
......@@ -7171,7 +7173,7 @@ fn analyzeCall(
71717173
71727174 try sema.safetyPanic(block, .noreturn_returned);
71737175 return Air.Inst.Ref.unreachable_value;
7174 } else if (func_ty_info.return_type.isNoReturn()) {
7176 } else if (func_ty_info.return_type == .noreturn_type) {
71757177 _ = try block.addNoOp(.unreach);
71767178 return Air.Inst.Ref.unreachable_value;
71777179 }
......@@ -7208,13 +7210,13 @@ fn analyzeInlineCallArg(
72087210 param_block: *Block,
72097211 arg_src: LazySrcLoc,
72107212 inst: Zir.Inst.Index,
7211 new_fn_info: Type.Payload.Function.Data,
7213 new_fn_info: InternPool.Key.FuncType,
72127214 arg_i: *usize,
72137215 uncasted_args: []const Air.Inst.Ref,
72147216 is_comptime_call: bool,
72157217 should_memoize: *bool,
72167218 memoized_call_key: Module.MemoizedCall.Key,
7217 raw_param_types: []const Type,
7219 raw_param_types: []const InternPool.Index,
72187220 func_inst: Air.Inst.Ref,
72197221 has_comptime_args: *bool,
72207222) !void {
......@@ -7233,13 +7235,14 @@ fn analyzeInlineCallArg(
72337235 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
72347236 const param_ty = param_ty: {
72357237 const raw_param_ty = raw_param_types[arg_i.*];
7236 if (!raw_param_ty.isGenericPoison()) break :param_ty raw_param_ty;
7238 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;
72377239 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
7238 break :param_ty try sema.analyzeAsType(param_block, param_src, param_ty_inst);
7240 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
7241 break :param_ty param_ty.toIntern();
72397242 };
72407243 new_fn_info.param_types[arg_i.*] = param_ty;
72417244 const uncasted_arg = uncasted_args[arg_i.*];
7242 if (try sema.typeRequiresComptime(param_ty)) {
7245 if (try sema.typeRequiresComptime(param_ty.toType())) {
72437246 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {
72447247 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
72457248 return err;
......@@ -7247,7 +7250,7 @@ fn analyzeInlineCallArg(
72477250 } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) {
72487251 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
72497252 }
7250 const casted_arg = sema.coerceExtra(arg_block, param_ty, uncasted_arg, arg_src, .{ .param_src = .{
7253 const casted_arg = sema.coerceExtra(arg_block, param_ty.toType(), uncasted_arg, arg_src, .{ .param_src = .{
72517254 .func_inst = func_inst,
72527255 .param_i = @intCast(u32, arg_i.*),
72537256 } }) catch |err| switch (err) {
......@@ -7276,7 +7279,7 @@ fn analyzeInlineCallArg(
72767279 }
72777280 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
72787281 memoized_call_key.args[arg_i.*] = .{
7279 .ty = param_ty,
7282 .ty = param_ty.toType(),
72807283 .val = arg_val,
72817284 };
72827285 } else {
......@@ -7292,7 +7295,7 @@ fn analyzeInlineCallArg(
72927295 .param_anytype, .param_anytype_comptime => {
72937296 // No coercion needed.
72947297 const uncasted_arg = uncasted_args[arg_i.*];
7295 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg);
7298 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern();
72967299
72977300 if (is_comptime_call) {
72987301 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
......@@ -7357,7 +7360,7 @@ fn analyzeGenericCallArg(
73577360 uncasted_arg: Air.Inst.Ref,
73587361 comptime_arg: TypedValue,
73597362 runtime_args: []Air.Inst.Ref,
7360 new_fn_info: Type.Payload.Function.Data,
7363 new_fn_info: InternPool.Key.FuncType,
73617364 runtime_i: *u32,
73627365) !void {
73637366 const mod = sema.mod;
......@@ -7365,7 +7368,7 @@ fn analyzeGenericCallArg(
73657368 comptime_arg.ty.hasRuntimeBits(mod) and
73667369 !(try sema.typeRequiresComptime(comptime_arg.ty));
73677370 if (is_runtime) {
7368 const param_ty = new_fn_info.param_types[runtime_i.*];
7371 const param_ty = new_fn_info.param_types[runtime_i.*].toType();
73697372 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
73707373 try sema.queueFullTypeResolution(param_ty);
73717374 runtime_args[runtime_i.*] = casted_arg;
......@@ -7387,7 +7390,7 @@ fn instantiateGenericCall(
73877390 func: Air.Inst.Ref,
73887391 func_src: LazySrcLoc,
73897392 call_src: LazySrcLoc,
7390 func_ty_info: Type.Payload.Function.Data,
7393 func_ty_info: InternPool.Key.FuncType,
73917394 ensure_result_used: bool,
73927395 uncasted_args: []const Air.Inst.Ref,
73937396 call_tag: Air.Inst.Tag,
......@@ -7431,14 +7434,14 @@ fn instantiateGenericCall(
74317434 var is_anytype = false;
74327435 switch (zir_tags[inst]) {
74337436 .param => {
7434 is_comptime = func_ty_info.paramIsComptime(i);
7437 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, i));
74357438 },
74367439 .param_comptime => {
74377440 is_comptime = true;
74387441 },
74397442 .param_anytype => {
74407443 is_anytype = true;
7441 is_comptime = func_ty_info.paramIsComptime(i);
7444 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, i));
74427445 },
74437446 .param_anytype_comptime => {
74447447 is_anytype = true;
......@@ -7609,7 +7612,7 @@ fn instantiateGenericCall(
76097612 // Make a runtime call to the new function, making sure to omit the comptime args.
76107613 const comptime_args = callee.comptime_args.?;
76117614 const func_ty = mod.declPtr(callee.owner_decl).ty;
7612 const new_fn_info = func_ty.fnInfo();
7615 const new_fn_info = mod.typeToFunc(func_ty).?;
76137616 const runtime_args_len = @intCast(u32, new_fn_info.param_types.len);
76147617 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
76157618 {
......@@ -7647,12 +7650,12 @@ fn instantiateGenericCall(
76477650 total_i += 1;
76487651 }
76497652
7650 try sema.queueFullTypeResolution(new_fn_info.return_type);
7653 try sema.queueFullTypeResolution(new_fn_info.return_type.toType());
76517654 }
76527655
76537656 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
76547657
7655 if (sema.owner_func != null and new_fn_info.return_type.isError(mod)) {
7658 if (sema.owner_func != null and new_fn_info.return_type.toType().isError(mod)) {
76567659 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
76577660 }
76587661
......@@ -7677,7 +7680,7 @@ fn instantiateGenericCall(
76777680 if (call_tag == .call_always_tail) {
76787681 return sema.handleTailCall(block, call_src, func_ty, result);
76797682 }
7680 if (new_fn_info.return_type.isNoReturn()) {
7683 if (new_fn_info.return_type == .noreturn_type) {
76817684 _ = try block.addNoOp(.unreach);
76827685 return Air.Inst.Ref.unreachable_value;
76837686 }
......@@ -7695,7 +7698,7 @@ fn resolveGenericInstantiationType(
76957698 module_fn: *Module.Fn,
76967699 new_module_func: *Module.Fn,
76977700 namespace: Namespace.Index,
7698 func_ty_info: Type.Payload.Function.Data,
7701 func_ty_info: InternPool.Key.FuncType,
76997702 call_src: LazySrcLoc,
77007703 bound_arg_src: ?LazySrcLoc,
77017704) !*Module.Fn {
......@@ -7755,14 +7758,14 @@ fn resolveGenericInstantiationType(
77557758 var is_anytype = false;
77567759 switch (zir_tags[inst]) {
77577760 .param => {
7758 is_comptime = func_ty_info.paramIsComptime(arg_i);
7761 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
77597762 },
77607763 .param_comptime => {
77617764 is_comptime = true;
77627765 },
77637766 .param_anytype => {
77647767 is_anytype = true;
7765 is_comptime = func_ty_info.paramIsComptime(arg_i);
7768 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
77667769 },
77677770 .param_anytype_comptime => {
77687771 is_anytype = true;
......@@ -7822,13 +7825,13 @@ fn resolveGenericInstantiationType(
78227825 var is_comptime = false;
78237826 switch (zir_tags[inst]) {
78247827 .param => {
7825 is_comptime = func_ty_info.paramIsComptime(arg_i);
7828 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
78267829 },
78277830 .param_comptime => {
78287831 is_comptime = true;
78297832 },
78307833 .param_anytype => {
7831 is_comptime = func_ty_info.paramIsComptime(arg_i);
7834 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
78327835 },
78337836 .param_anytype_comptime => {
78347837 is_comptime = true;
......@@ -7868,8 +7871,8 @@ fn resolveGenericInstantiationType(
78687871 new_decl.ty = try child_sema.typeOf(new_func_inst).copy(new_decl_arena_allocator);
78697872 // If the call evaluated to a return type that requires comptime, never mind
78707873 // our generic instantiation. Instead we need to perform a comptime call.
7871 const new_fn_info = new_decl.ty.fnInfo();
7872 if (try sema.typeRequiresComptime(new_fn_info.return_type)) {
7874 const new_fn_info = mod.typeToFunc(new_decl.ty).?;
7875 if (try sema.typeRequiresComptime(new_fn_info.return_type.toType())) {
78737876 return error.ComptimeReturn;
78747877 }
78757878 // Similarly, if the call evaluated to a generic type we need to instead
......@@ -8969,19 +8972,19 @@ fn funcCommon(
89698972 // the instantiation, which can depend on comptime parameters.
89708973 // Related proposal: https://github.com/ziglang/zig/issues/11834
89718974 const cc_resolved = cc orelse .Unspecified;
8972 const param_types = try sema.arena.alloc(Type, block.params.items.len);
8973 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);
8974 for (block.params.items, 0..) |param, i| {
8975 const param_types = try sema.arena.alloc(InternPool.Index, block.params.items.len);
8976 var comptime_bits: u32 = 0;
8977 for (param_types, block.params.items, 0..) |*dest_param_ty, param, i| {
89758978 const is_noalias = blk: {
89768979 const index = std.math.cast(u5, i) orelse break :blk false;
89778980 break :blk @truncate(u1, noalias_bits >> index) != 0;
89788981 };
8979 param_types[i] = param.ty;
8982 dest_param_ty.* = param.ty.toIntern();
89808983 sema.analyzeParameter(
89818984 block,
89828985 .unneeded,
89838986 param,
8984 comptime_params,
8987 &comptime_bits,
89858988 i,
89868989 &is_generic,
89878990 cc_resolved,
......@@ -8994,7 +8997,7 @@ fn funcCommon(
89948997 block,
89958998 Module.paramSrc(src_node_offset, mod, decl, i),
89968999 param,
8997 comptime_params,
9000 &comptime_bits,
89989001 i,
89999002 &is_generic,
90009003 cc_resolved,
......@@ -9019,7 +9022,7 @@ fn funcCommon(
90199022 else => |e| return e,
90209023 };
90219024
9022 const return_type = if (!inferred_error_set or ret_poison)
9025 const return_type: Type = if (!inferred_error_set or ret_poison)
90239026 bare_return_type
90249027 else blk: {
90259028 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
......@@ -9047,7 +9050,9 @@ fn funcCommon(
90479050 };
90489051 return sema.failWithOwnedErrorMsg(msg);
90499052 }
9050 if (!ret_poison and !Type.fnCallingConventionAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(return_type, .ret_ty)) {
9053 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and
9054 !try sema.validateExternType(return_type, .ret_ty))
9055 {
90519056 const msg = msg: {
90529057 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
90539058 return_type.fmt(sema.mod), @tagName(cc_resolved),
......@@ -9141,8 +9146,7 @@ fn funcCommon(
91419146 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
91429147 }
91439148 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
9144 for (comptime_params) |ct| is_generic = is_generic or ct;
9145 is_generic = is_generic or ret_ty_requires_comptime;
9149 is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
91469150
91479151 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {
91489152 // Make sure that StackTrace's fields are resolved so that the backend can
......@@ -9151,10 +9155,11 @@ fn funcCommon(
91519155 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
91529156 }
91539157
9154 break :fn_ty try Type.Tag.function.create(sema.arena, .{
9158 break :fn_ty try mod.funcType(.{
91559159 .param_types = param_types,
9156 .comptime_params = comptime_params.ptr,
9157 .return_type = return_type,
9160 .noalias_bits = noalias_bits,
9161 .comptime_bits = comptime_bits,
9162 .return_type = return_type.toIntern(),
91589163 .cc = cc_resolved,
91599164 .cc_is_generic = cc == null,
91609165 .alignment = alignment orelse 0,
......@@ -9164,7 +9169,6 @@ fn funcCommon(
91649169 .is_var_args = var_args,
91659170 .is_generic = is_generic,
91669171 .is_noinline = is_noinline,
9167 .noalias_bits = noalias_bits,
91689172 });
91699173 };
91709174
......@@ -9203,7 +9207,7 @@ fn funcCommon(
92039207 return sema.addType(fn_ty);
92049208 }
92059209
9206 const is_inline = fn_ty.fnCallingConvention() == .Inline;
9210 const is_inline = fn_ty.fnCallingConvention(mod) == .Inline;
92079211 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;
92089212
92099213 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {
......@@ -9243,7 +9247,7 @@ fn analyzeParameter(
92439247 block: *Block,
92449248 param_src: LazySrcLoc,
92459249 param: Block.Param,
9246 comptime_params: []bool,
9250 comptime_bits: *u32,
92479251 i: usize,
92489252 is_generic: *bool,
92499253 cc: std.builtin.CallingConvention,
......@@ -9252,14 +9256,16 @@ fn analyzeParameter(
92529256) !void {
92539257 const mod = sema.mod;
92549258 const requires_comptime = try sema.typeRequiresComptime(param.ty);
9255 comptime_params[i] = param.is_comptime or requires_comptime;
9259 if (param.is_comptime or requires_comptime) {
9260 comptime_bits.* |= @as(u32, 1) << @intCast(u5, i); // TODO: handle cast error
9261 }
92569262 const this_generic = param.ty.isGenericPoison();
92579263 is_generic.* = is_generic.* or this_generic;
92589264 const target = mod.getTarget();
9259 if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(target, cc)) {
9265 if (param.is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc)) {
92609266 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
92619267 }
9262 if (this_generic and !sema.no_partial_func_ty and !Type.fnCallingConventionAllowsZigTypes(target, cc)) {
9268 if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc)) {
92639269 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
92649270 }
92659271 if (!param.ty.isValidParamType(mod)) {
......@@ -9275,7 +9281,7 @@ fn analyzeParameter(
92759281 };
92769282 return sema.failWithOwnedErrorMsg(msg);
92779283 }
9278 if (!this_generic and !Type.fnCallingConventionAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) {
9284 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) {
92799285 const msg = msg: {
92809286 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
92819287 param.ty.fmt(mod), @tagName(cc),
......@@ -15986,22 +15992,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1598615992 ),
1598715993 .Fn => {
1598815994 // TODO: look into memoizing this result.
15989 const info = ty.fnInfo();
15995 const info = mod.typeToFunc(ty).?;
1599015996
1599115997 var params_anon_decl = try block.startAnonDecl();
1599215998 defer params_anon_decl.deinit();
1599315999
1599416000 const param_vals = try params_anon_decl.arena().alloc(Value, info.param_types.len);
15995 for (param_vals, 0..) |*param_val, i| {
15996 const param_ty = info.param_types[i];
15997 const is_generic = param_ty.isGenericPoison();
15998 const param_ty_val = if (is_generic)
15999 Value.null
16000 else
16001 try Value.Tag.opt_payload.create(
16002 params_anon_decl.arena(),
16003 try Value.Tag.ty.create(params_anon_decl.arena(), try param_ty.copy(params_anon_decl.arena())),
16004 );
16001 for (param_vals, info.param_types, 0..) |*param_val, param_ty, i| {
16002 const is_generic = param_ty == .generic_poison_type;
16003 const param_ty_val = try mod.intern_pool.get(mod.gpa, .{ .opt = .{
16004 .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),
16005 .val = if (is_generic) .none else param_ty,
16006 } });
1600516007
1600616008 const is_noalias = blk: {
1600716009 const index = std.math.cast(u5, i) orelse break :blk false;
......@@ -16015,7 +16017,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1601516017 // is_noalias: bool,
1601616018 Value.makeBool(is_noalias),
1601716019 // type: ?type,
16018 param_ty_val,
16020 param_ty_val.toValue(),
1601916021 };
1602016022 param_val.* = try Value.Tag.aggregate.create(params_anon_decl.arena(), param_fields);
1602116023 }
......@@ -16059,13 +16061,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1605916061 });
1606016062 };
1606116063
16062 const ret_ty_opt = if (!info.return_type.isGenericPoison())
16063 try Value.Tag.opt_payload.create(
16064 sema.arena,
16065 try Value.Tag.ty.create(sema.arena, info.return_type),
16066 )
16067 else
16068 Value.null;
16064 const ret_ty_opt = try mod.intern_pool.get(mod.gpa, .{ .opt = .{
16065 .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),
16066 .val = if (info.return_type == .generic_poison_type) .none else info.return_type,
16067 } });
1606916068
1607016069 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1607116070
......@@ -16080,7 +16079,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1608016079 // is_var_args: bool,
1608116080 Value.makeBool(info.is_var_args),
1608216081 // return_type: ?type,
16083 ret_ty_opt,
16082 ret_ty_opt.toValue(),
1608416083 // args: []const Fn.Param,
1608516084 args_val,
1608616085 };
......@@ -17788,7 +17787,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1778817787 if (inst_data.size != .One) {
1778917788 return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});
1779017789 }
17791 const fn_align = elem_ty.fnInfo().alignment;
17790 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
1779217791 if (inst_data.flags.has_align and abi_align != 0 and fn_align != 0 and
1779317792 abi_align != fn_align)
1779417793 {
......@@ -18939,7 +18938,7 @@ fn zirReify(
1893918938 if (ptr_size != .One) {
1894018939 return sema.fail(block, src, "function pointers must be single pointers", .{});
1894118940 }
18942 const fn_align = elem_ty.fnInfo().alignment;
18941 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
1894318942 if (abi_align != 0 and fn_align != 0 and
1894418943 abi_align != fn_align)
1894518944 {
......@@ -19483,12 +19482,10 @@ fn zirReify(
1948319482 const args_slice_val = args_val.castTag(.slice).?.data;
1948419483 const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod));
1948519484
19486 const param_types = try sema.arena.alloc(Type, args_len);
19487 const comptime_params = try sema.arena.alloc(bool, args_len);
19485 const param_types = try sema.arena.alloc(InternPool.Index, args_len);
1948819486
1948919487 var noalias_bits: u32 = 0;
19490 var i: usize = 0;
19491 while (i < args_len) : (i += 1) {
19488 for (param_types, 0..) |*param_type, i| {
1949219489 const arg = try args_slice_val.ptr.elemValue(mod, i);
1949319490 const arg_val = arg.castTag(.aggregate).?.data;
1949419491 // TODO use reflection instead of magic numbers here
......@@ -19505,25 +19502,22 @@ fn zirReify(
1950519502
1950619503 const param_type_val = param_type_opt_val.optionalValue(mod) orelse
1950719504 return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{});
19508 const param_type = try param_type_val.toType().copy(sema.arena);
19505 param_type.* = param_type_val.ip_index;
1950919506
1951019507 if (arg_is_noalias) {
19511 if (!param_type.isPtrAtRuntime(mod)) {
19508 if (!param_type.toType().isPtrAtRuntime(mod)) {
1951219509 return sema.fail(block, src, "non-pointer parameter declared noalias", .{});
1951319510 }
1951419511 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse
1951519512 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
1951619513 }
19517
19518 param_types[i] = param_type;
19519 comptime_params[i] = false;
1952019514 }
1952119515
19522 var fn_info = Type.Payload.Function.Data{
19516 const ty = try mod.funcType(.{
1952319517 .param_types = param_types,
19524 .comptime_params = comptime_params.ptr,
19518 .comptime_bits = 0,
1952519519 .noalias_bits = noalias_bits,
19526 .return_type = try return_type.toType().copy(sema.arena),
19520 .return_type = return_type.toIntern(),
1952719521 .alignment = alignment,
1952819522 .cc = cc,
1952919523 .is_var_args = is_var_args,
......@@ -19533,9 +19527,7 @@ fn zirReify(
1953319527 .cc_is_generic = false,
1953419528 .section_is_generic = false,
1953519529 .addrspace_is_generic = false,
19536 };
19537
19538 const ty = try Type.Tag.function.create(sema.arena, fn_info);
19530 });
1953919531 return sema.addType(ty);
1954019532 },
1954119533 .Frame => return sema.failWithUseOfAsync(block, src),
......@@ -23435,7 +23427,7 @@ fn explainWhyTypeIsComptimeInner(
2343523427 .Pointer => {
2343623428 const elem_ty = ty.elemType2(mod);
2343723429 if (elem_ty.zigTypeTag(mod) == .Fn) {
23438 const fn_info = elem_ty.fnInfo();
23430 const fn_info = mod.typeToFunc(elem_ty).?;
2343923431 if (fn_info.is_generic) {
2344023432 try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{});
2344123433 }
......@@ -23443,7 +23435,7 @@ fn explainWhyTypeIsComptimeInner(
2344323435 .Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}),
2344423436 else => {},
2344523437 }
23446 if (fn_info.return_type.comptimeOnly(mod)) {
23438 if (fn_info.return_type.toType().comptimeOnly(mod)) {
2344723439 try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{});
2344823440 }
2344923441 return;
......@@ -23543,10 +23535,10 @@ fn validateExternType(
2354323535 const target = sema.mod.getTarget();
2354423536 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.
2354523537 // The goal is to experiment with more integrated CPU/GPU code.
23546 if (ty.fnCallingConvention() == .Kernel and (target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64)) {
23538 if (ty.fnCallingConvention(mod) == .Kernel and (target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64)) {
2354723539 return true;
2354823540 }
23549 return !Type.fnCallingConventionAllowsZigTypes(target, ty.fnCallingConvention());
23541 return !target_util.fnCallConvAllowsZigTypes(target, ty.fnCallingConvention(mod));
2355023542 },
2355123543 .Enum => {
2355223544 return sema.validateExternType(try ty.intTagType(mod), position);
......@@ -23619,7 +23611,7 @@ fn explainWhyTypeIsNotExtern(
2361923611 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
2362023612 return;
2362123613 }
23622 switch (ty.fnCallingConvention()) {
23614 switch (ty.fnCallingConvention(mod)) {
2362323615 .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}),
2362423616 .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}),
2362523617 .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}),
......@@ -24548,10 +24540,10 @@ fn fieldCallBind(
2454824540 try sema.addReferencedBy(block, src, decl_idx);
2454924541 const decl_val = try sema.analyzeDeclVal(block, src, decl_idx);
2455024542 const decl_type = sema.typeOf(decl_val);
24551 if (decl_type.zigTypeTag(mod) == .Fn and
24552 decl_type.fnParamLen() >= 1)
24553 {
24554 const first_param_type = decl_type.fnParamType(0);
24543 if (mod.typeToFunc(decl_type)) |func_type| f: {
24544 if (func_type.param_types.len == 0) break :f;
24545
24546 const first_param_type = func_type.param_types[0].toType();
2455524547 // zig fmt: off
2455624548 if (first_param_type.isGenericPoison() or (
2455724549 first_param_type.zigTypeTag(mod) == .Pointer and
......@@ -27090,8 +27082,9 @@ fn coerceInMemoryAllowedFns(
2709027082 dest_src: LazySrcLoc,
2709127083 src_src: LazySrcLoc,
2709227084) !InMemoryCoercionResult {
27093 const dest_info = dest_ty.fnInfo();
27094 const src_info = src_ty.fnInfo();
27085 const mod = sema.mod;
27086 const dest_info = mod.typeToFunc(dest_ty).?;
27087 const src_info = mod.typeToFunc(src_ty).?;
2709527088
2709627089 if (dest_info.is_var_args != src_info.is_var_args) {
2709727090 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
......@@ -27108,13 +27101,13 @@ fn coerceInMemoryAllowedFns(
2710827101 } };
2710927102 }
2711027103
27111 if (!src_info.return_type.isNoReturn()) {
27112 const rt = try sema.coerceInMemoryAllowed(block, dest_info.return_type, src_info.return_type, false, target, dest_src, src_src);
27104 if (src_info.return_type != .noreturn_type) {
27105 const rt = try sema.coerceInMemoryAllowed(block, dest_info.return_type.toType(), src_info.return_type.toType(), false, target, dest_src, src_src);
2711327106 if (rt != .ok) {
2711427107 return InMemoryCoercionResult{ .fn_return_type = .{
2711527108 .child = try rt.dupe(sema.arena),
27116 .actual = src_info.return_type,
27117 .wanted = dest_info.return_type,
27109 .actual = src_info.return_type.toType(),
27110 .wanted = dest_info.return_type.toType(),
2711827111 } };
2711927112 }
2712027113 }
......@@ -27134,22 +27127,23 @@ fn coerceInMemoryAllowedFns(
2713427127 }
2713527128
2713627129 for (dest_info.param_types, 0..) |dest_param_ty, i| {
27137 const src_param_ty = src_info.param_types[i];
27130 const src_param_ty = src_info.param_types[i].toType();
2713827131
27139 if (dest_info.comptime_params[i] != src_info.comptime_params[i]) {
27132 const i_small = @intCast(u5, i);
27133 if (dest_info.paramIsComptime(i_small) != src_info.paramIsComptime(i_small)) {
2714027134 return InMemoryCoercionResult{ .fn_param_comptime = .{
2714127135 .index = i,
27142 .wanted = dest_info.comptime_params[i],
27136 .wanted = dest_info.paramIsComptime(i_small),
2714327137 } };
2714427138 }
2714527139
2714627140 // Note: Cast direction is reversed here.
27147 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src);
27141 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty.toType(), false, target, dest_src, src_src);
2714827142 if (param != .ok) {
2714927143 return InMemoryCoercionResult{ .fn_param = .{
2715027144 .child = try param.dupe(sema.arena),
2715127145 .actual = src_param_ty,
27152 .wanted = dest_param_ty,
27146 .wanted = dest_param_ty.toType(),
2715327147 .index = i,
2715427148 } };
2715527149 }
......@@ -31205,17 +31199,17 @@ fn resolvePeerTypes(
3120531199 return chosen_ty;
3120631200}
3120731201
31208pub fn resolveFnTypes(sema: *Sema, fn_info: Type.Payload.Function.Data) CompileError!void {
31202pub fn resolveFnTypes(sema: *Sema, fn_info: InternPool.Key.FuncType) CompileError!void {
3120931203 const mod = sema.mod;
31210 try sema.resolveTypeFully(fn_info.return_type);
31204 try sema.resolveTypeFully(fn_info.return_type.toType());
3121131205
31212 if (mod.comp.bin_file.options.error_return_tracing and fn_info.return_type.isError(mod)) {
31206 if (mod.comp.bin_file.options.error_return_tracing and fn_info.return_type.toType().isError(mod)) {
3121331207 // Ensure the type exists so that backends can assume that.
3121431208 _ = try sema.getBuiltinType("StackTrace");
3121531209 }
3121631210
3121731211 for (fn_info.param_types) |param_ty| {
31218 try sema.resolveTypeFully(param_ty);
31212 try sema.resolveTypeFully(param_ty.toType());
3121931213 }
3122031214}
3122131215
......@@ -31286,16 +31280,16 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
3128631280 return sema.resolveTypeLayout(payload_ty);
3128731281 },
3128831282 .Fn => {
31289 const info = ty.fnInfo();
31283 const info = mod.typeToFunc(ty).?;
3129031284 if (info.is_generic) {
3129131285 // Resolving of generic function types is deferred to when
3129231286 // the function is instantiated.
3129331287 return;
3129431288 }
3129531289 for (info.param_types) |param_ty| {
31296 try sema.resolveTypeLayout(param_ty);
31290 try sema.resolveTypeLayout(param_ty.toType());
3129731291 }
31298 try sema.resolveTypeLayout(info.return_type);
31292 try sema.resolveTypeLayout(info.return_type.toType());
3129931293 },
3130031294 else => {},
3130131295 }
......@@ -31615,15 +31609,13 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3161531609 .error_set_merged,
3161631610 => false,
3161731611
31618 .function => true,
31619
3162031612 .inferred_alloc_mut => unreachable,
3162131613 .inferred_alloc_const => unreachable,
3162231614
3162331615 .pointer => {
3162431616 const child_ty = ty.childType(mod);
3162531617 if (child_ty.zigTypeTag(mod) == .Fn) {
31626 return child_ty.fnInfo().is_generic;
31618 return mod.typeToFunc(child_ty).?.is_generic;
3162731619 } else {
3162831620 return sema.resolveTypeRequiresComptime(child_ty);
3162931621 }
......@@ -31644,7 +31636,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3164431636 .ptr_type => |ptr_type| {
3164531637 const child_ty = ptr_type.elem_type.toType();
3164631638 if (child_ty.zigTypeTag(mod) == .Fn) {
31647 return child_ty.fnInfo().is_generic;
31639 return mod.typeToFunc(child_ty).?.is_generic;
3164831640 } else {
3164931641 return sema.resolveTypeRequiresComptime(child_ty);
3165031642 }
......@@ -31653,6 +31645,8 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3165331645 .vector_type => |vector_type| return sema.resolveTypeRequiresComptime(vector_type.child.toType()),
3165431646 .opt_type => |child| return sema.resolveTypeRequiresComptime(child.toType()),
3165531647 .error_union_type => |error_union_type| return sema.resolveTypeRequiresComptime(error_union_type.payload_type.toType()),
31648 .func_type => true,
31649
3165631650 .simple_type => |t| switch (t) {
3165731651 .f16,
3165831652 .f32,
......@@ -31799,16 +31793,16 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
3179931793 },
3180031794 .ErrorUnion => return sema.resolveTypeFully(ty.errorUnionPayload()),
3180131795 .Fn => {
31802 const info = ty.fnInfo();
31796 const info = mod.typeToFunc(ty).?;
3180331797 if (info.is_generic) {
3180431798 // Resolving of generic function types is deferred to when
3180531799 // the function is instantiated.
3180631800 return;
3180731801 }
3180831802 for (info.param_types) |param_ty| {
31809 try sema.resolveTypeFully(param_ty);
31803 try sema.resolveTypeFully(param_ty.toType());
3181031804 }
31811 try sema.resolveTypeFully(info.return_type);
31805 try sema.resolveTypeFully(info.return_type.toType());
3181231806 },
3181331807 else => {},
3181431808 }
......@@ -31881,7 +31875,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
3188131875 .none => return ty,
3188231876
3188331877 .u1_type,
31884 .u5_type,
3188531878 .u8_type,
3188631879 .i8_type,
3188731880 .u16_type,
......@@ -31941,8 +31934,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
3194131934 .zero_u8 => unreachable,
3194231935 .one => unreachable,
3194331936 .one_usize => unreachable,
31944 .one_u5 => unreachable,
31945 .four_u5 => unreachable,
31937 .one_u8 => unreachable,
31938 .four_u8 => unreachable,
3194631939 .negative_one => unreachable,
3194731940 .calling_convention_c => unreachable,
3194831941 .calling_convention_inline => unreachable,
......@@ -32083,14 +32076,14 @@ fn resolveInferredErrorSet(
3208332076 // `*Module.Fn`. Not only is the function not relevant to the inferred error set
3208432077 // in this case, it may be a generic function which would cause an assertion failure
3208532078 // if we called `ensureFuncBodyAnalyzed` on it here.
32086 const ies_func_owner_decl = sema.mod.declPtr(ies.func.owner_decl);
32087 const ies_func_info = ies_func_owner_decl.ty.fnInfo();
32079 const ies_func_owner_decl = mod.declPtr(ies.func.owner_decl);
32080 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;
3208832081 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
3208932082 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,
3209032083 // so here we can simply skip this case.
32091 if (ies_func_info.return_type.isGenericPoison()) {
32084 if (ies_func_info.return_type == .generic_poison_type) {
3209232085 assert(ies_func_info.cc == .Inline);
32093 } else if (ies_func_info.return_type.errorUnionSet().castTag(.error_set_inferred).?.data == ies) {
32086 } else if (ies_func_info.return_type.toType().errorUnionSet().castTag(.error_set_inferred).?.data == ies) {
3209432087 if (ies_func_info.is_generic) {
3209532088 const msg = msg: {
3209632089 const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{});
......@@ -32285,7 +32278,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3228532278
3228632279 const prev_field_index = struct_obj.fields.getIndex(field_name).?;
3228732280 const prev_field_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{ .index = prev_field_index });
32288 try sema.mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});
32281 try mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});
3228932282 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});
3229032283 break :msg msg;
3229132284 };
......@@ -32387,7 +32380,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3238732380 .index = field_i,
3238832381 .range = .type,
3238932382 });
32390 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
32383 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(mod)});
3239132384 errdefer msg.destroy(sema.gpa);
3239232385
3239332386 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field.ty, .struct_field);
......@@ -32402,7 +32395,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3240232395 .index = field_i,
3240332396 .range = .type,
3240432397 });
32405 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
32398 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(mod)});
3240632399 errdefer msg.destroy(sema.gpa);
3240732400
3240832401 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field.ty);
......@@ -32580,7 +32573,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3258032573 // The provided type is an integer type and we must construct the enum tag type here.
3258132574 int_tag_ty = provided_ty;
3258232575 if (int_tag_ty.zigTypeTag(mod) != .Int and int_tag_ty.zigTypeTag(mod) != .ComptimeInt) {
32583 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(sema.mod)});
32576 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(mod)});
3258432577 }
3258532578
3258632579 if (fields_len > 0) {
......@@ -32590,7 +32583,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3259032583 const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{});
3259132584 errdefer msg.destroy(sema.gpa);
3259232585 try sema.errNote(&block_scope, tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{
32593 int_tag_ty.fmt(sema.mod),
32586 int_tag_ty.fmt(mod),
3259432587 fields_len - 1,
3259532588 });
3259632589 break :msg msg;
......@@ -32605,7 +32598,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3260532598 union_obj.tag_ty = provided_ty;
3260632599 const enum_type = switch (mod.intern_pool.indexToKey(union_obj.tag_ty.ip_index)) {
3260732600 .enum_type => |x| x,
32608 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(sema.mod)}),
32601 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(mod)}),
3260932602 };
3261032603 // The fields of the union must match the enum exactly.
3261132604 // A flag per field is used to check for missing and extraneous fields.
......@@ -32705,7 +32698,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3270532698 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;
3270632699 const other_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = gop.index }).lazy;
3270732700 const msg = msg: {
32708 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)});
32701 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, mod)});
3270932702 errdefer msg.destroy(gpa);
3271032703 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});
3271132704 break :msg msg;
......@@ -32751,7 +32744,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3275132744
3275232745 const prev_field_index = union_obj.fields.getIndex(field_name).?;
3275332746 const prev_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = prev_field_index }).lazy;
32754 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl, mod), msg, "other field here", .{});
32747 try mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl, mod), msg, "other field here", .{});
3275532748 try sema.errNote(&block_scope, src, msg, "union declared here", .{});
3275632749 break :msg msg;
3275732750 };
......@@ -32766,7 +32759,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3276632759 .range = .type,
3276732760 }).lazy;
3276832761 const msg = try sema.errMsg(&block_scope, ty_src, "no field named '{s}' in enum '{}'", .{
32769 field_name, union_obj.tag_ty.fmt(sema.mod),
32762 field_name, union_obj.tag_ty.fmt(mod),
3277032763 });
3277132764 errdefer msg.destroy(sema.gpa);
3277232765 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
......@@ -32800,7 +32793,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3280032793 .index = field_i,
3280132794 .range = .type,
3280232795 });
32803 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
32796 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)});
3280432797 errdefer msg.destroy(sema.gpa);
3280532798
3280632799 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field);
......@@ -32815,7 +32808,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3281532808 .index = field_i,
3281632809 .range = .type,
3281732810 });
32818 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
32811 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)});
3281932812 errdefer msg.destroy(sema.gpa);
3282032813
3282132814 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
......@@ -33060,7 +33053,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3306033053 .error_set,
3306133054 .error_set_merged,
3306233055 .error_union,
33063 .function,
3306433056 .error_set_inferred,
3306533057 .anyframe_T,
3306633058 .pointer,
......@@ -33087,7 +33079,12 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3308733079 return null;
3308833080 }
3308933081 },
33090 .ptr_type => null,
33082
33083 .ptr_type,
33084 .error_union_type,
33085 .func_type,
33086 => null,
33087
3309133088 .array_type => |array_type| {
3309233089 if (array_type.len == 0)
3309333090 return Value.initTag(.empty_array);
......@@ -33102,13 +33099,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3310233099 return null;
3310333100 },
3310433101 .opt_type => |child| {
33105 if (child.toType().isNoReturn()) {
33106 return Value.null;
33102 if (child == .noreturn_type) {
33103 return try mod.nullValue(ty);
3310733104 } else {
3310833105 return null;
3310933106 }
3311033107 },
33111 .error_union_type => null,
33108
3311233109 .simple_type => |t| switch (t) {
3311333110 .f16,
3311433111 .f32,
......@@ -33674,15 +33671,13 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3367433671 .error_set_merged,
3367533672 => false,
3367633673
33677 .function => true,
33678
3367933674 .inferred_alloc_mut => unreachable,
3368033675 .inferred_alloc_const => unreachable,
3368133676
3368233677 .pointer => {
3368333678 const child_ty = ty.childType(mod);
3368433679 if (child_ty.zigTypeTag(mod) == .Fn) {
33685 return child_ty.fnInfo().is_generic;
33680 return mod.typeToFunc(child_ty).?.is_generic;
3368633681 } else {
3368733682 return sema.typeRequiresComptime(child_ty);
3368833683 }
......@@ -33703,7 +33698,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3370333698 .ptr_type => |ptr_type| {
3370433699 const child_ty = ptr_type.elem_type.toType();
3370533700 if (child_ty.zigTypeTag(mod) == .Fn) {
33706 return child_ty.fnInfo().is_generic;
33701 return mod.typeToFunc(child_ty).?.is_generic;
3370733702 } else {
3370833703 return sema.typeRequiresComptime(child_ty);
3370933704 }
......@@ -33714,6 +33709,8 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3371433709 .error_union_type => |error_union_type| {
3371533710 return sema.typeRequiresComptime(error_union_type.payload_type.toType());
3371633711 },
33712 .func_type => true,
33713
3371733714 .simple_type => |t| return switch (t) {
3371833715 .f16,
3371933716 .f32,
......@@ -33870,7 +33867,8 @@ fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 {
3387033867
3387133868/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
3387233869pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
33873 const fn_info = ty.fnInfo();
33870 const mod = sema.mod;
33871 const fn_info = mod.typeToFunc(ty).?;
3387433872 if (fn_info.is_generic) return false;
3387533873 if (fn_info.is_var_args) return true;
3387633874 switch (fn_info.cc) {
......@@ -33878,7 +33876,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
3387833876 .Inline => return false,
3387933877 else => {},
3388033878 }
33881 if (try sema.typeRequiresComptime(fn_info.return_type)) {
33879 if (try sema.typeRequiresComptime(fn_info.return_type.toType())) {
3388233880 return false;
3388333881 }
3388433882 return true;
src/Zir.zig+2-3
......@@ -2052,7 +2052,6 @@ pub const Inst = struct {
20522052 /// and `[]Ref`.
20532053 pub const Ref = enum(u32) {
20542054 u1_type = @enumToInt(InternPool.Index.u1_type),
2055 u5_type = @enumToInt(InternPool.Index.u5_type),
20562055 u8_type = @enumToInt(InternPool.Index.u8_type),
20572056 i8_type = @enumToInt(InternPool.Index.i8_type),
20582057 u16_type = @enumToInt(InternPool.Index.u16_type),
......@@ -2121,8 +2120,8 @@ pub const Inst = struct {
21212120 zero_u8 = @enumToInt(InternPool.Index.zero_u8),
21222121 one = @enumToInt(InternPool.Index.one),
21232122 one_usize = @enumToInt(InternPool.Index.one_usize),
2124 one_u5 = @enumToInt(InternPool.Index.one_u5),
2125 four_u5 = @enumToInt(InternPool.Index.four_u5),
2123 one_u8 = @enumToInt(InternPool.Index.one_u8),
2124 four_u8 = @enumToInt(InternPool.Index.four_u8),
21262125 negative_one = @enumToInt(InternPool.Index.negative_one),
21272126 calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c),
21282127 calling_convention_inline = @enumToInt(InternPool.Index.calling_convention_inline),
src/arch/aarch64/CodeGen.zig+21-23
......@@ -472,7 +472,7 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
472472
473473fn gen(self: *Self) !void {
474474 const mod = self.bin_file.options.module.?;
475 const cc = self.fn_type.fnCallingConvention();
475 const cc = self.fn_type.fnCallingConvention(mod);
476476 if (cc != .Naked) {
477477 // stp fp, lr, [sp, #-16]!
478478 _ = try self.addInst(.{
......@@ -1146,7 +1146,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
11461146 .stack_offset => blk: {
11471147 // self.ret_mcv is an address to where this function
11481148 // should store its result into
1149 const ret_ty = self.fn_type.fnReturnType();
1149 const ret_ty = self.fn_type.fnReturnType(mod);
11501150 const ptr_ty = try mod.singleMutPtrType(ret_ty);
11511151
11521152 // addr_reg will contain the address of where to store the
......@@ -4271,7 +4271,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42714271
42724272 if (info.return_value == .stack_offset) {
42734273 log.debug("airCall: return by reference", .{});
4274 const ret_ty = fn_ty.fnReturnType();
4274 const ret_ty = fn_ty.fnReturnType(mod);
42754275 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));
42764276 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));
42774277 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);
......@@ -4428,10 +4428,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
44284428}
44294429
44304430fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4431 const mod = self.bin_file.options.module.?;
44314432 const un_op = self.air.instructions.items(.data)[inst].un_op;
44324433 const operand = try self.resolveInst(un_op);
4433 const ret_ty = self.fn_type.fnReturnType();
4434 const mod = self.bin_file.options.module.?;
4434 const ret_ty = self.fn_type.fnReturnType(mod);
44354435
44364436 switch (self.ret_mcv) {
44374437 .none => {},
......@@ -4460,10 +4460,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
44604460}
44614461
44624462fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4463 const mod = self.bin_file.options.module.?;
44634464 const un_op = self.air.instructions.items(.data)[inst].un_op;
44644465 const ptr = try self.resolveInst(un_op);
44654466 const ptr_ty = self.typeOf(un_op);
4466 const ret_ty = self.fn_type.fnReturnType();
4467 const ret_ty = self.fn_type.fnReturnType(mod);
44674468
44684469 switch (self.ret_mcv) {
44694470 .none => {},
......@@ -4483,7 +4484,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
44834484 // location.
44844485 const op_inst = Air.refToIndex(un_op).?;
44854486 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {
4486 const mod = self.bin_file.options.module.?;
44874487 const abi_size = @intCast(u32, ret_ty.abiSize(mod));
44884488 const abi_align = ret_ty.abiAlignment(mod);
44894489
......@@ -6226,12 +6226,11 @@ const CallMCValues = struct {
62266226
62276227/// Caller must call `CallMCValues.deinit`.
62286228fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6229 const cc = fn_ty.fnCallingConvention();
6230 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());
6231 defer self.gpa.free(param_types);
6232 fn_ty.fnParamTypes(param_types);
6229 const mod = self.bin_file.options.module.?;
6230 const fn_info = mod.typeToFunc(fn_ty).?;
6231 const cc = fn_info.cc;
62336232 var result: CallMCValues = .{
6234 .args = try self.gpa.alloc(MCValue, param_types.len),
6233 .args = try self.gpa.alloc(MCValue, fn_info.param_types.len),
62356234 // These undefined values must be populated before returning from this function.
62366235 .return_value = undefined,
62376236 .stack_byte_count = undefined,
......@@ -6239,8 +6238,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62396238 };
62406239 errdefer self.gpa.free(result.args);
62416240
6242 const ret_ty = fn_ty.fnReturnType();
6243 const mod = self.bin_file.options.module.?;
6241 const ret_ty = fn_ty.fnReturnType(mod);
62446242
62456243 switch (cc) {
62466244 .Naked => {
......@@ -6271,8 +6269,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62716269 }
62726270 }
62736271
6274 for (param_types, 0..) |ty, i| {
6275 const param_size = @intCast(u32, ty.abiSize(mod));
6272 for (fn_info.param_types, 0..) |ty, i| {
6273 const param_size = @intCast(u32, ty.toType().abiSize(mod));
62766274 if (param_size == 0) {
62776275 result.args[i] = .{ .none = {} };
62786276 continue;
......@@ -6280,14 +6278,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62806278
62816279 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned
62826280 // values to spread across odd-numbered registers.
6283 if (ty.abiAlignment(mod) == 16 and !self.target.isDarwin()) {
6281 if (ty.toType().abiAlignment(mod) == 16 and !self.target.isDarwin()) {
62846282 // Round up NCRN to the next even number
62856283 ncrn += ncrn % 2;
62866284 }
62876285
62886286 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
62896287 if (param_size <= 8) {
6290 result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty) };
6288 result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };
62916289 ncrn += 1;
62926290 } else {
62936291 return self.fail("TODO MCValues with multiple registers", .{});
......@@ -6298,7 +6296,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62986296 ncrn = 8;
62996297 // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided
63006298 // that the entire stack space consumed by the arguments is 8-byte aligned.
6301 if (ty.abiAlignment(mod) == 8) {
6299 if (ty.toType().abiAlignment(mod) == 8) {
63026300 if (nsaa % 8 != 0) {
63036301 nsaa += 8 - (nsaa % 8);
63046302 }
......@@ -6336,10 +6334,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
63366334
63376335 var stack_offset: u32 = 0;
63386336
6339 for (param_types, 0..) |ty, i| {
6340 if (ty.abiSize(mod) > 0) {
6341 const param_size = @intCast(u32, ty.abiSize(mod));
6342 const param_alignment = ty.abiAlignment(mod);
6337 for (fn_info.param_types, 0..) |ty, i| {
6338 if (ty.toType().abiSize(mod) > 0) {
6339 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6340 const param_alignment = ty.toType().abiAlignment(mod);
63436341
63446342 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
63456343 result.args[i] = .{ .stack_argument_offset = stack_offset };
src/arch/arm/CodeGen.zig+21-23
......@@ -478,7 +478,7 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
478478
479479fn gen(self: *Self) !void {
480480 const mod = self.bin_file.options.module.?;
481 const cc = self.fn_type.fnCallingConvention();
481 const cc = self.fn_type.fnCallingConvention(mod);
482482 if (cc != .Naked) {
483483 // push {fp, lr}
484484 const push_reloc = try self.addNop();
......@@ -1123,7 +1123,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
11231123 .stack_offset => blk: {
11241124 // self.ret_mcv is an address to where this function
11251125 // should store its result into
1126 const ret_ty = self.fn_type.fnReturnType();
1126 const ret_ty = self.fn_type.fnReturnType(mod);
11271127 const ptr_ty = try mod.singleMutPtrType(ret_ty);
11281128
11291129 // addr_reg will contain the address of where to store the
......@@ -4250,7 +4250,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42504250 // untouched by the parameter passing code
42514251 const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: {
42524252 log.debug("airCall: return by reference", .{});
4253 const ret_ty = fn_ty.fnReturnType();
4253 const ret_ty = fn_ty.fnReturnType(mod);
42544254 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));
42554255 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));
42564256 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);
......@@ -4350,7 +4350,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43504350 if (RegisterManager.indexOfRegIntoTracked(reg) == null) {
43514351 // Save function return value into a tracked register
43524352 log.debug("airCall: copying {} as it is not tracked", .{reg});
4353 const new_reg = try self.copyToTmpRegister(fn_ty.fnReturnType(), info.return_value);
4353 const new_reg = try self.copyToTmpRegister(fn_ty.fnReturnType(mod), info.return_value);
43544354 break :result MCValue{ .register = new_reg };
43554355 }
43564356 },
......@@ -4374,10 +4374,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43744374}
43754375
43764376fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4377 const mod = self.bin_file.options.module.?;
43774378 const un_op = self.air.instructions.items(.data)[inst].un_op;
43784379 const operand = try self.resolveInst(un_op);
4379 const ret_ty = self.fn_type.fnReturnType();
4380 const mod = self.bin_file.options.module.?;
4380 const ret_ty = self.fn_type.fnReturnType(mod);
43814381
43824382 switch (self.ret_mcv) {
43834383 .none => {},
......@@ -4406,10 +4406,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
44064406}
44074407
44084408fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4409 const mod = self.bin_file.options.module.?;
44094410 const un_op = self.air.instructions.items(.data)[inst].un_op;
44104411 const ptr = try self.resolveInst(un_op);
44114412 const ptr_ty = self.typeOf(un_op);
4412 const ret_ty = self.fn_type.fnReturnType();
4413 const ret_ty = self.fn_type.fnReturnType(mod);
44134414
44144415 switch (self.ret_mcv) {
44154416 .none => {},
......@@ -4429,7 +4430,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
44294430 // location.
44304431 const op_inst = Air.refToIndex(un_op).?;
44314432 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {
4432 const mod = self.bin_file.options.module.?;
44334433 const abi_size = @intCast(u32, ret_ty.abiSize(mod));
44344434 const abi_align = ret_ty.abiAlignment(mod);
44354435
......@@ -6171,12 +6171,11 @@ const CallMCValues = struct {
61716171
61726172/// Caller must call `CallMCValues.deinit`.
61736173fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6174 const cc = fn_ty.fnCallingConvention();
6175 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());
6176 defer self.gpa.free(param_types);
6177 fn_ty.fnParamTypes(param_types);
6174 const mod = self.bin_file.options.module.?;
6175 const fn_info = mod.typeToFunc(fn_ty).?;
6176 const cc = fn_info.cc;
61786177 var result: CallMCValues = .{
6179 .args = try self.gpa.alloc(MCValue, param_types.len),
6178 .args = try self.gpa.alloc(MCValue, fn_info.param_types.len),
61806179 // These undefined values must be populated before returning from this function.
61816180 .return_value = undefined,
61826181 .stack_byte_count = undefined,
......@@ -6184,8 +6183,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
61846183 };
61856184 errdefer self.gpa.free(result.args);
61866185
6187 const ret_ty = fn_ty.fnReturnType();
6188 const mod = self.bin_file.options.module.?;
6186 const ret_ty = fn_ty.fnReturnType(mod);
61896187
61906188 switch (cc) {
61916189 .Naked => {
......@@ -6219,11 +6217,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62196217 }
62206218 }
62216219
6222 for (param_types, 0..) |ty, i| {
6223 if (ty.abiAlignment(mod) == 8)
6220 for (fn_info.param_types, 0..) |ty, i| {
6221 if (ty.toType().abiAlignment(mod) == 8)
62246222 ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2);
62256223
6226 const param_size = @intCast(u32, ty.abiSize(mod));
6224 const param_size = @intCast(u32, ty.toType().abiSize(mod));
62276225 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
62286226 if (param_size <= 4) {
62296227 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };
......@@ -6235,7 +6233,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62356233 return self.fail("TODO MCValues split between registers and stack", .{});
62366234 } else {
62376235 ncrn = 4;
6238 if (ty.abiAlignment(mod) == 8)
6236 if (ty.toType().abiAlignment(mod) == 8)
62396237 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
62406238
62416239 result.args[i] = .{ .stack_argument_offset = nsaa };
......@@ -6269,10 +6267,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62696267
62706268 var stack_offset: u32 = 0;
62716269
6272 for (param_types, 0..) |ty, i| {
6273 if (ty.abiSize(mod) > 0) {
6274 const param_size = @intCast(u32, ty.abiSize(mod));
6275 const param_alignment = ty.abiAlignment(mod);
6270 for (fn_info.param_types, 0..) |ty, i| {
6271 if (ty.toType().abiSize(mod) > 0) {
6272 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6273 const param_alignment = ty.toType().abiAlignment(mod);
62766274
62776275 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
62786276 result.args[i] = .{ .stack_argument_offset = stack_offset };
src/arch/riscv64/CodeGen.zig+11-11
......@@ -347,7 +347,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
347347}
348348
349349fn gen(self: *Self) !void {
350 const cc = self.fn_type.fnCallingConvention();
350 const mod = self.bin_file.options.module.?;
351 const cc = self.fn_type.fnCallingConvention(mod);
351352 if (cc != .Naked) {
352353 // TODO Finish function prologue and epilogue for riscv64.
353354
......@@ -1803,7 +1804,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
18031804}
18041805
18051806fn ret(self: *Self, mcv: MCValue) !void {
1806 const ret_ty = self.fn_type.fnReturnType();
1807 const mod = self.bin_file.options.module.?;
1808 const ret_ty = self.fn_type.fnReturnType(mod);
18071809 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
18081810 // Just add space for an instruction, patch this later
18091811 const index = try self.addInst(.{
......@@ -2621,12 +2623,11 @@ const CallMCValues = struct {
26212623
26222624/// Caller must call `CallMCValues.deinit`.
26232625fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2624 const cc = fn_ty.fnCallingConvention();
2625 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());
2626 defer self.gpa.free(param_types);
2627 fn_ty.fnParamTypes(param_types);
2626 const mod = self.bin_file.options.module.?;
2627 const fn_info = mod.typeToFunc(fn_ty).?;
2628 const cc = fn_info.cc;
26282629 var result: CallMCValues = .{
2629 .args = try self.gpa.alloc(MCValue, param_types.len),
2630 .args = try self.gpa.alloc(MCValue, fn_info.param_types.len),
26302631 // These undefined values must be populated before returning from this function.
26312632 .return_value = undefined,
26322633 .stack_byte_count = undefined,
......@@ -2634,8 +2635,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26342635 };
26352636 errdefer self.gpa.free(result.args);
26362637
2637 const ret_ty = fn_ty.fnReturnType();
2638 const mod = self.bin_file.options.module.?;
2638 const ret_ty = fn_ty.fnReturnType(mod);
26392639
26402640 switch (cc) {
26412641 .Naked => {
......@@ -2655,8 +2655,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26552655 var next_stack_offset: u32 = 0;
26562656 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
26572657
2658 for (param_types, 0..) |ty, i| {
2659 const param_size = @intCast(u32, ty.abiSize(mod));
2658 for (fn_info.param_types, 0..) |ty, i| {
2659 const param_size = @intCast(u32, ty.toType().abiSize(mod));
26602660 if (param_size <= 8) {
26612661 if (next_register < argument_registers.len) {
26622662 result.args[i] = .{ .register = argument_registers[next_register] };
src/arch/sparc64/CodeGen.zig+11-11
......@@ -363,7 +363,8 @@ pub fn generate(
363363}
364364
365365fn gen(self: *Self) !void {
366 const cc = self.fn_type.fnCallingConvention();
366 const mod = self.bin_file.options.module.?;
367 const cc = self.fn_type.fnCallingConvention(mod);
367368 if (cc != .Naked) {
368369 // TODO Finish function prologue and epilogue for sparc64.
369370
......@@ -4458,12 +4459,11 @@ fn realStackOffset(off: u32) u32 {
44584459
44594460/// Caller must call `CallMCValues.deinit`.
44604461fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
4461 const cc = fn_ty.fnCallingConvention();
4462 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());
4463 defer self.gpa.free(param_types);
4464 fn_ty.fnParamTypes(param_types);
4462 const mod = self.bin_file.options.module.?;
4463 const fn_info = mod.typeToFunc(fn_ty).?;
4464 const cc = fn_info.cc;
44654465 var result: CallMCValues = .{
4466 .args = try self.gpa.alloc(MCValue, param_types.len),
4466 .args = try self.gpa.alloc(MCValue, fn_info.param_types.len),
44674467 // These undefined values must be populated before returning from this function.
44684468 .return_value = undefined,
44694469 .stack_byte_count = undefined,
......@@ -4471,8 +4471,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
44714471 };
44724472 errdefer self.gpa.free(result.args);
44734473
4474 const ret_ty = fn_ty.fnReturnType();
4475 const mod = self.bin_file.options.module.?;
4474 const ret_ty = fn_ty.fnReturnType(mod);
44764475
44774476 switch (cc) {
44784477 .Naked => {
......@@ -4495,8 +4494,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
44954494 .callee => abi.c_abi_int_param_regs_callee_view,
44964495 };
44974496
4498 for (param_types, 0..) |ty, i| {
4499 const param_size = @intCast(u32, ty.abiSize(mod));
4497 for (fn_info.param_types, 0..) |ty, i| {
4498 const param_size = @intCast(u32, ty.toType().abiSize(mod));
45004499 if (param_size <= 8) {
45014500 if (next_register < argument_registers.len) {
45024501 result.args[i] = .{ .register = argument_registers[next_register] };
......@@ -4580,7 +4579,8 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
45804579}
45814580
45824581fn ret(self: *Self, mcv: MCValue) !void {
4583 const ret_ty = self.fn_type.fnReturnType();
4582 const mod = self.bin_file.options.module.?;
4583 const ret_ty = self.fn_type.fnReturnType(mod);
45844584 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
45854585
45864586 // Just add space for a branch instruction, patch this later
src/arch/wasm/CodeGen.zig+45-47
......@@ -1145,7 +1145,7 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
11451145fn genFunctype(
11461146 gpa: Allocator,
11471147 cc: std.builtin.CallingConvention,
1148 params: []const Type,
1148 params: []const InternPool.Index,
11491149 return_type: Type,
11501150 mod: *Module,
11511151) !wasm.Type {
......@@ -1170,7 +1170,8 @@ fn genFunctype(
11701170 }
11711171
11721172 // param types
1173 for (params) |param_type| {
1173 for (params) |param_type_ip| {
1174 const param_type = param_type_ip.toType();
11741175 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;
11751176
11761177 switch (cc) {
......@@ -1234,9 +1235,9 @@ pub fn generate(
12341235}
12351236
12361237fn genFunc(func: *CodeGen) InnerError!void {
1237 const fn_info = func.decl.ty.fnInfo();
12381238 const mod = func.bin_file.base.options.module.?;
1239 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type, mod);
1239 const fn_info = mod.typeToFunc(func.decl.ty).?;
1240 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
12401241 defer func_type.deinit(func.gpa);
12411242 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);
12421243
......@@ -1345,10 +1346,8 @@ const CallWValues = struct {
13451346
13461347fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
13471348 const mod = func.bin_file.base.options.module.?;
1348 const cc = fn_ty.fnCallingConvention();
1349 const param_types = try func.gpa.alloc(Type, fn_ty.fnParamLen());
1350 defer func.gpa.free(param_types);
1351 fn_ty.fnParamTypes(param_types);
1349 const fn_info = mod.typeToFunc(fn_ty).?;
1350 const cc = fn_info.cc;
13521351 var result: CallWValues = .{
13531352 .args = &.{},
13541353 .return_value = .none,
......@@ -1360,8 +1359,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13601359
13611360 // Check if we store the result as a pointer to the stack rather than
13621361 // by value
1363 const fn_info = fn_ty.fnInfo();
1364 if (firstParamSRet(fn_info.cc, fn_info.return_type, mod)) {
1362 if (firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
13651363 // the sret arg will be passed as first argument, therefore we
13661364 // set the `return_value` before allocating locals for regular args.
13671365 result.return_value = .{ .local = .{ .value = func.local_index, .references = 1 } };
......@@ -1370,8 +1368,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13701368
13711369 switch (cc) {
13721370 .Unspecified => {
1373 for (param_types) |ty| {
1374 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
1371 for (fn_info.param_types) |ty| {
1372 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
13751373 continue;
13761374 }
13771375
......@@ -1380,8 +1378,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13801378 }
13811379 },
13821380 .C => {
1383 for (param_types) |ty| {
1384 const ty_classes = abi.classifyType(ty, mod);
1381 for (fn_info.param_types) |ty| {
1382 const ty_classes = abi.classifyType(ty.toType(), mod);
13851383 for (ty_classes) |class| {
13861384 if (class == .none) continue;
13871385 try args.append(.{ .local = .{ .value = func.local_index, .references = 1 } });
......@@ -2095,11 +2093,11 @@ fn genBody(func: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
20952093}
20962094
20972095fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2096 const mod = func.bin_file.base.options.module.?;
20982097 const un_op = func.air.instructions.items(.data)[inst].un_op;
20992098 const operand = try func.resolveInst(un_op);
2100 const fn_info = func.decl.ty.fnInfo();
2101 const ret_ty = fn_info.return_type;
2102 const mod = func.bin_file.base.options.module.?;
2099 const fn_info = mod.typeToFunc(func.decl.ty).?;
2100 const ret_ty = fn_info.return_type.toType();
21032101
21042102 // result must be stored in the stack and we return a pointer
21052103 // to the stack instead
......@@ -2146,8 +2144,8 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
21462144 break :result try func.allocStack(Type.usize); // create pointer to void
21472145 }
21482146
2149 const fn_info = func.decl.ty.fnInfo();
2150 if (firstParamSRet(fn_info.cc, fn_info.return_type, mod)) {
2147 const fn_info = mod.typeToFunc(func.decl.ty).?;
2148 if (firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
21512149 break :result func.return_value;
21522150 }
21532151
......@@ -2163,12 +2161,12 @@ fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
21632161 const operand = try func.resolveInst(un_op);
21642162 const ret_ty = func.typeOf(un_op).childType(mod);
21652163
2166 const fn_info = func.decl.ty.fnInfo();
2164 const fn_info = mod.typeToFunc(func.decl.ty).?;
21672165 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
21682166 if (ret_ty.isError(mod)) {
21692167 try func.addImm32(0);
21702168 }
2171 } else if (!firstParamSRet(fn_info.cc, fn_info.return_type, mod)) {
2169 } else if (!firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
21722170 // leave on the stack
21732171 _ = try func.load(operand, ret_ty, 0);
21742172 }
......@@ -2191,9 +2189,9 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
21912189 .Pointer => ty.childType(mod),
21922190 else => unreachable,
21932191 };
2194 const ret_ty = fn_ty.fnReturnType();
2195 const fn_info = fn_ty.fnInfo();
2196 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, mod);
2192 const ret_ty = fn_ty.fnReturnType(mod);
2193 const fn_info = mod.typeToFunc(fn_ty).?;
2194 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod);
21972195
21982196 const callee: ?Decl.Index = blk: {
21992197 const func_val = (try func.air.value(pl_op.operand, mod)) orelse break :blk null;
......@@ -2203,8 +2201,8 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22032201 break :blk function.data.owner_decl;
22042202 } else if (func_val.castTag(.extern_fn)) |extern_fn| {
22052203 const ext_decl = mod.declPtr(extern_fn.data.owner_decl);
2206 const ext_info = ext_decl.ty.fnInfo();
2207 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type, mod);
2204 const ext_info = mod.typeToFunc(ext_decl.ty).?;
2205 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);
22082206 defer func_type.deinit(func.gpa);
22092207 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_fn.data.owner_decl);
22102208 const atom = func.bin_file.getAtomPtr(atom_index);
......@@ -2235,7 +2233,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22352233 const arg_ty = func.typeOf(arg);
22362234 if (!arg_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
22372235
2238 try func.lowerArg(fn_ty.fnInfo().cc, arg_ty, arg_val);
2236 try func.lowerArg(mod.typeToFunc(fn_ty).?.cc, arg_ty, arg_val);
22392237 }
22402238
22412239 if (callee) |direct| {
......@@ -2248,7 +2246,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22482246 const operand = try func.resolveInst(pl_op.operand);
22492247 try func.emitWValue(operand);
22502248
2251 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type, mod);
2249 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
22522250 defer fn_type.deinit(func.gpa);
22532251
22542252 const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);
......@@ -2264,7 +2262,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22642262 } else if (first_param_sret) {
22652263 break :result_value sret;
22662264 // TODO: Make this less fragile and optimize
2267 } else if (fn_ty.fnInfo().cc == .C and ret_ty.zigTypeTag(mod) == .Struct or ret_ty.zigTypeTag(mod) == .Union) {
2265 } else if (mod.typeToFunc(fn_ty).?.cc == .C and ret_ty.zigTypeTag(mod) == .Struct or ret_ty.zigTypeTag(mod) == .Union) {
22682266 const result_local = try func.allocLocal(ret_ty);
22692267 try func.addLabel(.local_set, result_local.local.value);
22702268 const scalar_type = abi.scalarType(ret_ty, mod);
......@@ -2528,7 +2526,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
25282526 const mod = func.bin_file.base.options.module.?;
25292527 const arg_index = func.arg_index;
25302528 const arg = func.args[arg_index];
2531 const cc = func.decl.ty.fnInfo().cc;
2529 const cc = mod.typeToFunc(func.decl.ty).?.cc;
25322530 const arg_ty = func.typeOfIndex(inst);
25332531 if (cc == .C) {
25342532 const arg_classes = abi.classifyType(arg_ty, mod);
......@@ -2647,9 +2645,9 @@ fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) Inner
26472645 }
26482646
26492647 switch (op) {
2650 .mul => return func.callIntrinsic("__multi3", &.{ ty, ty }, ty, &.{ lhs, rhs }),
2651 .shr => return func.callIntrinsic("__lshrti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }),
2652 .shl => return func.callIntrinsic("__ashlti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }),
2648 .mul => return func.callIntrinsic("__multi3", &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }),
2649 .shr => return func.callIntrinsic("__lshrti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }),
2650 .shl => return func.callIntrinsic("__ashlti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }),
26532651 .xor => {
26542652 const result = try func.allocStack(ty);
26552653 try func.emitWValue(result);
......@@ -2839,7 +2837,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In
28392837 };
28402838
28412839 // fma requires three operands
2842 var param_types_buffer: [3]Type = .{ ty, ty, ty };
2840 var param_types_buffer: [3]InternPool.Index = .{ ty.ip_index, ty.ip_index, ty.ip_index };
28432841 const param_types = param_types_buffer[0..args.len];
28442842 return func.callIntrinsic(fn_name, param_types, ty, args);
28452843}
......@@ -5298,7 +5296,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
52985296 // call __extendhfsf2(f16) f32
52995297 const f32_result = try func.callIntrinsic(
53005298 "__extendhfsf2",
5301 &.{Type.f16},
5299 &.{.f16_type},
53025300 Type.f32,
53035301 &.{operand},
53045302 );
......@@ -5316,7 +5314,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
53165314 target_util.compilerRtFloatAbbrev(wanted_bits),
53175315 }) catch unreachable;
53185316
5319 return func.callIntrinsic(fn_name, &.{given}, wanted, &.{operand});
5317 return func.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand});
53205318}
53215319
53225320fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5347,7 +5345,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
53475345 } else operand;
53485346
53495347 // call __truncsfhf2(f32) f16
5350 return func.callIntrinsic("__truncsfhf2", &.{Type.f32}, Type.f16, &.{op});
5348 return func.callIntrinsic("__truncsfhf2", &.{.f32_type}, Type.f16, &.{op});
53515349 }
53525350
53535351 var fn_name_buf: [12]u8 = undefined;
......@@ -5356,7 +5354,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
53565354 target_util.compilerRtFloatAbbrev(wanted_bits),
53575355 }) catch unreachable;
53585356
5359 return func.callIntrinsic(fn_name, &.{given}, wanted, &.{operand});
5357 return func.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand});
53605358}
53615359
53625360fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
......@@ -5842,7 +5840,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58425840
58435841 const bin_op = try func.callIntrinsic(
58445842 "__multi3",
5845 &[_]Type{Type.i64} ** 4,
5843 &[_]InternPool.Index{.i64_type} ** 4,
58465844 Type.i128,
58475845 &.{ lhs, lhs_shifted, rhs, rhs_shifted },
58485846 );
......@@ -5866,19 +5864,19 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58665864
58675865 const mul1 = try func.callIntrinsic(
58685866 "__multi3",
5869 &[_]Type{Type.i64} ** 4,
5867 &[_]InternPool.Index{.i64_type} ** 4,
58705868 Type.i128,
58715869 &.{ lhs_lsb, zero, rhs_msb, zero },
58725870 );
58735871 const mul2 = try func.callIntrinsic(
58745872 "__multi3",
5875 &[_]Type{Type.i64} ** 4,
5873 &[_]InternPool.Index{.i64_type} ** 4,
58765874 Type.i128,
58775875 &.{ rhs_lsb, zero, lhs_msb, zero },
58785876 );
58795877 const mul3 = try func.callIntrinsic(
58805878 "__multi3",
5881 &[_]Type{Type.i64} ** 4,
5879 &[_]InternPool.Index{.i64_type} ** 4,
58825880 Type.i128,
58835881 &.{ lhs_msb, zero, rhs_msb, zero },
58845882 );
......@@ -5977,7 +5975,7 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
59775975 // call to compiler-rt `fn fmaf(f32, f32, f32) f32`
59785976 var result = try func.callIntrinsic(
59795977 "fmaf",
5980 &.{ Type.f32, Type.f32, Type.f32 },
5978 &.{ .f32_type, .f32_type, .f32_type },
59815979 Type.f32,
59825980 &.{ rhs_ext, lhs_ext, addend_ext },
59835981 );
......@@ -6707,7 +6705,7 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67076705fn callIntrinsic(
67086706 func: *CodeGen,
67096707 name: []const u8,
6710 param_types: []const Type,
6708 param_types: []const InternPool.Index,
67116709 return_type: Type,
67126710 args: []const WValue,
67136711) InnerError!WValue {
......@@ -6735,8 +6733,8 @@ fn callIntrinsic(
67356733 // Lower all arguments to the stack before we call our function
67366734 for (args, 0..) |arg, arg_i| {
67376735 assert(!(want_sret_param and arg == .stack));
6738 assert(param_types[arg_i].hasRuntimeBitsIgnoreComptime(mod));
6739 try func.lowerArg(.C, param_types[arg_i], arg);
6736 assert(param_types[arg_i].toType().hasRuntimeBitsIgnoreComptime(mod));
6737 try func.lowerArg(.C, param_types[arg_i].toType(), arg);
67406738 }
67416739
67426740 // Actually call our intrinsic
......@@ -6938,7 +6936,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
69386936 try writer.writeByte(std.wasm.opcode(.end));
69396937
69406938 const slice_ty = Type.const_slice_u8_sentinel_0;
6941 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty}, slice_ty, mod);
6939 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, mod);
69426940 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);
69436941}
69446942
src/arch/x86_64/CodeGen.zig+22-12
......@@ -26,6 +26,7 @@ const Liveness = @import("../../Liveness.zig");
2626const Lower = @import("Lower.zig");
2727const Mir = @import("Mir.zig");
2828const Module = @import("../../Module.zig");
29const InternPool = @import("../../InternPool.zig");
2930const Target = std.Target;
3031const Type = @import("../../type.zig").Type;
3132const TypedValue = @import("../../TypedValue.zig");
......@@ -697,7 +698,8 @@ pub fn generate(
697698 FrameAlloc.init(.{ .size = 0, .alignment = 1 }),
698699 );
699700
700 var call_info = function.resolveCallingConventionValues(fn_type, &.{}, .args_frame) catch |err| switch (err) {
701 const fn_info = mod.typeToFunc(fn_type).?;
702 var call_info = function.resolveCallingConventionValues(fn_info, &.{}, .args_frame) catch |err| switch (err) {
701703 error.CodegenFail => return Result{ .fail = function.err_msg.? },
702704 error.OutOfRegisters => return Result{
703705 .fail = try ErrorMsg.create(
......@@ -1566,7 +1568,7 @@ fn asmMemoryRegisterImmediate(
15661568
15671569fn gen(self: *Self) InnerError!void {
15681570 const mod = self.bin_file.options.module.?;
1569 const cc = self.fn_type.fnCallingConvention();
1571 const cc = self.fn_type.fnCallingConvention(mod);
15701572 if (cc != .Naked) {
15711573 try self.asmRegister(.{ ._, .push }, .rbp);
15721574 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
......@@ -8042,7 +8044,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
80428044 else => unreachable,
80438045 };
80448046
8045 var info = try self.resolveCallingConventionValues(fn_ty, args[fn_ty.fnParamLen()..], .call_frame);
8047 const fn_info = mod.typeToFunc(fn_ty).?;
8048
8049 var info = try self.resolveCallingConventionValues(fn_info, args[fn_info.param_types.len..], .call_frame);
80468050 defer info.deinit(self);
80478051
80488052 // We need a properly aligned and sized call frame to be able to call this function.
......@@ -8083,7 +8087,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
80838087 const ret_lock = switch (info.return_value.long) {
80848088 .none, .unreach => null,
80858089 .indirect => |reg_off| lock: {
8086 const ret_ty = fn_ty.fnReturnType();
8090 const ret_ty = fn_info.return_type.toType();
80878091 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));
80888092 try self.genSetReg(reg_off.reg, Type.usize, .{
80898093 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
......@@ -8199,9 +8203,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81998203}
82008204
82018205fn airRet(self: *Self, inst: Air.Inst.Index) !void {
8206 const mod = self.bin_file.options.module.?;
82028207 const un_op = self.air.instructions.items(.data)[inst].un_op;
82038208 const operand = try self.resolveInst(un_op);
8204 const ret_ty = self.fn_type.fnReturnType();
8209 const ret_ty = self.fn_type.fnReturnType(mod);
82058210 switch (self.ret_mcv.short) {
82068211 .none => {},
82078212 .register => try self.genCopy(ret_ty, self.ret_mcv.short, operand),
......@@ -11683,18 +11688,23 @@ const CallMCValues = struct {
1168311688/// Caller must call `CallMCValues.deinit`.
1168411689fn resolveCallingConventionValues(
1168511690 self: *Self,
11686 fn_ty: Type,
11691 fn_info: InternPool.Key.FuncType,
1168711692 var_args: []const Air.Inst.Ref,
1168811693 stack_frame_base: FrameIndex,
1168911694) !CallMCValues {
1169011695 const mod = self.bin_file.options.module.?;
11691 const cc = fn_ty.fnCallingConvention();
11692 const param_len = fn_ty.fnParamLen();
11693 const param_types = try self.gpa.alloc(Type, param_len + var_args.len);
11696 const cc = fn_info.cc;
11697 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
1169411698 defer self.gpa.free(param_types);
11695 fn_ty.fnParamTypes(param_types);
11699
11700 for (param_types[0..fn_info.param_types.len], fn_info.param_types) |*dest, src| {
11701 dest.* = src.toType();
11702 }
1169611703 // TODO: promote var arg types
11697 for (param_types[param_len..], var_args) |*param_ty, arg| param_ty.* = self.typeOf(arg);
11704 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg| {
11705 param_ty.* = self.typeOf(arg);
11706 }
11707
1169811708 var result: CallMCValues = .{
1169911709 .args = try self.gpa.alloc(MCValue, param_types.len),
1170011710 // These undefined values must be populated before returning from this function.
......@@ -11704,7 +11714,7 @@ fn resolveCallingConventionValues(
1170411714 };
1170511715 errdefer self.gpa.free(result.args);
1170611716
11707 const ret_ty = fn_ty.fnReturnType();
11717 const ret_ty = fn_info.return_type.toType();
1170811718
1170911719 switch (cc) {
1171011720 .Naked => {
src/codegen.zig+1-1
......@@ -1081,7 +1081,7 @@ fn genDeclRef(
10811081
10821082 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
10831083 if (tv.ty.castPtrToFn(mod)) |fn_ty| {
1084 if (fn_ty.fnInfo().is_generic) {
1084 if (mod.typeToFunc(fn_ty).?.is_generic) {
10851085 return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod) });
10861086 }
10871087 } else if (tv.ty.zigTypeTag(mod) == .Pointer) {
src/codegen/c.zig+7-6
......@@ -1507,7 +1507,7 @@ pub const DeclGen = struct {
15071507 const fn_decl = mod.declPtr(fn_decl_index);
15081508 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);
15091509
1510 const fn_info = fn_decl.ty.fnInfo();
1510 const fn_info = mod.typeToFunc(fn_decl.ty).?;
15111511 if (fn_info.cc == .Naked) {
15121512 switch (kind) {
15131513 .forward => try w.writeAll("zig_naked_decl "),
......@@ -1517,7 +1517,7 @@ pub const DeclGen = struct {
15171517 }
15181518 if (fn_decl.val.castTag(.function)) |func_payload|
15191519 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
1520 if (fn_info.return_type.ip_index == .noreturn_type) try w.writeAll("zig_noreturn ");
1520 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
15211521
15221522 const trailing = try renderTypePrefix(
15231523 dg.decl_index,
......@@ -3455,7 +3455,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
34553455 } else {
34563456 try reap(f, inst, &.{un_op});
34573457 // Not even allowed to return void in a naked function.
3458 if (if (f.object.dg.decl) |decl| decl.ty.fnCallingConvention() != .Naked else true)
3458 if (if (f.object.dg.decl) |decl| decl.ty.fnCallingConvention(mod) != .Naked else true)
34593459 try writer.writeAll("return;\n");
34603460 }
34613461 return .none;
......@@ -4094,7 +4094,7 @@ fn airCall(
40944094) !CValue {
40954095 const mod = f.object.dg.module;
40964096 // Not even allowed to call panic in a naked function.
4097 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() == .Naked) return .none;
4097 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention(mod) == .Naked) return .none;
40984098
40994099 const gpa = f.object.dg.gpa;
41004100 const writer = f.object.writer();
......@@ -4143,7 +4143,7 @@ fn airCall(
41434143 else => unreachable,
41444144 };
41454145
4146 const ret_ty = fn_ty.fnReturnType();
4146 const ret_ty = fn_ty.fnReturnType(mod);
41474147 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
41484148
41494149 const result_local = result: {
......@@ -4622,8 +4622,9 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {
46224622}
46234623
46244624fn airUnreach(f: *Function) !CValue {
4625 const mod = f.object.dg.module;
46254626 // Not even allowed to call unreachable in a naked function.
4626 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() == .Naked) return .none;
4627 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention(mod) == .Naked) return .none;
46274628
46284629 try f.object.writer().writeAll("zig_unreachable();\n");
46294630 return .none;
src/codegen/c/type.zig+17-17
......@@ -1720,7 +1720,7 @@ pub const CType = extern union {
17201720 .Opaque => self.init(.void),
17211721
17221722 .Fn => {
1723 const info = ty.fnInfo();
1723 const info = mod.typeToFunc(ty).?;
17241724 if (!info.is_generic) {
17251725 if (lookup.isMutable()) {
17261726 const param_kind: Kind = switch (kind) {
......@@ -1728,10 +1728,10 @@ pub const CType = extern union {
17281728 .complete, .parameter, .global => .parameter,
17291729 .payload => unreachable,
17301730 };
1731 _ = try lookup.typeToIndex(info.return_type, param_kind);
1731 _ = try lookup.typeToIndex(info.return_type.toType(), param_kind);
17321732 for (info.param_types) |param_type| {
1733 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;
1734 _ = try lookup.typeToIndex(param_type, param_kind);
1733 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
1734 _ = try lookup.typeToIndex(param_type.toType(), param_kind);
17351735 }
17361736 }
17371737 self.init(if (info.is_var_args) .varargs_function else .function);
......@@ -2013,7 +2013,7 @@ pub const CType = extern union {
20132013 .function,
20142014 .varargs_function,
20152015 => {
2016 const info = ty.fnInfo();
2016 const info = mod.typeToFunc(ty).?;
20172017 assert(!info.is_generic);
20182018 const param_kind: Kind = switch (kind) {
20192019 .forward, .forward_parameter => .forward_parameter,
......@@ -2023,21 +2023,21 @@ pub const CType = extern union {
20232023
20242024 var c_params_len: usize = 0;
20252025 for (info.param_types) |param_type| {
2026 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;
2026 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
20272027 c_params_len += 1;
20282028 }
20292029
20302030 const params_pl = try arena.alloc(Index, c_params_len);
20312031 var c_param_i: usize = 0;
20322032 for (info.param_types) |param_type| {
2033 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;
2034 params_pl[c_param_i] = store.set.typeToIndex(param_type, mod, param_kind).?;
2033 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2034 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
20352035 c_param_i += 1;
20362036 }
20372037
20382038 const fn_pl = try arena.create(Payload.Function);
20392039 fn_pl.* = .{ .base = .{ .tag = t }, .data = .{
2040 .return_type = store.set.typeToIndex(info.return_type, mod, param_kind).?,
2040 .return_type = store.set.typeToIndex(info.return_type.toType(), mod, param_kind).?,
20412041 .param_types = params_pl,
20422042 } };
20432043 return initPayload(fn_pl);
......@@ -2145,7 +2145,7 @@ pub const CType = extern union {
21452145 => {
21462146 if (ty.zigTypeTag(mod) != .Fn) return false;
21472147
2148 const info = ty.fnInfo();
2148 const info = mod.typeToFunc(ty).?;
21492149 assert(!info.is_generic);
21502150 const data = cty.cast(Payload.Function).?.data;
21512151 const param_kind: Kind = switch (self.kind) {
......@@ -2154,18 +2154,18 @@ pub const CType = extern union {
21542154 .payload => unreachable,
21552155 };
21562156
2157 if (!self.eqlRecurse(info.return_type, data.return_type, param_kind))
2157 if (!self.eqlRecurse(info.return_type.toType(), data.return_type, param_kind))
21582158 return false;
21592159
21602160 var c_param_i: usize = 0;
21612161 for (info.param_types) |param_type| {
2162 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;
2162 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
21632163
21642164 if (c_param_i >= data.param_types.len) return false;
21652165 const param_cty = data.param_types[c_param_i];
21662166 c_param_i += 1;
21672167
2168 if (!self.eqlRecurse(param_type, param_cty, param_kind))
2168 if (!self.eqlRecurse(param_type.toType(), param_cty, param_kind))
21692169 return false;
21702170 }
21712171 return c_param_i == data.param_types.len;
......@@ -2258,7 +2258,7 @@ pub const CType = extern union {
22582258 .function,
22592259 .varargs_function,
22602260 => {
2261 const info = ty.fnInfo();
2261 const info = mod.typeToFunc(ty).?;
22622262 assert(!info.is_generic);
22632263 const param_kind: Kind = switch (self.kind) {
22642264 .forward, .forward_parameter => .forward_parameter,
......@@ -2266,10 +2266,10 @@ pub const CType = extern union {
22662266 .payload => unreachable,
22672267 };
22682268
2269 self.updateHasherRecurse(hasher, info.return_type, param_kind);
2269 self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);
22702270 for (info.param_types) |param_type| {
2271 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;
2272 self.updateHasherRecurse(hasher, param_type, param_kind);
2271 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2272 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
22732273 }
22742274 },
22752275
src/codegen/llvm.zig+117-118
......@@ -954,17 +954,17 @@ pub const Object = struct {
954954 builder.positionBuilderAtEnd(entry_block);
955955
956956 // This gets the LLVM values from the function and stores them in `dg.args`.
957 const fn_info = decl.ty.fnInfo();
957 const fn_info = mod.typeToFunc(decl.ty).?;
958958 const sret = firstParamSRet(fn_info, mod);
959959 const ret_ptr = if (sret) llvm_func.getParam(0) else null;
960960 const gpa = dg.gpa;
961961
962 if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type)) |s| switch (s) {
962 if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) {
963963 .signed => dg.addAttr(llvm_func, 0, "signext"),
964964 .unsigned => dg.addAttr(llvm_func, 0, "zeroext"),
965965 };
966966
967 const err_return_tracing = fn_info.return_type.isError(mod) and
967 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
968968 mod.comp.bin_file.options.error_return_tracing;
969969
970970 const err_ret_trace = if (err_return_tracing)
......@@ -986,7 +986,7 @@ pub const Object = struct {
986986 .byval => {
987987 assert(!it.byval_attr);
988988 const param_index = it.zig_index - 1;
989 const param_ty = fn_info.param_types[param_index];
989 const param_ty = fn_info.param_types[param_index].toType();
990990 const param = llvm_func.getParam(llvm_arg_i);
991991 try args.ensureUnusedCapacity(1);
992992
......@@ -1005,7 +1005,7 @@ pub const Object = struct {
10051005 llvm_arg_i += 1;
10061006 },
10071007 .byref => {
1008 const param_ty = fn_info.param_types[it.zig_index - 1];
1008 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
10091009 const param_llvm_ty = try dg.lowerType(param_ty);
10101010 const param = llvm_func.getParam(llvm_arg_i);
10111011 const alignment = param_ty.abiAlignment(mod);
......@@ -1024,7 +1024,7 @@ pub const Object = struct {
10241024 }
10251025 },
10261026 .byref_mut => {
1027 const param_ty = fn_info.param_types[it.zig_index - 1];
1027 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
10281028 const param_llvm_ty = try dg.lowerType(param_ty);
10291029 const param = llvm_func.getParam(llvm_arg_i);
10301030 const alignment = param_ty.abiAlignment(mod);
......@@ -1044,7 +1044,7 @@ pub const Object = struct {
10441044 },
10451045 .abi_sized_int => {
10461046 assert(!it.byval_attr);
1047 const param_ty = fn_info.param_types[it.zig_index - 1];
1047 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
10481048 const param = llvm_func.getParam(llvm_arg_i);
10491049 llvm_arg_i += 1;
10501050
......@@ -1071,7 +1071,7 @@ pub const Object = struct {
10711071 },
10721072 .slice => {
10731073 assert(!it.byval_attr);
1074 const param_ty = fn_info.param_types[it.zig_index - 1];
1074 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
10751075 const ptr_info = param_ty.ptrInfo(mod);
10761076
10771077 if (math.cast(u5, it.zig_index - 1)) |i| {
......@@ -1104,7 +1104,7 @@ pub const Object = struct {
11041104 .multiple_llvm_types => {
11051105 assert(!it.byval_attr);
11061106 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];
1107 const param_ty = fn_info.param_types[it.zig_index - 1];
1107 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
11081108 const param_llvm_ty = try dg.lowerType(param_ty);
11091109 const param_alignment = param_ty.abiAlignment(mod);
11101110 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
......@@ -1135,7 +1135,7 @@ pub const Object = struct {
11351135 args.appendAssumeCapacity(casted);
11361136 },
11371137 .float_array => {
1138 const param_ty = fn_info.param_types[it.zig_index - 1];
1138 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
11391139 const param_llvm_ty = try dg.lowerType(param_ty);
11401140 const param = llvm_func.getParam(llvm_arg_i);
11411141 llvm_arg_i += 1;
......@@ -1153,7 +1153,7 @@ pub const Object = struct {
11531153 }
11541154 },
11551155 .i32_array, .i64_array => {
1156 const param_ty = fn_info.param_types[it.zig_index - 1];
1156 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
11571157 const param_llvm_ty = try dg.lowerType(param_ty);
11581158 const param = llvm_func.getParam(llvm_arg_i);
11591159 llvm_arg_i += 1;
......@@ -1182,7 +1182,7 @@ pub const Object = struct {
11821182 const line_number = decl.src_line + 1;
11831183 const is_internal_linkage = decl.val.tag() != .extern_fn and
11841184 !mod.decl_exports.contains(decl_index);
1185 const noret_bit: c_uint = if (fn_info.return_type.isNoReturn())
1185 const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)
11861186 llvm.DIFlags.NoReturn
11871187 else
11881188 0;
......@@ -2331,26 +2331,26 @@ pub const Object = struct {
23312331 return full_di_ty;
23322332 },
23332333 .Fn => {
2334 const fn_info = ty.fnInfo();
2334 const fn_info = mod.typeToFunc(ty).?;
23352335
23362336 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);
23372337 defer param_di_types.deinit();
23382338
23392339 // Return type goes first.
2340 if (fn_info.return_type.hasRuntimeBitsIgnoreComptime(mod)) {
2340 if (fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) {
23412341 const sret = firstParamSRet(fn_info, mod);
2342 const di_ret_ty = if (sret) Type.void else fn_info.return_type;
2342 const di_ret_ty = if (sret) Type.void else fn_info.return_type.toType();
23432343 try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full));
23442344
23452345 if (sret) {
2346 const ptr_ty = try mod.singleMutPtrType(fn_info.return_type);
2346 const ptr_ty = try mod.singleMutPtrType(fn_info.return_type.toType());
23472347 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
23482348 }
23492349 } else {
23502350 try param_di_types.append(try o.lowerDebugType(Type.void, .full));
23512351 }
23522352
2353 if (fn_info.return_type.isError(mod) and
2353 if (fn_info.return_type.toType().isError(mod) and
23542354 o.module.comp.bin_file.options.error_return_tracing)
23552355 {
23562356 const ptr_ty = try mod.singleMutPtrType(o.getStackTraceType());
......@@ -2358,13 +2358,13 @@ pub const Object = struct {
23582358 }
23592359
23602360 for (fn_info.param_types) |param_ty| {
2361 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
2361 if (!param_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
23622362
2363 if (isByRef(param_ty, mod)) {
2364 const ptr_ty = try mod.singleMutPtrType(param_ty);
2363 if (isByRef(param_ty.toType(), mod)) {
2364 const ptr_ty = try mod.singleMutPtrType(param_ty.toType());
23652365 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
23662366 } else {
2367 try param_di_types.append(try o.lowerDebugType(param_ty, .full));
2367 try param_di_types.append(try o.lowerDebugType(param_ty.toType(), .full));
23682368 }
23692369 }
23702370
......@@ -2565,7 +2565,7 @@ pub const DeclGen = struct {
25652565 if (gop.found_existing) return gop.value_ptr.*;
25662566
25672567 assert(decl.has_tv);
2568 const fn_info = zig_fn_type.fnInfo();
2568 const fn_info = mod.typeToFunc(zig_fn_type).?;
25692569 const target = mod.getTarget();
25702570 const sret = firstParamSRet(fn_info, mod);
25712571
......@@ -2598,11 +2598,11 @@ pub const DeclGen = struct {
25982598 dg.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 0
25992599 dg.addArgAttr(llvm_fn, 0, "noalias");
26002600
2601 const raw_llvm_ret_ty = try dg.lowerType(fn_info.return_type);
2601 const raw_llvm_ret_ty = try dg.lowerType(fn_info.return_type.toType());
26022602 llvm_fn.addSretAttr(raw_llvm_ret_ty);
26032603 }
26042604
2605 const err_return_tracing = fn_info.return_type.isError(mod) and
2605 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
26062606 mod.comp.bin_file.options.error_return_tracing;
26072607
26082608 if (err_return_tracing) {
......@@ -2626,13 +2626,13 @@ pub const DeclGen = struct {
26262626 }
26272627
26282628 if (fn_info.alignment != 0) {
2629 llvm_fn.setAlignment(fn_info.alignment);
2629 llvm_fn.setAlignment(@intCast(c_uint, fn_info.alignment));
26302630 }
26312631
26322632 // Function attributes that are independent of analysis results of the function body.
26332633 dg.addCommonFnAttributes(llvm_fn);
26342634
2635 if (fn_info.return_type.isNoReturn()) {
2635 if (fn_info.return_type == .noreturn_type) {
26362636 dg.addFnAttr(llvm_fn, "noreturn");
26372637 }
26382638
......@@ -2645,15 +2645,15 @@ pub const DeclGen = struct {
26452645 while (it.next()) |lowering| switch (lowering) {
26462646 .byval => {
26472647 const param_index = it.zig_index - 1;
2648 const param_ty = fn_info.param_types[param_index];
2648 const param_ty = fn_info.param_types[param_index].toType();
26492649 if (!isByRef(param_ty, mod)) {
26502650 dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
26512651 }
26522652 },
26532653 .byref => {
26542654 const param_ty = fn_info.param_types[it.zig_index - 1];
2655 const param_llvm_ty = try dg.lowerType(param_ty);
2656 const alignment = param_ty.abiAlignment(mod);
2655 const param_llvm_ty = try dg.lowerType(param_ty.toType());
2656 const alignment = param_ty.toType().abiAlignment(mod);
26572657 dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
26582658 },
26592659 .byref_mut => {
......@@ -3142,7 +3142,7 @@ pub const DeclGen = struct {
31423142
31433143 fn lowerTypeFn(dg: *DeclGen, fn_ty: Type) Allocator.Error!*llvm.Type {
31443144 const mod = dg.module;
3145 const fn_info = fn_ty.fnInfo();
3145 const fn_info = mod.typeToFunc(fn_ty).?;
31463146 const llvm_ret_ty = try lowerFnRetTy(dg, fn_info);
31473147
31483148 var llvm_params = std.ArrayList(*llvm.Type).init(dg.gpa);
......@@ -3152,7 +3152,7 @@ pub const DeclGen = struct {
31523152 try llvm_params.append(dg.context.pointerType(0));
31533153 }
31543154
3155 if (fn_info.return_type.isError(mod) and
3155 if (fn_info.return_type.toType().isError(mod) and
31563156 mod.comp.bin_file.options.error_return_tracing)
31573157 {
31583158 const ptr_ty = try mod.singleMutPtrType(dg.object.getStackTraceType());
......@@ -3163,19 +3163,19 @@ pub const DeclGen = struct {
31633163 while (it.next()) |lowering| switch (lowering) {
31643164 .no_bits => continue,
31653165 .byval => {
3166 const param_ty = fn_info.param_types[it.zig_index - 1];
3166 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
31673167 try llvm_params.append(try dg.lowerType(param_ty));
31683168 },
31693169 .byref, .byref_mut => {
31703170 try llvm_params.append(dg.context.pointerType(0));
31713171 },
31723172 .abi_sized_int => {
3173 const param_ty = fn_info.param_types[it.zig_index - 1];
3173 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
31743174 const abi_size = @intCast(c_uint, param_ty.abiSize(mod));
31753175 try llvm_params.append(dg.context.intType(abi_size * 8));
31763176 },
31773177 .slice => {
3178 const param_ty = fn_info.param_types[it.zig_index - 1];
3178 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
31793179 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
31803180 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
31813181 param_ty.optionalChild(mod).slicePtrFieldType(&buf, mod)
......@@ -3195,7 +3195,7 @@ pub const DeclGen = struct {
31953195 try llvm_params.append(dg.context.intType(16));
31963196 },
31973197 .float_array => |count| {
3198 const param_ty = fn_info.param_types[it.zig_index - 1];
3198 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
31993199 const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
32003200 const field_count = @intCast(c_uint, count);
32013201 const arr_ty = float_ty.arrayType(field_count);
......@@ -3223,7 +3223,7 @@ pub const DeclGen = struct {
32233223 const mod = dg.module;
32243224 const lower_elem_ty = switch (elem_ty.zigTypeTag(mod)) {
32253225 .Opaque => true,
3226 .Fn => !elem_ty.fnInfo().is_generic,
3226 .Fn => !mod.typeToFunc(elem_ty).?.is_generic,
32273227 .Array => elem_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod),
32283228 else => elem_ty.hasRuntimeBitsIgnoreComptime(mod),
32293229 };
......@@ -4204,7 +4204,7 @@ pub const DeclGen = struct {
42044204
42054205 const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn;
42064206 if ((!is_fn_body and !decl.ty.hasRuntimeBits(mod)) or
4207 (is_fn_body and decl.ty.fnInfo().is_generic))
4207 (is_fn_body and mod.typeToFunc(decl.ty).?.is_generic))
42084208 {
42094209 return self.lowerPtrToVoid(tv.ty);
42104210 }
......@@ -4354,7 +4354,7 @@ pub const DeclGen = struct {
43544354 llvm_fn: *llvm.Value,
43554355 param_ty: Type,
43564356 param_index: u32,
4357 fn_info: Type.Payload.Function.Data,
4357 fn_info: InternPool.Key.FuncType,
43584358 llvm_arg_i: u32,
43594359 ) void {
43604360 const mod = dg.module;
......@@ -4774,8 +4774,8 @@ pub const FuncGen = struct {
47744774 .Pointer => callee_ty.childType(mod),
47754775 else => unreachable,
47764776 };
4777 const fn_info = zig_fn_ty.fnInfo();
4778 const return_type = fn_info.return_type;
4777 const fn_info = mod.typeToFunc(zig_fn_ty).?;
4778 const return_type = fn_info.return_type.toType();
47794779 const llvm_fn = try self.resolveInst(pl_op.operand);
47804780 const target = mod.getTarget();
47814781 const sret = firstParamSRet(fn_info, mod);
......@@ -4790,7 +4790,7 @@ pub const FuncGen = struct {
47904790 break :blk ret_ptr;
47914791 };
47924792
4793 const err_return_tracing = fn_info.return_type.isError(mod) and
4793 const err_return_tracing = return_type.isError(mod) and
47944794 self.dg.module.comp.bin_file.options.error_return_tracing;
47954795 if (err_return_tracing) {
47964796 try llvm_args.append(self.err_ret_trace.?);
......@@ -4971,14 +4971,14 @@ pub const FuncGen = struct {
49714971 while (it.next()) |lowering| switch (lowering) {
49724972 .byval => {
49734973 const param_index = it.zig_index - 1;
4974 const param_ty = fn_info.param_types[param_index];
4974 const param_ty = fn_info.param_types[param_index].toType();
49754975 if (!isByRef(param_ty, mod)) {
49764976 self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
49774977 }
49784978 },
49794979 .byref => {
49804980 const param_index = it.zig_index - 1;
4981 const param_ty = fn_info.param_types[param_index];
4981 const param_ty = fn_info.param_types[param_index].toType();
49824982 const param_llvm_ty = try self.dg.lowerType(param_ty);
49834983 const alignment = param_ty.abiAlignment(mod);
49844984 self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
......@@ -4998,7 +4998,7 @@ pub const FuncGen = struct {
49984998
49994999 .slice => {
50005000 assert(!it.byval_attr);
5001 const param_ty = fn_info.param_types[it.zig_index - 1];
5001 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
50025002 const ptr_info = param_ty.ptrInfo(mod);
50035003 const llvm_arg_i = it.llvm_index - 2;
50045004
......@@ -5023,7 +5023,7 @@ pub const FuncGen = struct {
50235023 };
50245024 }
50255025
5026 if (return_type.isNoReturn() and attr != .AlwaysTail) {
5026 if (fn_info.return_type == .noreturn_type and attr != .AlwaysTail) {
50275027 return null;
50285028 }
50295029
......@@ -5088,9 +5088,9 @@ pub const FuncGen = struct {
50885088 _ = self.builder.buildRetVoid();
50895089 return null;
50905090 }
5091 const fn_info = self.dg.decl.ty.fnInfo();
5091 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;
50925092 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5093 if (fn_info.return_type.isError(mod)) {
5093 if (fn_info.return_type.toType().isError(mod)) {
50945094 // Functions with an empty error set are emitted with an error code
50955095 // return type and return zero so they can be function pointers coerced
50965096 // to functions that return anyerror.
......@@ -5135,9 +5135,9 @@ pub const FuncGen = struct {
51355135 const un_op = self.air.instructions.items(.data)[inst].un_op;
51365136 const ptr_ty = self.typeOf(un_op);
51375137 const ret_ty = ptr_ty.childType(mod);
5138 const fn_info = self.dg.decl.ty.fnInfo();
5138 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;
51395139 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5140 if (fn_info.return_type.isError(mod)) {
5140 if (fn_info.return_type.toType().isError(mod)) {
51415141 // Functions with an empty error set are emitted with an error code
51425142 // return type and return zero so they can be function pointers coerced
51435143 // to functions that return anyerror.
......@@ -6148,25 +6148,21 @@ pub const FuncGen = struct {
61486148 defer self.gpa.free(fqn);
61496149
61506150 const is_internal_linkage = !mod.decl_exports.contains(decl_index);
6151 var fn_ty_pl: Type.Payload.Function = .{
6152 .base = .{ .tag = .function },
6153 .data = .{
6154 .param_types = &.{},
6155 .comptime_params = undefined,
6156 .return_type = Type.void,
6157 .alignment = 0,
6158 .noalias_bits = 0,
6159 .cc = .Unspecified,
6160 .is_var_args = false,
6161 .is_generic = false,
6162 .is_noinline = false,
6163 .align_is_generic = false,
6164 .cc_is_generic = false,
6165 .section_is_generic = false,
6166 .addrspace_is_generic = false,
6167 },
6168 };
6169 const fn_ty = Type.initPayload(&fn_ty_pl.base);
6151 const fn_ty = try mod.funcType(.{
6152 .param_types = &.{},
6153 .return_type = .void_type,
6154 .alignment = 0,
6155 .noalias_bits = 0,
6156 .comptime_bits = 0,
6157 .cc = .Unspecified,
6158 .is_var_args = false,
6159 .is_generic = false,
6160 .is_noinline = false,
6161 .align_is_generic = false,
6162 .cc_is_generic = false,
6163 .section_is_generic = false,
6164 .addrspace_is_generic = false,
6165 });
61706166 const subprogram = dib.createFunction(
61716167 di_file.toScope(),
61726168 decl.name,
......@@ -10546,31 +10542,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
1054610542 }
1054710543}
1054810544
10549fn firstParamSRet(fn_info: Type.Payload.Function.Data, mod: *Module) bool {
10550 if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime(mod)) return false;
10545fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool {
10546 if (!fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) return false;
1055110547
1055210548 const target = mod.getTarget();
1055310549 switch (fn_info.cc) {
10554 .Unspecified, .Inline => return isByRef(fn_info.return_type, mod),
10550 .Unspecified, .Inline => return isByRef(fn_info.return_type.toType(), mod),
1055510551 .C => switch (target.cpu.arch) {
1055610552 .mips, .mipsel => return false,
1055710553 .x86_64 => switch (target.os.tag) {
10558 .windows => return x86_64_abi.classifyWindows(fn_info.return_type, mod) == .memory,
10559 else => return firstParamSRetSystemV(fn_info.return_type, mod),
10554 .windows => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10555 else => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
1056010556 },
10561 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, mod)[0] == .indirect,
10562 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, mod) == .memory,
10563 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type, mod, .ret)) {
10557 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type.toType(), mod)[0] == .indirect,
10558 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
10559 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type.toType(), mod, .ret)) {
1056410560 .memory, .i64_array => return true,
1056510561 .i32_array => |size| return size != 1,
1056610562 .byval => return false,
1056710563 },
10568 .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type, mod) == .memory,
10564 .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
1056910565 else => return false, // TODO investigate C ABI for other architectures
1057010566 },
10571 .SysV => return firstParamSRetSystemV(fn_info.return_type, mod),
10572 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type, mod) == .memory,
10573 .Stdcall => return !isScalar(mod, fn_info.return_type),
10567 .SysV => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
10568 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10569 .Stdcall => return !isScalar(mod, fn_info.return_type.toType()),
1057410570 else => return false,
1057510571 }
1057610572}
......@@ -10585,13 +10581,14 @@ fn firstParamSRetSystemV(ty: Type, mod: *Module) bool {
1058510581/// In order to support the C calling convention, some return types need to be lowered
1058610582/// completely differently in the function prototype to honor the C ABI, and then
1058710583/// be effectively bitcasted to the actual return type.
10588fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10584fn lowerFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
1058910585 const mod = dg.module;
10590 if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime(mod)) {
10586 const return_type = fn_info.return_type.toType();
10587 if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {
1059110588 // If the return type is an error set or an error union, then we make this
1059210589 // anyerror return type instead, so that it can be coerced into a function
1059310590 // pointer type which has anyerror as the return type.
10594 if (fn_info.return_type.isError(mod)) {
10591 if (return_type.isError(mod)) {
1059510592 return dg.lowerType(Type.anyerror);
1059610593 } else {
1059710594 return dg.context.voidType();
......@@ -10600,61 +10597,61 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
1060010597 const target = mod.getTarget();
1060110598 switch (fn_info.cc) {
1060210599 .Unspecified, .Inline => {
10603 if (isByRef(fn_info.return_type, mod)) {
10600 if (isByRef(return_type, mod)) {
1060410601 return dg.context.voidType();
1060510602 } else {
10606 return dg.lowerType(fn_info.return_type);
10603 return dg.lowerType(return_type);
1060710604 }
1060810605 },
1060910606 .C => {
1061010607 switch (target.cpu.arch) {
10611 .mips, .mipsel => return dg.lowerType(fn_info.return_type),
10608 .mips, .mipsel => return dg.lowerType(return_type),
1061210609 .x86_64 => switch (target.os.tag) {
1061310610 .windows => return lowerWin64FnRetTy(dg, fn_info),
1061410611 else => return lowerSystemVFnRetTy(dg, fn_info),
1061510612 },
1061610613 .wasm32 => {
10617 if (isScalar(mod, fn_info.return_type)) {
10618 return dg.lowerType(fn_info.return_type);
10614 if (isScalar(mod, return_type)) {
10615 return dg.lowerType(return_type);
1061910616 }
10620 const classes = wasm_c_abi.classifyType(fn_info.return_type, mod);
10617 const classes = wasm_c_abi.classifyType(return_type, mod);
1062110618 if (classes[0] == .indirect or classes[0] == .none) {
1062210619 return dg.context.voidType();
1062310620 }
1062410621
1062510622 assert(classes[0] == .direct and classes[1] == .none);
10626 const scalar_type = wasm_c_abi.scalarType(fn_info.return_type, mod);
10623 const scalar_type = wasm_c_abi.scalarType(return_type, mod);
1062710624 const abi_size = scalar_type.abiSize(mod);
1062810625 return dg.context.intType(@intCast(c_uint, abi_size * 8));
1062910626 },
1063010627 .aarch64, .aarch64_be => {
10631 switch (aarch64_c_abi.classifyType(fn_info.return_type, mod)) {
10628 switch (aarch64_c_abi.classifyType(return_type, mod)) {
1063210629 .memory => return dg.context.voidType(),
10633 .float_array => return dg.lowerType(fn_info.return_type),
10634 .byval => return dg.lowerType(fn_info.return_type),
10630 .float_array => return dg.lowerType(return_type),
10631 .byval => return dg.lowerType(return_type),
1063510632 .integer => {
10636 const bit_size = fn_info.return_type.bitSize(mod);
10633 const bit_size = return_type.bitSize(mod);
1063710634 return dg.context.intType(@intCast(c_uint, bit_size));
1063810635 },
1063910636 .double_integer => return dg.context.intType(64).arrayType(2),
1064010637 }
1064110638 },
1064210639 .arm, .armeb => {
10643 switch (arm_c_abi.classifyType(fn_info.return_type, mod, .ret)) {
10640 switch (arm_c_abi.classifyType(return_type, mod, .ret)) {
1064410641 .memory, .i64_array => return dg.context.voidType(),
1064510642 .i32_array => |len| if (len == 1) {
1064610643 return dg.context.intType(32);
1064710644 } else {
1064810645 return dg.context.voidType();
1064910646 },
10650 .byval => return dg.lowerType(fn_info.return_type),
10647 .byval => return dg.lowerType(return_type),
1065110648 }
1065210649 },
1065310650 .riscv32, .riscv64 => {
10654 switch (riscv_c_abi.classifyType(fn_info.return_type, mod)) {
10651 switch (riscv_c_abi.classifyType(return_type, mod)) {
1065510652 .memory => return dg.context.voidType(),
1065610653 .integer => {
10657 const bit_size = fn_info.return_type.bitSize(mod);
10654 const bit_size = return_type.bitSize(mod);
1065810655 return dg.context.intType(@intCast(c_uint, bit_size));
1065910656 },
1066010657 .double_integer => {
......@@ -10664,50 +10661,52 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
1066410661 };
1066510662 return dg.context.structType(&llvm_types_buffer, 2, .False);
1066610663 },
10667 .byval => return dg.lowerType(fn_info.return_type),
10664 .byval => return dg.lowerType(return_type),
1066810665 }
1066910666 },
1067010667 // TODO investigate C ABI for other architectures
10671 else => return dg.lowerType(fn_info.return_type),
10668 else => return dg.lowerType(return_type),
1067210669 }
1067310670 },
1067410671 .Win64 => return lowerWin64FnRetTy(dg, fn_info),
1067510672 .SysV => return lowerSystemVFnRetTy(dg, fn_info),
1067610673 .Stdcall => {
10677 if (isScalar(mod, fn_info.return_type)) {
10678 return dg.lowerType(fn_info.return_type);
10674 if (isScalar(mod, return_type)) {
10675 return dg.lowerType(return_type);
1067910676 } else {
1068010677 return dg.context.voidType();
1068110678 }
1068210679 },
10683 else => return dg.lowerType(fn_info.return_type),
10680 else => return dg.lowerType(return_type),
1068410681 }
1068510682}
1068610683
10687fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10684fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
1068810685 const mod = dg.module;
10689 switch (x86_64_abi.classifyWindows(fn_info.return_type, mod)) {
10686 const return_type = fn_info.return_type.toType();
10687 switch (x86_64_abi.classifyWindows(return_type, mod)) {
1069010688 .integer => {
10691 if (isScalar(mod, fn_info.return_type)) {
10692 return dg.lowerType(fn_info.return_type);
10689 if (isScalar(mod, return_type)) {
10690 return dg.lowerType(return_type);
1069310691 } else {
10694 const abi_size = fn_info.return_type.abiSize(mod);
10692 const abi_size = return_type.abiSize(mod);
1069510693 return dg.context.intType(@intCast(c_uint, abi_size * 8));
1069610694 }
1069710695 },
1069810696 .win_i128 => return dg.context.intType(64).vectorType(2),
1069910697 .memory => return dg.context.voidType(),
10700 .sse => return dg.lowerType(fn_info.return_type),
10698 .sse => return dg.lowerType(return_type),
1070110699 else => unreachable,
1070210700 }
1070310701}
1070410702
10705fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10703fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
1070610704 const mod = dg.module;
10707 if (isScalar(mod, fn_info.return_type)) {
10708 return dg.lowerType(fn_info.return_type);
10705 const return_type = fn_info.return_type.toType();
10706 if (isScalar(mod, return_type)) {
10707 return dg.lowerType(return_type);
1070910708 }
10710 const classes = x86_64_abi.classifySystemV(fn_info.return_type, mod, .ret);
10709 const classes = x86_64_abi.classifySystemV(return_type, mod, .ret);
1071110710 if (classes[0] == .memory) {
1071210711 return dg.context.voidType();
1071310712 }
......@@ -10748,7 +10747,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm
1074810747 }
1074910748 }
1075010749 if (classes[0] == .integer and classes[1] == .none) {
10751 const abi_size = fn_info.return_type.abiSize(mod);
10750 const abi_size = return_type.abiSize(mod);
1075210751 return dg.context.intType(@intCast(c_uint, abi_size * 8));
1075310752 }
1075410753 return dg.context.structType(&llvm_types_buffer, llvm_types_index, .False);
......@@ -10756,7 +10755,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm
1075610755
1075710756const ParamTypeIterator = struct {
1075810757 dg: *DeclGen,
10759 fn_info: Type.Payload.Function.Data,
10758 fn_info: InternPool.Key.FuncType,
1076010759 zig_index: u32,
1076110760 llvm_index: u32,
1076210761 llvm_types_len: u32,
......@@ -10781,7 +10780,7 @@ const ParamTypeIterator = struct {
1078110780 if (it.zig_index >= it.fn_info.param_types.len) return null;
1078210781 const ty = it.fn_info.param_types[it.zig_index];
1078310782 it.byval_attr = false;
10784 return nextInner(it, ty);
10783 return nextInner(it, ty.toType());
1078510784 }
1078610785
1078710786 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
......@@ -10793,7 +10792,7 @@ const ParamTypeIterator = struct {
1079310792 return nextInner(it, fg.typeOf(args[it.zig_index]));
1079410793 }
1079510794 } else {
10796 return nextInner(it, it.fn_info.param_types[it.zig_index]);
10795 return nextInner(it, it.fn_info.param_types[it.zig_index].toType());
1079710796 }
1079810797 }
1079910798
......@@ -11009,7 +11008,7 @@ const ParamTypeIterator = struct {
1100911008 }
1101011009};
1101111010
11012fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTypeIterator {
11011fn iterateParamTypes(dg: *DeclGen, fn_info: InternPool.Key.FuncType) ParamTypeIterator {
1101311012 return .{
1101411013 .dg = dg,
1101511014 .fn_info = fn_info,
src/codegen/spirv.zig+11-11
......@@ -1227,8 +1227,9 @@ pub const DeclGen = struct {
12271227 },
12281228 .Fn => switch (repr) {
12291229 .direct => {
1230 const fn_info = mod.typeToFunc(ty).?;
12301231 // TODO: Put this somewhere in Sema.zig
1231 if (ty.fnIsVarArgs())
1232 if (fn_info.is_var_args)
12321233 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});
12331234
12341235 const param_ty_refs = try self.gpa.alloc(CacheRef, ty.fnParamLen());
......@@ -1546,18 +1547,17 @@ pub const DeclGen = struct {
15461547 assert(decl.ty.zigTypeTag(mod) == .Fn);
15471548 const prototype_id = try self.resolveTypeId(decl.ty);
15481549 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{
1549 .id_result_type = try self.resolveTypeId(decl.ty.fnReturnType()),
1550 .id_result_type = try self.resolveTypeId(decl.ty.fnReturnType(mod)),
15501551 .id_result = decl_id,
15511552 .function_control = .{}, // TODO: We can set inline here if the type requires it.
15521553 .function_type = prototype_id,
15531554 });
15541555
1555 const params = decl.ty.fnParamLen();
1556 var i: usize = 0;
1556 const fn_info = mod.typeToFunc(decl.ty).?;
15571557
1558 try self.args.ensureUnusedCapacity(self.gpa, params);
1559 while (i < params) : (i += 1) {
1560 const param_type_id = try self.resolveTypeId(decl.ty.fnParamType(i));
1558 try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
1559 for (fn_info.param_types) |param_type| {
1560 const param_type_id = try self.resolveTypeId(param_type.toType());
15611561 const arg_result_id = self.spv.allocId();
15621562 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
15631563 .id_result_type = param_type_id,
......@@ -3338,10 +3338,10 @@ pub const DeclGen = struct {
33383338 .Pointer => return self.fail("cannot call function pointers", .{}),
33393339 else => unreachable,
33403340 };
3341 const fn_info = zig_fn_ty.fnInfo();
3341 const fn_info = mod.typeToFunc(zig_fn_ty).?;
33423342 const return_type = fn_info.return_type;
33433343
3344 const result_type_id = try self.resolveTypeId(return_type);
3344 const result_type_id = try self.resolveTypeId(return_type.toType());
33453345 const result_id = self.spv.allocId();
33463346 const callee_id = try self.resolve(pl_op.operand);
33473347
......@@ -3368,11 +3368,11 @@ pub const DeclGen = struct {
33683368 .id_ref_3 = params[0..n_params],
33693369 });
33703370
3371 if (return_type.isNoReturn()) {
3371 if (return_type == .noreturn_type) {
33723372 try self.func.body.emit(self.spv.gpa, .OpUnreachable, {});
33733373 }
33743374
3375 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(mod)) {
3375 if (self.liveness.isUnused(inst) or !return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) {
33763376 return null;
33773377 }
33783378
src/link/Coff.zig+1-1
......@@ -1430,7 +1430,7 @@ pub fn updateDeclExports(
14301430 .x86 => std.builtin.CallingConvention.Stdcall,
14311431 else => std.builtin.CallingConvention.C,
14321432 };
1433 const decl_cc = exported_decl.ty.fnCallingConvention();
1433 const decl_cc = exported_decl.ty.fnCallingConvention(mod);
14341434 if (decl_cc == .C and mem.eql(u8, exp.options.name, "main") and
14351435 self.base.options.link_libc)
14361436 {
src/link/Dwarf.zig+1-1
......@@ -1022,7 +1022,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
10221022 const decl_name_with_null = decl_name[0 .. decl_name.len + 1];
10231023 try dbg_info_buffer.ensureUnusedCapacity(25 + decl_name_with_null.len);
10241024
1025 const fn_ret_type = decl.ty.fnReturnType();
1025 const fn_ret_type = decl.ty.fnReturnType(mod);
10261026 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);
10271027 if (fn_ret_has_bits) {
10281028 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.subprogram));
src/link/SpirV.zig+3-3
......@@ -131,12 +131,12 @@ pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index)
131131
132132pub fn updateDeclExports(
133133 self: *SpirV,
134 module: *Module,
134 mod: *Module,
135135 decl_index: Module.Decl.Index,
136136 exports: []const *Module.Export,
137137) !void {
138 const decl = module.declPtr(decl_index);
139 if (decl.val.tag() == .function and decl.ty.fnCallingConvention() == .Kernel) {
138 const decl = mod.declPtr(decl_index);
139 if (decl.val.tag() == .function and decl.ty.fnCallingConvention(mod) == .Kernel) {
140140 // TODO: Unify with resolveDecl in spirv.zig.
141141 const entry = try self.decl_link.getOrPut(decl_index);
142142 if (!entry.found_existing) {
src/target.zig+11
......@@ -649,3 +649,14 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {
649649 else => "o", // Non-standard
650650 };
651651}
652
653pub fn fnCallConvAllowsZigTypes(target: std.Target, cc: std.builtin.CallingConvention) bool {
654 return switch (cc) {
655 .Unspecified, .Async, .Inline => true,
656 // For now we want to authorize PTX kernel to use zig objects, even if
657 // we end up exposing the ABI. The goal is to experiment with more
658 // integrated CPU/GPU code.
659 .Kernel => target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64,
660 else => false,
661 };
662}
src/type.zig+110-282
......@@ -42,8 +42,6 @@ pub const Type = struct {
4242 .error_set_merged,
4343 => return .ErrorSet,
4444
45 .function => return .Fn,
46
4745 .pointer,
4846 .inferred_alloc_const,
4947 .inferred_alloc_mut,
......@@ -66,6 +64,7 @@ pub const Type = struct {
6664 .union_type => return .Union,
6765 .opaque_type => return .Opaque,
6866 .enum_type => return .Enum,
67 .func_type => return .Fn,
6968 .simple_type => |s| switch (s) {
7069 .f16,
7170 .f32,
......@@ -344,53 +343,6 @@ pub const Type = struct {
344343 return true;
345344 },
346345
347 .function => {
348 if (b.zigTypeTag(mod) != .Fn) return false;
349
350 const a_info = a.fnInfo();
351 const b_info = b.fnInfo();
352
353 if (!a_info.return_type.isGenericPoison() and
354 !b_info.return_type.isGenericPoison() and
355 !eql(a_info.return_type, b_info.return_type, mod))
356 return false;
357
358 if (a_info.is_var_args != b_info.is_var_args)
359 return false;
360
361 if (a_info.is_generic != b_info.is_generic)
362 return false;
363
364 if (a_info.is_noinline != b_info.is_noinline)
365 return false;
366
367 if (a_info.noalias_bits != b_info.noalias_bits)
368 return false;
369
370 if (!a_info.cc_is_generic and a_info.cc != b_info.cc)
371 return false;
372
373 if (!a_info.align_is_generic and a_info.alignment != b_info.alignment)
374 return false;
375
376 if (a_info.param_types.len != b_info.param_types.len)
377 return false;
378
379 for (a_info.param_types, 0..) |a_param_ty, i| {
380 const b_param_ty = b_info.param_types[i];
381 if (a_info.comptime_params[i] != b_info.comptime_params[i])
382 return false;
383
384 if (a_param_ty.isGenericPoison()) continue;
385 if (b_param_ty.isGenericPoison()) continue;
386
387 if (!eql(a_param_ty, b_param_ty, mod))
388 return false;
389 }
390
391 return true;
392 },
393
394346 .pointer,
395347 .inferred_alloc_const,
396348 .inferred_alloc_mut,
......@@ -501,32 +453,6 @@ pub const Type = struct {
501453 std.hash.autoHash(hasher, ies);
502454 },
503455
504 .function => {
505 std.hash.autoHash(hasher, std.builtin.TypeId.Fn);
506
507 const fn_info = ty.fnInfo();
508 if (!fn_info.return_type.isGenericPoison()) {
509 hashWithHasher(fn_info.return_type, hasher, mod);
510 }
511 if (!fn_info.align_is_generic) {
512 std.hash.autoHash(hasher, fn_info.alignment);
513 }
514 if (!fn_info.cc_is_generic) {
515 std.hash.autoHash(hasher, fn_info.cc);
516 }
517 std.hash.autoHash(hasher, fn_info.is_var_args);
518 std.hash.autoHash(hasher, fn_info.is_generic);
519 std.hash.autoHash(hasher, fn_info.is_noinline);
520 std.hash.autoHash(hasher, fn_info.noalias_bits);
521
522 std.hash.autoHash(hasher, fn_info.param_types.len);
523 for (fn_info.param_types, 0..) |param_ty, i| {
524 std.hash.autoHash(hasher, fn_info.paramIsComptime(i));
525 if (param_ty.isGenericPoison()) continue;
526 hashWithHasher(param_ty, hasher, mod);
527 }
528 },
529
530456 .pointer,
531457 .inferred_alloc_const,
532458 .inferred_alloc_mut,
......@@ -631,30 +557,6 @@ pub const Type = struct {
631557 };
632558 },
633559
634 .function => {
635 const payload = self.castTag(.function).?.data;
636 const param_types = try allocator.alloc(Type, payload.param_types.len);
637 for (payload.param_types, 0..) |param_ty, i| {
638 param_types[i] = try param_ty.copy(allocator);
639 }
640 const other_comptime_params = payload.comptime_params[0..payload.param_types.len];
641 const comptime_params = try allocator.dupe(bool, other_comptime_params);
642 return Tag.function.create(allocator, .{
643 .return_type = try payload.return_type.copy(allocator),
644 .param_types = param_types,
645 .cc = payload.cc,
646 .alignment = payload.alignment,
647 .is_var_args = payload.is_var_args,
648 .is_generic = payload.is_generic,
649 .is_noinline = payload.is_noinline,
650 .comptime_params = comptime_params.ptr,
651 .align_is_generic = payload.align_is_generic,
652 .cc_is_generic = payload.cc_is_generic,
653 .section_is_generic = payload.section_is_generic,
654 .addrspace_is_generic = payload.addrspace_is_generic,
655 .noalias_bits = payload.noalias_bits,
656 });
657 },
658560 .pointer => {
659561 const payload = self.castTag(.pointer).?.data;
660562 const sent: ?Value = if (payload.sentinel) |some|
......@@ -766,32 +668,6 @@ pub const Type = struct {
766668 while (true) {
767669 const t = ty.tag();
768670 switch (t) {
769 .function => {
770 const payload = ty.castTag(.function).?.data;
771 try writer.writeAll("fn(");
772 for (payload.param_types, 0..) |param_type, i| {
773 if (i != 0) try writer.writeAll(", ");
774 try param_type.dump("", .{}, writer);
775 }
776 if (payload.is_var_args) {
777 if (payload.param_types.len != 0) {
778 try writer.writeAll(", ");
779 }
780 try writer.writeAll("...");
781 }
782 try writer.writeAll(") ");
783 if (payload.alignment != 0) {
784 try writer.print("align({d}) ", .{payload.alignment});
785 }
786 if (payload.cc != .Unspecified) {
787 try writer.writeAll("callconv(.");
788 try writer.writeAll(@tagName(payload.cc));
789 try writer.writeAll(") ");
790 }
791 ty = payload.return_type;
792 continue;
793 },
794
795671 .anyframe_T => {
796672 const return_type = ty.castTag(.anyframe_T).?.data;
797673 try writer.print("anyframe->", .{});
......@@ -909,48 +785,6 @@ pub const Type = struct {
909785 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
910786 },
911787
912 .function => {
913 const fn_info = ty.fnInfo();
914 if (fn_info.is_noinline) {
915 try writer.writeAll("noinline ");
916 }
917 try writer.writeAll("fn(");
918 for (fn_info.param_types, 0..) |param_ty, i| {
919 if (i != 0) try writer.writeAll(", ");
920 if (fn_info.paramIsComptime(i)) {
921 try writer.writeAll("comptime ");
922 }
923 if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) {
924 try writer.writeAll("noalias ");
925 };
926 if (param_ty.isGenericPoison()) {
927 try writer.writeAll("anytype");
928 } else {
929 try print(param_ty, writer, mod);
930 }
931 }
932 if (fn_info.is_var_args) {
933 if (fn_info.param_types.len != 0) {
934 try writer.writeAll(", ");
935 }
936 try writer.writeAll("...");
937 }
938 try writer.writeAll(") ");
939 if (fn_info.alignment != 0) {
940 try writer.print("align({d}) ", .{fn_info.alignment});
941 }
942 if (fn_info.cc != .Unspecified) {
943 try writer.writeAll("callconv(.");
944 try writer.writeAll(@tagName(fn_info.cc));
945 try writer.writeAll(") ");
946 }
947 if (fn_info.return_type.isGenericPoison()) {
948 try writer.writeAll("anytype");
949 } else {
950 try print(fn_info.return_type, writer, mod);
951 }
952 },
953
954788 .error_union => {
955789 const error_union = ty.castTag(.error_union).?.data;
956790 try print(error_union.error_set, writer, mod);
......@@ -1158,6 +992,48 @@ pub const Type = struct {
1158992 const decl = mod.declPtr(enum_type.decl);
1159993 try decl.renderFullyQualifiedName(mod, writer);
1160994 },
995 .func_type => |fn_info| {
996 if (fn_info.is_noinline) {
997 try writer.writeAll("noinline ");
998 }
999 try writer.writeAll("fn(");
1000 for (fn_info.param_types, 0..) |param_ty, i| {
1001 if (i != 0) try writer.writeAll(", ");
1002 if (std.math.cast(u5, i)) |index| {
1003 if (fn_info.paramIsComptime(index)) {
1004 try writer.writeAll("comptime ");
1005 }
1006 if (fn_info.paramIsNoalias(index)) {
1007 try writer.writeAll("noalias ");
1008 }
1009 }
1010 if (param_ty == .generic_poison_type) {
1011 try writer.writeAll("anytype");
1012 } else {
1013 try print(param_ty.toType(), writer, mod);
1014 }
1015 }
1016 if (fn_info.is_var_args) {
1017 if (fn_info.param_types.len != 0) {
1018 try writer.writeAll(", ");
1019 }
1020 try writer.writeAll("...");
1021 }
1022 try writer.writeAll(") ");
1023 if (fn_info.alignment != 0) {
1024 try writer.print("align({d}) ", .{fn_info.alignment});
1025 }
1026 if (fn_info.cc != .Unspecified) {
1027 try writer.writeAll("callconv(.");
1028 try writer.writeAll(@tagName(fn_info.cc));
1029 try writer.writeAll(") ");
1030 }
1031 if (fn_info.return_type == .generic_poison_type) {
1032 try writer.writeAll("anytype");
1033 } else {
1034 try print(fn_info.return_type.toType(), writer, mod);
1035 }
1036 },
11611037
11621038 // values, not types
11631039 .undef => unreachable,
......@@ -1174,6 +1050,11 @@ pub const Type = struct {
11741050 }
11751051 }
11761052
1053 pub fn toIntern(ty: Type) InternPool.Index {
1054 assert(ty.ip_index != .none);
1055 return ty.ip_index;
1056 }
1057
11771058 pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value {
11781059 if (self.ip_index != .none) return self.ip_index.toValue();
11791060 switch (self.tag()) {
......@@ -1223,7 +1104,7 @@ pub const Type = struct {
12231104 if (ignore_comptime_only) {
12241105 return true;
12251106 } else if (ty.childType(mod).zigTypeTag(mod) == .Fn) {
1226 return !ty.childType(mod).fnInfo().is_generic;
1107 return !mod.typeToFunc(ty.childType(mod)).?.is_generic;
12271108 } else if (strat == .sema) {
12281109 return !(try strat.sema.typeRequiresComptime(ty));
12291110 } else {
......@@ -1231,12 +1112,6 @@ pub const Type = struct {
12311112 }
12321113 },
12331114
1234 // These are false because they are comptime-only types.
1235 // These are function *bodies*, not pointers.
1236 // Special exceptions have to be made when emitting functions due to
1237 // this returning false.
1238 .function => return false,
1239
12401115 .optional => {
12411116 const child_ty = ty.optionalChild(mod);
12421117 if (child_ty.isNoReturn()) {
......@@ -1262,7 +1137,7 @@ pub const Type = struct {
12621137 // to comptime-only types do not, with the exception of function pointers.
12631138 if (ignore_comptime_only) return true;
12641139 const child_ty = ptr_type.elem_type.toType();
1265 if (child_ty.zigTypeTag(mod) == .Fn) return !child_ty.fnInfo().is_generic;
1140 if (child_ty.zigTypeTag(mod) == .Fn) return !mod.typeToFunc(child_ty).?.is_generic;
12661141 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));
12671142 return !comptimeOnly(ty, mod);
12681143 },
......@@ -1293,6 +1168,13 @@ pub const Type = struct {
12931168 }
12941169 },
12951170 .error_union_type => @panic("TODO"),
1171
1172 // These are function *bodies*, not pointers.
1173 // They return false here because they are comptime-only types.
1174 // Special exceptions have to be made when emitting functions due to
1175 // this returning false.
1176 .func_type => false,
1177
12961178 .simple_type => |t| switch (t) {
12971179 .f16,
12981180 .f32,
......@@ -1436,8 +1318,6 @@ pub const Type = struct {
14361318 .error_set_single,
14371319 .error_set_inferred,
14381320 .error_set_merged,
1439 // These are function bodies, not function pointers.
1440 .function,
14411321 .error_union,
14421322 .anyframe_T,
14431323 => false,
......@@ -1448,12 +1328,21 @@ pub const Type = struct {
14481328 .optional => ty.isPtrLikeOptional(mod),
14491329 },
14501330 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1451 .int_type => true,
1452 .ptr_type => true,
1331 .int_type,
1332 .ptr_type,
1333 .vector_type,
1334 => true,
1335
1336 .error_union_type,
1337 .anon_struct_type,
1338 .opaque_type,
1339 // These are function bodies, not function pointers.
1340 .func_type,
1341 => false,
1342
14531343 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
1454 .vector_type => true,
14551344 .opt_type => |child| child.toType().isPtrLikeOptional(mod),
1456 .error_union_type => false,
1345
14571346 .simple_type => |t| switch (t) {
14581347 .f16,
14591348 .f32,
......@@ -1509,12 +1398,10 @@ pub const Type = struct {
15091398 };
15101399 return struct_obj.layout != .Auto;
15111400 },
1512 .anon_struct_type => false,
15131401 .union_type => |union_type| switch (union_type.runtime_tag) {
15141402 .none, .safety => mod.unionPtr(union_type.index).layout != .Auto,
15151403 .tagged => false,
15161404 },
1517 .opaque_type => false,
15181405 .enum_type => |enum_type| switch (enum_type.tag_mode) {
15191406 .auto => false,
15201407 .explicit, .nonexhaustive => true,
......@@ -1546,7 +1433,7 @@ pub const Type = struct {
15461433 pub fn isFnOrHasRuntimeBits(ty: Type, mod: *Module) bool {
15471434 switch (ty.zigTypeTag(mod)) {
15481435 .Fn => {
1549 const fn_info = ty.fnInfo();
1436 const fn_info = mod.typeToFunc(ty).?;
15501437 if (fn_info.is_generic) return false;
15511438 if (fn_info.is_var_args) return true;
15521439 switch (fn_info.cc) {
......@@ -1555,7 +1442,7 @@ pub const Type = struct {
15551442 .Inline => return false,
15561443 else => {},
15571444 }
1558 if (fn_info.return_type.comptimeOnly(mod)) return false;
1445 if (fn_info.return_type.toType().comptimeOnly(mod)) return false;
15591446 return true;
15601447 },
15611448 else => return ty.hasRuntimeBits(mod),
......@@ -1707,13 +1594,6 @@ pub const Type = struct {
17071594 switch (ty.ip_index) {
17081595 .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = 0 },
17091596 .none => switch (ty.tag()) {
1710 // represents machine code; not a pointer
1711 .function => {
1712 const alignment = ty.castTag(.function).?.data.alignment;
1713 if (alignment != 0) return AbiAlignmentAdvanced{ .scalar = alignment };
1714 return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) };
1715 },
1716
17171597 .pointer,
17181598 .anyframe_T,
17191599 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
......@@ -1753,6 +1633,13 @@ pub const Type = struct {
17531633
17541634 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
17551635 .error_union_type => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
1636 // represents machine code; not a pointer
1637 .func_type => |func_type| {
1638 const alignment = @intCast(u32, func_type.alignment);
1639 if (alignment != 0) return AbiAlignmentAdvanced{ .scalar = alignment };
1640 return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) };
1641 },
1642
17561643 .simple_type => |t| switch (t) {
17571644 .bool,
17581645 .atomic_order,
......@@ -2086,7 +1973,6 @@ pub const Type = struct {
20861973 .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 },
20871974
20881975 .none => switch (ty.tag()) {
2089 .function => unreachable, // represents machine code; not a pointer
20901976 .inferred_alloc_const => unreachable,
20911977 .inferred_alloc_mut => unreachable,
20921978
......@@ -2187,6 +2073,7 @@ pub const Type = struct {
21872073
21882074 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
21892075 .error_union_type => @panic("TODO"),
2076 .func_type => unreachable, // represents machine code; not a pointer
21902077 .simple_type => |t| switch (t) {
21912078 .bool,
21922079 .atomic_order,
......@@ -2408,7 +2295,6 @@ pub const Type = struct {
24082295
24092296 switch (ty.ip_index) {
24102297 .none => switch (ty.tag()) {
2411 .function => unreachable, // represents machine code; not a pointer
24122298 .inferred_alloc_const => unreachable,
24132299 .inferred_alloc_mut => unreachable,
24142300
......@@ -2453,6 +2339,7 @@ pub const Type = struct {
24532339 },
24542340 .opt_type => @panic("TODO"),
24552341 .error_union_type => @panic("TODO"),
2342 .func_type => unreachable, // represents machine code; not a pointer
24562343 .simple_type => |t| switch (t) {
24572344 .f16 => return 16,
24582345 .f32 => return 32,
......@@ -3271,6 +3158,7 @@ pub const Type = struct {
32713158
32723159 .opt_type => unreachable,
32733160 .error_union_type => unreachable,
3161 .func_type => unreachable,
32743162 .simple_type => unreachable, // handled via Index enum tag above
32753163
32763164 .union_type => unreachable,
......@@ -3356,54 +3244,22 @@ pub const Type = struct {
33563244 };
33573245 }
33583246
3359 /// Asserts the type is a function.
3360 pub fn fnParamLen(self: Type) usize {
3361 return self.castTag(.function).?.data.param_types.len;
3362 }
3363
3364 /// Asserts the type is a function. The length of the slice must be at least the length
3365 /// given by `fnParamLen`.
3366 pub fn fnParamTypes(self: Type, types: []Type) void {
3367 const payload = self.castTag(.function).?.data;
3368 @memcpy(types[0..payload.param_types.len], payload.param_types);
3369 }
3370
3371 /// Asserts the type is a function.
3372 pub fn fnParamType(self: Type, index: usize) Type {
3373 switch (self.tag()) {
3374 .function => {
3375 const payload = self.castTag(.function).?.data;
3376 return payload.param_types[index];
3377 },
3378
3379 else => unreachable,
3380 }
3381 }
3382
33833247 /// Asserts the type is a function or a function pointer.
3384 pub fn fnReturnType(ty: Type) Type {
3385 const fn_ty = switch (ty.tag()) {
3386 .pointer => ty.castTag(.pointer).?.data.pointee_type,
3387 .function => ty,
3388 else => unreachable,
3389 };
3390 return fn_ty.castTag(.function).?.data.return_type;
3248 pub fn fnReturnType(ty: Type, mod: *Module) Type {
3249 return fnReturnTypeIp(ty, mod.intern_pool);
33913250 }
33923251
3393 /// Asserts the type is a function.
3394 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {
3395 return self.castTag(.function).?.data.cc;
3252 pub fn fnReturnTypeIp(ty: Type, ip: InternPool) Type {
3253 return switch (ip.indexToKey(ty.ip_index)) {
3254 .ptr_type => |ptr_type| ip.indexToKey(ptr_type.elem_type).func_type.return_type,
3255 .func_type => |func_type| func_type.return_type,
3256 else => unreachable,
3257 }.toType();
33963258 }
33973259
33983260 /// Asserts the type is a function.
3399 pub fn fnCallingConventionAllowsZigTypes(target: Target, cc: std.builtin.CallingConvention) bool {
3400 return switch (cc) {
3401 .Unspecified, .Async, .Inline => true,
3402 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.
3403 // The goal is to experiment with more integrated CPU/GPU code.
3404 .Kernel => target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64,
3405 else => false,
3406 };
3261 pub fn fnCallingConvention(ty: Type, mod: *Module) std.builtin.CallingConvention {
3262 return mod.intern_pool.indexToKey(ty.ip_index).func_type.cc;
34073263 }
34083264
34093265 pub fn isValidParamType(self: Type, mod: *const Module) bool {
......@@ -3421,12 +3277,8 @@ pub const Type = struct {
34213277 }
34223278
34233279 /// Asserts the type is a function.
3424 pub fn fnIsVarArgs(self: Type) bool {
3425 return self.castTag(.function).?.data.is_var_args;
3426 }
3427
3428 pub fn fnInfo(ty: Type) Payload.Function.Data {
3429 return ty.castTag(.function).?.data;
3280 pub fn fnIsVarArgs(ty: Type, mod: *Module) bool {
3281 return mod.intern_pool.indexToKey(ty.ip_index).func_type.is_var_args;
34303282 }
34313283
34323284 pub fn isNumeric(ty: Type, mod: *const Module) bool {
......@@ -3474,7 +3326,6 @@ pub const Type = struct {
34743326 .error_set_single,
34753327 .error_set,
34763328 .error_set_merged,
3477 .function,
34783329 .error_set_inferred,
34793330 .anyframe_T,
34803331 .pointer,
......@@ -3500,7 +3351,12 @@ pub const Type = struct {
35003351 return null;
35013352 }
35023353 },
3503 .ptr_type => return null,
3354
3355 .ptr_type,
3356 .error_union_type,
3357 .func_type,
3358 => return null,
3359
35043360 .array_type => |array_type| {
35053361 if (array_type.len == 0)
35063362 return Value.initTag(.empty_array);
......@@ -3514,13 +3370,13 @@ pub const Type = struct {
35143370 return null;
35153371 },
35163372 .opt_type => |child| {
3517 if (child.toType().isNoReturn()) {
3518 return Value.null;
3373 if (child == .noreturn_type) {
3374 return try mod.nullValue(ty);
35193375 } else {
35203376 return null;
35213377 }
35223378 },
3523 .error_union_type => return null,
3379
35243380 .simple_type => |t| switch (t) {
35253381 .f16,
35263382 .f32,
......@@ -3682,9 +3538,6 @@ pub const Type = struct {
36823538 .error_set_merged,
36833539 => false,
36843540
3685 // These are function bodies, not function pointers.
3686 .function => true,
3687
36883541 .inferred_alloc_mut => unreachable,
36893542 .inferred_alloc_const => unreachable,
36903543
......@@ -3721,6 +3574,9 @@ pub const Type = struct {
37213574 .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod),
37223575 .opt_type => |child| child.toType().comptimeOnly(mod),
37233576 .error_union_type => |error_union_type| error_union_type.payload_type.toType().comptimeOnly(mod),
3577 // These are function bodies, not function pointers.
3578 .func_type => true,
3579
37243580 .simple_type => |t| switch (t) {
37253581 .f16,
37263582 .f32,
......@@ -4367,6 +4223,10 @@ pub const Type = struct {
43674223 return ty.ip_index == .generic_poison_type;
43684224 }
43694225
4226 pub fn isBoundFn(ty: Type) bool {
4227 return ty.ip_index == .none and ty.tag() == .bound_fn;
4228 }
4229
43704230 /// This enum does not directly correspond to `std.builtin.TypeId` because
43714231 /// it has extra enum tags in it, as a way of using less memory. For example,
43724232 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
......@@ -4383,7 +4243,6 @@ pub const Type = struct {
43834243 // After this, the tag requires a payload.
43844244
43854245 pointer,
4386 function,
43874246 optional,
43884247 error_union,
43894248 anyframe_T,
......@@ -4411,7 +4270,6 @@ pub const Type = struct {
44114270 .error_set_merged => Payload.ErrorSetMerged,
44124271
44134272 .pointer => Payload.Pointer,
4414 .function => Payload.Function,
44154273 .error_union => Payload.ErrorUnion,
44164274 .error_set_single => Payload.Name,
44174275 };
......@@ -4508,36 +4366,6 @@ pub const Type = struct {
45084366 data: u16,
45094367 };
45104368
4511 pub const Function = struct {
4512 pub const base_tag = Tag.function;
4513
4514 base: Payload = Payload{ .tag = base_tag },
4515 data: Data,
4516
4517 // TODO look into optimizing this memory to take fewer bytes
4518 pub const Data = struct {
4519 param_types: []Type,
4520 comptime_params: [*]bool,
4521 return_type: Type,
4522 /// If zero use default target function code alignment.
4523 alignment: u32,
4524 noalias_bits: u32,
4525 cc: std.builtin.CallingConvention,
4526 is_var_args: bool,
4527 is_generic: bool,
4528 is_noinline: bool,
4529 align_is_generic: bool,
4530 cc_is_generic: bool,
4531 section_is_generic: bool,
4532 addrspace_is_generic: bool,
4533
4534 pub fn paramIsComptime(self: @This(), i: usize) bool {
4535 assert(i < self.param_types.len);
4536 return self.comptime_params[i];
4537 }
4538 };
4539 };
4540
45414369 pub const ErrorSet = struct {
45424370 pub const base_tag = Tag.error_set;
45434371
src/value.zig+5
......@@ -602,6 +602,11 @@ pub const Value = struct {
602602 return result;
603603 }
604604
605 pub fn toIntern(val: Value) InternPool.Index {
606 assert(val.ip_index != .none);
607 return val.ip_index;
608 }
609
605610 /// Asserts that the value is representable as a type.
606611 pub fn toType(self: Value) Type {
607612 if (self.ip_index != .none) return self.ip_index.toType();