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;...@@ -143,7 +143,7 @@ pub const Mode = OptimizeMode;
143143
144/// This data structure is used by the Zig language code generation and144/// This data structure is used by the Zig language code generation and
145/// therefore must be kept in sync with the compiler implementation.145/// therefore must be kept in sync with the compiler implementation.
146pub const CallingConvention = enum {146pub const CallingConvention = enum(u8) {
147 /// This is the default Zig calling convention used when not using `export` on `fn`147 /// This is the default Zig calling convention used when not using `export` on `fn`
148 /// and no other calling convention is specified.148 /// and no other calling convention is specified.
149 Unspecified,149 Unspecified,
src/Air.zig+3-4
...@@ -845,7 +845,6 @@ pub const Inst = struct {...@@ -845,7 +845,6 @@ pub const Inst = struct {
845845
846 pub const Ref = enum(u32) {846 pub const Ref = enum(u32) {
847 u1_type = @enumToInt(InternPool.Index.u1_type),847 u1_type = @enumToInt(InternPool.Index.u1_type),
848 u5_type = @enumToInt(InternPool.Index.u5_type),
849 u8_type = @enumToInt(InternPool.Index.u8_type),848 u8_type = @enumToInt(InternPool.Index.u8_type),
850 i8_type = @enumToInt(InternPool.Index.i8_type),849 i8_type = @enumToInt(InternPool.Index.i8_type),
851 u16_type = @enumToInt(InternPool.Index.u16_type),850 u16_type = @enumToInt(InternPool.Index.u16_type),
...@@ -914,8 +913,8 @@ pub const Inst = struct {...@@ -914,8 +913,8 @@ pub const Inst = struct {
914 zero_u8 = @enumToInt(InternPool.Index.zero_u8),913 zero_u8 = @enumToInt(InternPool.Index.zero_u8),
915 one = @enumToInt(InternPool.Index.one),914 one = @enumToInt(InternPool.Index.one),
916 one_usize = @enumToInt(InternPool.Index.one_usize),915 one_usize = @enumToInt(InternPool.Index.one_usize),
917 one_u5 = @enumToInt(InternPool.Index.one_u5),916 one_u8 = @enumToInt(InternPool.Index.one_u8),
918 four_u5 = @enumToInt(InternPool.Index.four_u5),917 four_u8 = @enumToInt(InternPool.Index.four_u8),
919 negative_one = @enumToInt(InternPool.Index.negative_one),918 negative_one = @enumToInt(InternPool.Index.negative_one),
920 calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c),919 calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c),
921 calling_convention_inline = @enumToInt(InternPool.Index.calling_convention_inline),920 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 {...@@ -1383,7 +1382,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
13831382
1384 .call, .call_always_tail, .call_never_tail, .call_never_inline => {1383 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
1385 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);1384 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1386 return callee_ty.fnReturnType();1385 return callee_ty.fnReturnTypeIp(ip);
1387 },1386 },
13881387
1389 .slice_elem_val, .ptr_elem_val, .array_elem_val => {1388 .slice_elem_val, .ptr_elem_val, .array_elem_val => {
src/InternPool.zig+204-40
...@@ -148,6 +148,7 @@ pub const Key = union(enum) {...@@ -148,6 +148,7 @@ pub const Key = union(enum) {
148 union_type: UnionType,148 union_type: UnionType,
149 opaque_type: OpaqueType,149 opaque_type: OpaqueType,
150 enum_type: EnumType,150 enum_type: EnumType,
151 func_type: FuncType,
151152
152 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented153 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
153 /// via `simple_value` and has a named `Index` tag for it.154 /// via `simple_value` and has a named `Index` tag for it.
...@@ -185,6 +186,13 @@ pub const Key = union(enum) {...@@ -185,6 +186,13 @@ pub const Key = union(enum) {
185 /// If zero use pointee_type.abiAlignment()186 /// If zero use pointee_type.abiAlignment()
186 /// When creating pointer types, if alignment is equal to pointee type187 /// When creating pointer types, if alignment is equal to pointee type
187 /// abi alignment, this value should be set to 0 instead.188 /// 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.
188 alignment: u64 = 0,196 alignment: u64 = 0,
189 /// If this is non-zero it means the pointer points to a sub-byte197 /// If this is non-zero it means the pointer points to a sub-byte
190 /// range of data, which is backed by a "host integer" with this198 /// range of data, which is backed by a "host integer" with this
...@@ -358,6 +366,44 @@ pub const Key = union(enum) {...@@ -358,6 +366,44 @@ pub const Key = union(enum) {
358 }366 }
359 };367 };
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
361 pub const Int = struct {407 pub const Int = struct {
362 ty: Index,408 ty: Index,
363 storage: Storage,409 storage: Storage,
...@@ -512,6 +558,18 @@ pub const Key = union(enum) {...@@ -512,6 +558,18 @@ pub const Key = union(enum) {
512 for (anon_struct_type.values) |elem| std.hash.autoHash(hasher, elem);558 for (anon_struct_type.values) |elem| std.hash.autoHash(hasher, elem);
513 for (anon_struct_type.names) |elem| std.hash.autoHash(hasher, elem);559 for (anon_struct_type.names) |elem| std.hash.autoHash(hasher, elem);
514 },560 },
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 },
515 }573 }
516 }574 }
517575
...@@ -670,6 +728,20 @@ pub const Key = union(enum) {...@@ -670,6 +728,20 @@ pub const Key = union(enum) {
670 std.mem.eql(Index, a_info.values, b_info.values) and728 std.mem.eql(Index, a_info.values, b_info.values) and
671 std.mem.eql(NullTerminatedString, a_info.names, b_info.names);729 std.mem.eql(NullTerminatedString, a_info.names, b_info.names);
672 },730 },
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 },
673 }745 }
674 }746 }
675747
...@@ -687,6 +759,7 @@ pub const Key = union(enum) {...@@ -687,6 +759,7 @@ pub const Key = union(enum) {
687 .opaque_type,759 .opaque_type,
688 .enum_type,760 .enum_type,
689 .anon_struct_type,761 .anon_struct_type,
762 .func_type,
690 => .type_type,763 => .type_type,
691764
692 inline .ptr,765 inline .ptr,
...@@ -734,7 +807,6 @@ pub const Index = enum(u32) {...@@ -734,7 +807,6 @@ pub const Index = enum(u32) {
734 pub const last_value: Index = .empty_struct;807 pub const last_value: Index = .empty_struct;
735808
736 u1_type,809 u1_type,
737 u5_type,
738 u8_type,810 u8_type,
739 i8_type,811 i8_type,
740 u16_type,812 u16_type,
...@@ -811,10 +883,10 @@ pub const Index = enum(u32) {...@@ -811,10 +883,10 @@ pub const Index = enum(u32) {
811 one,883 one,
812 /// `1` (usize)884 /// `1` (usize)
813 one_usize,885 one_usize,
814 /// `1` (u5)886 /// `1` (u8)
815 one_u5,887 one_u8,
816 /// `4` (u5)888 /// `4` (u8)
817 four_u5,889 four_u8,
818 /// `-1` (comptime_int)890 /// `-1` (comptime_int)
819 negative_one,891 negative_one,
820 /// `std.builtin.CallingConvention.C`892 /// `std.builtin.CallingConvention.C`
...@@ -880,12 +952,6 @@ pub const static_keys = [_]Key{...@@ -880,12 +952,6 @@ pub const static_keys = [_]Key{
880 .bits = 1,952 .bits = 1,
881 } },953 } },
882954
883 // u5_type
884 .{ .int_type = .{
885 .signedness = .unsigned,
886 .bits = 5,
887 } },
888
889 .{ .int_type = .{955 .{ .int_type = .{
890 .signedness = .unsigned,956 .signedness = .unsigned,
891 .bits = 8,957 .bits = 8,
...@@ -1074,14 +1140,14 @@ pub const static_keys = [_]Key{...@@ -1074,14 +1140,14 @@ pub const static_keys = [_]Key{
1074 .storage = .{ .u64 = 1 },1140 .storage = .{ .u64 = 1 },
1075 } },1141 } },
10761142
1077 // one_u51143 // one_u8
1078 .{ .int = .{1144 .{ .int = .{
1079 .ty = .u5_type,1145 .ty = .u8_type,
1080 .storage = .{ .u64 = 1 },1146 .storage = .{ .u64 = 1 },
1081 } },1147 } },
1082 // four_u51148 // four_u8
1083 .{ .int = .{1149 .{ .int = .{
1084 .ty = .u5_type,1150 .ty = .u8_type,
1085 .storage = .{ .u64 = 4 },1151 .storage = .{ .u64 = 4 },
1086 } },1152 } },
1087 // negative_one1153 // negative_one
...@@ -1092,12 +1158,12 @@ pub const static_keys = [_]Key{...@@ -1092,12 +1158,12 @@ pub const static_keys = [_]Key{
1092 // calling_convention_c1158 // calling_convention_c
1093 .{ .enum_tag = .{1159 .{ .enum_tag = .{
1094 .ty = .calling_convention_type,1160 .ty = .calling_convention_type,
1095 .int = .one_u5,1161 .int = .one_u8,
1096 } },1162 } },
1097 // calling_convention_inline1163 // calling_convention_inline
1098 .{ .enum_tag = .{1164 .{ .enum_tag = .{
1099 .ty = .calling_convention_type,1165 .ty = .calling_convention_type,
1100 .int = .four_u5,1166 .int = .four_u8,
1101 } },1167 } },
11021168
1103 .{ .simple_value = .void },1169 .{ .simple_value = .void },
...@@ -1181,6 +1247,9 @@ pub const Tag = enum(u8) {...@@ -1181,6 +1247,9 @@ pub const Tag = enum(u8) {
1181 /// An untagged union type which has a safety tag.1247 /// An untagged union type which has a safety tag.
1182 /// `data` is `Module.Union.Index`.1248 /// `data` is `Module.Union.Index`.
1183 type_union_safety,1249 type_union_safety,
1250 /// A function body type.
1251 /// `data` is extra index to `TypeFunction`.
1252 type_function,
11841253
1185 /// Typed `undefined`.1254 /// Typed `undefined`.
1186 /// `data` is `Index` of the type.1255 /// `data` is `Index` of the type.
...@@ -1283,6 +1352,29 @@ pub const Tag = enum(u8) {...@@ -1283,6 +1352,29 @@ pub const Tag = enum(u8) {
1283 aggregate,1352 aggregate,
1284};1353};
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
1286/// Trailing:1378/// Trailing:
1287/// 0. element: Index for each len1379/// 0. element: Index for each len
1288/// len is determined by the aggregate type.1380/// len is determined by the aggregate type.
...@@ -1371,24 +1463,6 @@ pub const Pointer = struct {...@@ -1371,24 +1463,6 @@ pub const Pointer = struct {
1371 flags: Flags,1463 flags: Flags,
1372 packed_offset: PackedOffset,1464 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
1392 pub const Flags = packed struct(u32) {1466 pub const Flags = packed struct(u32) {
1393 size: Size,1467 size: Size,
1394 alignment: Alignment,1468 alignment: Alignment,
...@@ -1409,6 +1483,24 @@ pub const Pointer = struct {...@@ -1409,6 +1483,24 @@ pub const Pointer = struct {
1409 pub const VectorIndex = Key.PtrType.VectorIndex;1483 pub const VectorIndex = Key.PtrType.VectorIndex;
1410};1484};
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
1412/// Used for non-sentineled arrays that have length fitting in u32, as well as1504/// Used for non-sentineled arrays that have length fitting in u32, as well as
1413/// vectors.1505/// vectors.
1414pub const Vector = struct {1506pub const Vector = struct {
...@@ -1765,6 +1857,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -1765,6 +1857,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
1765 },1857 },
1766 .type_enum_explicit => indexToKeyEnum(ip, data, .explicit),1858 .type_enum_explicit => indexToKeyEnum(ip, data, .explicit),
1767 .type_enum_nonexhaustive => indexToKeyEnum(ip, data, .nonexhaustive),1859 .type_enum_nonexhaustive => indexToKeyEnum(ip, data, .nonexhaustive),
1860 .type_function => .{ .func_type = indexToKeyFuncType(ip, data) },
17681861
1769 .undef => .{ .undef = @intToEnum(Index, data) },1862 .undef => .{ .undef = @intToEnum(Index, data) },
1770 .opt_null => .{ .opt = .{1863 .opt_null => .{ .opt = .{
...@@ -1896,6 +1989,29 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {...@@ -1896,6 +1989,29 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
1896 };1989 };
1897}1990}
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
1899/// Asserts the integer tag type is already present in the InternPool.2015/// Asserts the integer tag type is already present in the InternPool.
1900fn getEnumIntTagType(ip: InternPool, fields_len: u32) Index {2016fn getEnumIntTagType(ip: InternPool, fields_len: u32) Index {
1901 return ip.getAssumeExists(.{ .int_type = .{2017 return ip.getAssumeExists(.{ .int_type = .{
...@@ -1977,7 +2093,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -1977,7 +2093,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
1977 .child = ptr_type.elem_type,2093 .child = ptr_type.elem_type,
1978 .sentinel = ptr_type.sentinel,2094 .sentinel = ptr_type.sentinel,
1979 .flags = .{2095 .flags = .{
1980 .alignment = Pointer.Alignment.fromByteUnits(ptr_type.alignment),2096 .alignment = Alignment.fromByteUnits(ptr_type.alignment),
1981 .is_const = ptr_type.is_const,2097 .is_const = ptr_type.is_const,
1982 .is_volatile = ptr_type.is_volatile,2098 .is_volatile = ptr_type.is_volatile,
1983 .is_allowzero = ptr_type.is_allowzero,2099 .is_allowzero = ptr_type.is_allowzero,
...@@ -2163,6 +2279,37 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -2163,6 +2279,37 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
2163 }2279 }
2164 },2280 },
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
2166 .extern_func => @panic("TODO"),2313 .extern_func => @panic("TODO"),
21672314
2168 .ptr => |ptr| switch (ptr.addr) {2315 .ptr => |ptr| switch (ptr.addr) {
...@@ -2736,6 +2883,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {...@@ -2736,6 +2883,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
2736 OptionalMapIndex => @enumToInt(@field(extra, field.name)),2883 OptionalMapIndex => @enumToInt(@field(extra, field.name)),
2737 i32 => @bitCast(u32, @field(extra, field.name)),2884 i32 => @bitCast(u32, @field(extra, field.name)),
2738 Pointer.Flags => @bitCast(u32, @field(extra, field.name)),2885 Pointer.Flags => @bitCast(u32, @field(extra, field.name)),
2886 TypeFunction.Flags => @bitCast(u32, @field(extra, field.name)),
2739 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),2887 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
2740 Pointer.VectorIndex => @enumToInt(@field(extra, field.name)),2888 Pointer.VectorIndex => @enumToInt(@field(extra, field.name)),
2741 else => @compileError("bad field type: " ++ @typeName(field.type)),2889 else => @compileError("bad field type: " ++ @typeName(field.type)),
...@@ -2797,6 +2945,7 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:...@@ -2797,6 +2945,7 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:
2797 OptionalMapIndex => @intToEnum(OptionalMapIndex, int32),2945 OptionalMapIndex => @intToEnum(OptionalMapIndex, int32),
2798 i32 => @bitCast(i32, int32),2946 i32 => @bitCast(i32, int32),
2799 Pointer.Flags => @bitCast(Pointer.Flags, int32),2947 Pointer.Flags => @bitCast(Pointer.Flags, int32),
2948 TypeFunction.Flags => @bitCast(TypeFunction.Flags, int32),
2800 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),2949 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),
2801 Pointer.VectorIndex => @intToEnum(Pointer.VectorIndex, int32),2950 Pointer.VectorIndex => @intToEnum(Pointer.VectorIndex, int32),
2802 else => @compileError("bad field type: " ++ @typeName(field.type)),2951 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...@@ -2988,17 +3137,17 @@ pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Ind
2988 }3137 }
2989}3138}
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);
2992 const tags = ip.items.items(.tag);3142 const tags = ip.items.items(.tag);
2993 if (val == .none) return .none;
2994 if (tags[@enumToInt(val)] != .type_struct) return .none;3143 if (tags[@enumToInt(val)] != .type_struct) return .none;
2995 const datas = ip.items.items(.data);3144 const datas = ip.items.items(.data);
2996 return @intToEnum(Module.Struct.Index, datas[@enumToInt(val)]).toOptional();3145 return @intToEnum(Module.Struct.Index, datas[@enumToInt(val)]).toOptional();
2997}3146}
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);
3000 const tags = ip.items.items(.tag);3150 const tags = ip.items.items(.tag);
3001 if (val == .none) return .none;
3002 switch (tags[@enumToInt(val)]) {3151 switch (tags[@enumToInt(val)]) {
3003 .type_union_tagged, .type_union_untagged, .type_union_safety => {},3152 .type_union_tagged, .type_union_untagged, .type_union_safety => {},
3004 else => return .none,3153 else => return .none,
...@@ -3007,6 +3156,16 @@ pub fn indexToUnion(ip: *InternPool, val: Index) Module.Union.OptionalIndex {...@@ -3007,6 +3156,16 @@ pub fn indexToUnion(ip: *InternPool, val: Index) Module.Union.OptionalIndex {
3007 return @intToEnum(Module.Union.Index, datas[@enumToInt(val)]).toOptional();3156 return @intToEnum(Module.Union.Index, datas[@enumToInt(val)]).toOptional();
3008}3157}
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
3010pub fn isOptionalType(ip: InternPool, ty: Index) bool {3169pub fn isOptionalType(ip: InternPool, ty: Index) bool {
3011 const tags = ip.items.items(.tag);3170 const tags = ip.items.items(.tag);
3012 if (ty == .none) return false;3171 if (ty == .none) return false;
...@@ -3092,6 +3251,11 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {...@@ -3092,6 +3251,11 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
3092 .type_union_safety,3251 .type_union_safety,
3093 => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),3252 => @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
3095 .undef => 0,3259 .undef => 0,
3096 .simple_type => 0,3260 .simple_type => 0,
3097 .simple_value => 0,3261 .simple_value => 0,
src/Module.zig+30-8
...@@ -846,7 +846,7 @@ pub const Decl = struct {...@@ -846,7 +846,7 @@ pub const Decl = struct {
846 pub fn getStructIndex(decl: *Decl, mod: *Module) Struct.OptionalIndex {846 pub fn getStructIndex(decl: *Decl, mod: *Module) Struct.OptionalIndex {
847 if (!decl.owns_tv) return .none;847 if (!decl.owns_tv) return .none;
848 const ty = (decl.val.castTag(.ty) orelse return .none).data;848 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);
850 }850 }
851851
852 /// If the Decl has a value and it is a union, return it,852 /// 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 {...@@ -4764,7 +4764,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4764 decl.analysis = .complete;4764 decl.analysis = .complete;
4765 decl.generation = mod.generation;4765 decl.generation = mod.generation;
47664766
4767 const is_inline = decl.ty.fnCallingConvention() == .Inline;4767 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
4768 if (decl.is_exported) {4768 if (decl.is_exported) {
4769 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };4769 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
4770 if (is_inline) {4770 if (is_inline) {
...@@ -5617,6 +5617,9 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5617,6 +5617,9 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5617 const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);5617 const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);
5618 defer decl.value_arena.?.release(&decl_arena);5618 defer decl.value_arena.?.release(&decl_arena);
56195619
5620 const fn_ty = decl.ty;
5621 const fn_ty_info = mod.typeToFunc(fn_ty).?;
5622
5620 var sema: Sema = .{5623 var sema: Sema = .{
5621 .mod = mod,5624 .mod = mod,
5622 .gpa = gpa,5625 .gpa = gpa,
...@@ -5626,7 +5629,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5626,7 +5629,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5626 .owner_decl = decl,5629 .owner_decl = decl,
5627 .owner_decl_index = decl_index,5630 .owner_decl_index = decl_index,
5628 .func = func,5631 .func = func,
5629 .fn_ret_ty = decl.ty.fnReturnType(),5632 .fn_ret_ty = fn_ty_info.return_type.toType(),
5630 .owner_func = func,5633 .owner_func = func,
5631 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),5634 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
5632 };5635 };
...@@ -5664,8 +5667,6 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5664,8 +5667,6 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5664 // This could be a generic function instantiation, however, in which case we need to5667 // This could be a generic function instantiation, however, in which case we need to
5665 // map the comptime parameters to constant values and only emit arg AIR instructions5668 // map the comptime parameters to constant values and only emit arg AIR instructions
5666 // for the runtime ones.5669 // for the runtime ones.
5667 const fn_ty = decl.ty;
5668 const fn_ty_info = fn_ty.fnInfo();
5669 const runtime_params_len = @intCast(u32, fn_ty_info.param_types.len);5670 const runtime_params_len = @intCast(u32, fn_ty_info.param_types.len);
5670 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);5671 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
5671 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`5672 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 {...@@ -5692,7 +5693,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5692 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);5693 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
5693 total_param_index += 1;5694 total_param_index += 1;
5694 continue;5695 continue;
5695 } else fn_ty_info.param_types[runtime_param_index];5696 } else fn_ty_info.param_types[runtime_param_index].toType();
56965697
5697 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {5698 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
5698 error.NeededSourceLocation => unreachable,5699 error.NeededSourceLocation => unreachable,
...@@ -6864,6 +6865,10 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {...@@ -6864,6 +6865,10 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6864 return ptrType(mod, .{ .elem_type = child_type.ip_index, .is_const = true });6865 return ptrType(mod, .{ .elem_type = child_type.ip_index, .is_const = true });
6865}6866}
68666867
6868pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Type {
6869 return (try intern(mod, .{ .func_type = info })).toType();
6870}
6871
6867/// Supports optionals in addition to pointers.6872/// Supports optionals in addition to pointers.
6868pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {6873pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
6869 if (ty.isPtrLikeOptional(mod)) {6874 if (ty.isPtrLikeOptional(mod)) {
...@@ -6996,6 +7001,16 @@ pub fn floatValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value {...@@ -6996,6 +7001,16 @@ pub fn floatValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value {
6996 return i.toValue();7001 return i.toValue();
6997}7002}
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
6999pub fn smallestUnsignedInt(mod: *Module, max: u64) Allocator.Error!Type {7014pub fn smallestUnsignedInt(mod: *Module, max: u64) Allocator.Error!Type {
7000 return intType(mod, .unsigned, Type.smallestUnsignedBits(max));7015 return intType(mod, .unsigned, Type.smallestUnsignedBits(max));
7001}7016}
...@@ -7201,15 +7216,22 @@ pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.I...@@ -7201,15 +7216,22 @@ pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.I
7201/// * A struct which has no fields (`struct {}`).7216/// * A struct which has no fields (`struct {}`).
7202/// * Not a struct.7217/// * Not a struct.
7203pub fn typeToStruct(mod: *Module, ty: Type) ?*Struct {7218pub 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;
7205 return mod.structPtr(struct_index);7221 return mod.structPtr(struct_index);
7206}7222}
72077223
7208pub fn typeToUnion(mod: *Module, ty: Type) ?*Union {7224pub 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;
7210 return mod.unionPtr(union_index);7227 return mod.unionPtr(union_index);
7211}7228}
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
7213pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {7235pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {
7214 @setCold(true);7236 @setCold(true);
7215 const owner_decl = mod.declPtr(owner_decl_index);7237 const owner_decl = mod.declPtr(owner_decl_index);
src/Sema.zig+166-168
...@@ -5850,6 +5850,7 @@ pub fn analyzeExport(...@@ -5850,6 +5850,7 @@ pub fn analyzeExport(
5850}5850}
58515851
5852fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {5852fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
5853 const mod = sema.mod;
5853 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;5854 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
5854 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };5855 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
5855 const src = LazySrcLoc.nodeOffset(extra.node);5856 const src = LazySrcLoc.nodeOffset(extra.node);
...@@ -5862,8 +5863,8 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -5862,8 +5863,8 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5862 const func = sema.func orelse5863 const func = sema.func orelse
5863 return sema.fail(block, src, "@setAlignStack outside function body", .{});5864 return sema.fail(block, src, "@setAlignStack outside function body", .{});
58645865
5865 const fn_owner_decl = sema.mod.declPtr(func.owner_decl);5866 const fn_owner_decl = mod.declPtr(func.owner_decl);
5866 switch (fn_owner_decl.ty.fnCallingConvention()) {5867 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
5867 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),5868 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
5868 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),5869 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),
5869 else => if (block.inlining != null) {5870 else => if (block.inlining != null) {
...@@ -5871,7 +5872,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -5871,7 +5872,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
5871 },5872 },
5872 }5873 }
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);
5875 if (gop.found_existing) {5876 if (gop.found_existing) {
5876 const msg = msg: {5877 const msg = msg: {
5877 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});5878 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});
...@@ -6378,7 +6379,7 @@ fn zirCall(...@@ -6378,7 +6379,7 @@ fn zirCall(
6378 var input_is_error = false;6379 var input_is_error = false;
6379 const block_index = @intCast(Air.Inst.Index, block.instructions.items.len);6380 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).?;
6382 const fn_params_len = func_ty_info.param_types.len;6383 const fn_params_len = func_ty_info.param_types.len;
6383 const parent_comptime = block.is_comptime;6384 const parent_comptime = block.is_comptime;
6384 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.6385 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
...@@ -6393,7 +6394,7 @@ fn zirCall(...@@ -6393,7 +6394,7 @@ fn zirCall(
63936394
6394 // Generate args to comptime params in comptime block.6395 // Generate args to comptime params in comptime block.
6395 defer block.is_comptime = parent_comptime;6396 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))) {
6397 block.is_comptime = true;6398 block.is_comptime = true;
6398 // TODO set comptime_reason6399 // TODO set comptime_reason
6399 }6400 }
...@@ -6402,10 +6403,10 @@ fn zirCall(...@@ -6402,10 +6403,10 @@ fn zirCall(
6402 if (arg_index >= fn_params_len)6403 if (arg_index >= fn_params_len)
6403 break :inst Air.Inst.Ref.var_args_param_type;6404 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)
6406 break :inst Air.Inst.Ref.generic_poison_type;6407 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());
6409 });6410 });
64106411
6411 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);6412 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
...@@ -6506,7 +6507,7 @@ fn checkCallArgumentCount(...@@ -6506,7 +6507,7 @@ fn checkCallArgumentCount(
6506 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(sema.mod)});6507 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(sema.mod)});
6507 };6508 };
65086509
6509 const func_ty_info = func_ty.fnInfo();6510 const func_ty_info = mod.typeToFunc(func_ty).?;
6510 const fn_params_len = func_ty_info.param_types.len;6511 const fn_params_len = func_ty_info.param_types.len;
6511 const args_len = total_args - @boolToInt(member_fn);6512 const args_len = total_args - @boolToInt(member_fn);
6512 if (func_ty_info.is_var_args) {6513 if (func_ty_info.is_var_args) {
...@@ -6562,7 +6563,7 @@ fn callBuiltin(...@@ -6562,7 +6563,7 @@ fn callBuiltin(
6562 std.debug.panic("type '{}' is not a function calling builtin fn", .{callee_ty.fmt(sema.mod)});6563 std.debug.panic("type '{}' is not a function calling builtin fn", .{callee_ty.fmt(sema.mod)});
6563 };6564 };
65646565
6565 const func_ty_info = func_ty.fnInfo();6566 const func_ty_info = mod.typeToFunc(func_ty).?;
6566 const fn_params_len = func_ty_info.param_types.len;6567 const fn_params_len = func_ty_info.param_types.len;
6567 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) {6568 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) {
6568 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len });6569 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len });
...@@ -6573,7 +6574,7 @@ fn callBuiltin(...@@ -6573,7 +6574,7 @@ fn callBuiltin(
6573const GenericCallAdapter = struct {6574const GenericCallAdapter = struct {
6574 generic_fn: *Module.Fn,6575 generic_fn: *Module.Fn,
6575 precomputed_hash: u64,6576 precomputed_hash: u64,
6576 func_ty_info: Type.Payload.Function.Data,6577 func_ty_info: InternPool.Key.FuncType,
6577 args: []const Arg,6578 args: []const Arg,
6578 module: *Module,6579 module: *Module,
65796580
...@@ -6656,7 +6657,7 @@ fn analyzeCall(...@@ -6656,7 +6657,7 @@ fn analyzeCall(
6656 const mod = sema.mod;6657 const mod = sema.mod;
66576658
6658 const callee_ty = sema.typeOf(func);6659 const callee_ty = sema.typeOf(func);
6659 const func_ty_info = func_ty.fnInfo();6660 const func_ty_info = mod.typeToFunc(func_ty).?;
6660 const fn_params_len = func_ty_info.param_types.len;6661 const fn_params_len = func_ty_info.param_types.len;
6661 const cc = func_ty_info.cc;6662 const cc = func_ty_info.cc;
6662 if (cc == .Naked) {6663 if (cc == .Naked) {
...@@ -6704,7 +6705,7 @@ fn analyzeCall(...@@ -6704,7 +6705,7 @@ fn analyzeCall(
6704 var comptime_reason_buf: Block.ComptimeReason = undefined;6705 var comptime_reason_buf: Block.ComptimeReason = undefined;
6705 var comptime_reason: ?*const Block.ComptimeReason = null;6706 var comptime_reason: ?*const Block.ComptimeReason = null;
6706 if (!is_comptime_call) {6707 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| {
6708 is_comptime_call = ct;6709 is_comptime_call = ct;
6709 if (ct) {6710 if (ct) {
6710 // stage1 can't handle doing this directly6711 // stage1 can't handle doing this directly
...@@ -6712,7 +6713,7 @@ fn analyzeCall(...@@ -6712,7 +6713,7 @@ fn analyzeCall(
6712 .block = block,6713 .block = block,
6713 .func = func,6714 .func = func,
6714 .func_src = func_src,6715 .func_src = func_src,
6715 .return_ty = func_ty_info.return_type,6716 .return_ty = func_ty_info.return_type.toType(),
6716 } };6717 } };
6717 comptime_reason = &comptime_reason_buf;6718 comptime_reason = &comptime_reason_buf;
6718 }6719 }
...@@ -6750,7 +6751,7 @@ fn analyzeCall(...@@ -6750,7 +6751,7 @@ fn analyzeCall(
6750 .block = block,6751 .block = block,
6751 .func = func,6752 .func = func,
6752 .func_src = func_src,6753 .func_src = func_src,
6753 .return_ty = func_ty_info.return_type,6754 .return_ty = func_ty_info.return_type.toType(),
6754 } };6755 } };
6755 comptime_reason = &comptime_reason_buf;6756 comptime_reason = &comptime_reason_buf;
6756 },6757 },
...@@ -6875,9 +6876,9 @@ fn analyzeCall(...@@ -6875,9 +6876,9 @@ fn analyzeCall(
6875 // comptime state.6876 // comptime state.
6876 var should_memoize = true;6877 var should_memoize = true;
68776878
6878 var new_fn_info = fn_owner_decl.ty.fnInfo();6879 var new_fn_info = mod.typeToFunc(fn_owner_decl.ty).?;
6879 new_fn_info.param_types = try sema.arena.alloc(Type, new_fn_info.param_types.len);6880 new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len);
6880 new_fn_info.comptime_params = (try sema.arena.alloc(bool, new_fn_info.param_types.len)).ptr;6881 new_fn_info.comptime_bits = 0;
68816882
6882 // This will have return instructions analyzed as break instructions to6883 // This will have return instructions analyzed as break instructions to
6883 // the block_inst above. Here we are performing "comptime/inline semantic analysis"6884 // the block_inst above. Here we are performing "comptime/inline semantic analysis"
...@@ -6970,7 +6971,7 @@ fn analyzeCall(...@@ -6970,7 +6971,7 @@ fn analyzeCall(
6970 }6971 }
6971 break :blk bare_return_type;6972 break :blk bare_return_type;
6972 };6973 };
6973 new_fn_info.return_type = fn_ret_ty;6974 new_fn_info.return_type = fn_ret_ty.ip_index;
6974 const parent_fn_ret_ty = sema.fn_ret_ty;6975 const parent_fn_ret_ty = sema.fn_ret_ty;
6975 sema.fn_ret_ty = fn_ret_ty;6976 sema.fn_ret_ty = fn_ret_ty;
6976 defer sema.fn_ret_ty = parent_fn_ret_ty;6977 defer sema.fn_ret_ty = parent_fn_ret_ty;
...@@ -6993,7 +6994,7 @@ fn analyzeCall(...@@ -6993,7 +6994,7 @@ fn analyzeCall(
6993 }6994 }
6994 }6995 }
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);
6997 if (!is_comptime_call and !block.is_typeof) {6998 if (!is_comptime_call and !block.is_typeof) {
6998 try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin);6999 try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin);
69997000
...@@ -7081,13 +7082,14 @@ fn analyzeCall(...@@ -7081,13 +7082,14 @@ fn analyzeCall(
7081 assert(!func_ty_info.is_generic);7082 assert(!func_ty_info.is_generic);
70827083
7083 const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len);7084 const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len);
7085 const fn_info = mod.typeToFunc(func_ty).?;
7084 for (uncasted_args, 0..) |uncasted_arg, i| {7086 for (uncasted_args, 0..) |uncasted_arg, i| {
7085 if (i < fn_params_len) {7087 if (i < fn_params_len) {
7086 const opts: CoerceOpts = .{ .param_src = .{7088 const opts: CoerceOpts = .{ .param_src = .{
7087 .func_inst = func,7089 .func_inst = func,
7088 .param_i = @intCast(u32, i),7090 .param_i = @intCast(u32, i),
7089 } };7091 } };
7090 const param_ty = func_ty.fnParamType(i);7092 const param_ty = fn_info.param_types[i].toType();
7091 args[i] = sema.analyzeCallArg(7093 args[i] = sema.analyzeCallArg(
7092 block,7094 block,
7093 .unneeded,7095 .unneeded,
...@@ -7126,8 +7128,8 @@ fn analyzeCall(...@@ -7126,8 +7128,8 @@ fn analyzeCall(
71267128
7127 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);7129 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
71287130
7129 try sema.queueFullTypeResolution(func_ty_info.return_type);7131 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7130 if (sema.owner_func != null and func_ty_info.return_type.isError(mod)) {7132 if (sema.owner_func != null and func_ty_info.return_type.toType().isError(mod)) {
7131 sema.owner_func.?.calls_or_awaits_errorable_fn = true;7133 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
7132 }7134 }
71337135
...@@ -7155,7 +7157,7 @@ fn analyzeCall(...@@ -7155,7 +7157,7 @@ fn analyzeCall(
7155 try sema.ensureResultUsed(block, sema.typeOf(func_inst), call_src);7157 try sema.ensureResultUsed(block, sema.typeOf(func_inst), call_src);
7156 }7158 }
7157 return sema.handleTailCall(block, call_src, func_ty, func_inst);7159 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) {
7159 // Function pointers and extern functions aren't guaranteed to7161 // Function pointers and extern functions aren't guaranteed to
7160 // actually be noreturn so we add a safety check for them.7162 // actually be noreturn so we add a safety check for them.
7161 check: {7163 check: {
...@@ -7171,7 +7173,7 @@ fn analyzeCall(...@@ -7171,7 +7173,7 @@ fn analyzeCall(
71717173
7172 try sema.safetyPanic(block, .noreturn_returned);7174 try sema.safetyPanic(block, .noreturn_returned);
7173 return Air.Inst.Ref.unreachable_value;7175 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) {
7175 _ = try block.addNoOp(.unreach);7177 _ = try block.addNoOp(.unreach);
7176 return Air.Inst.Ref.unreachable_value;7178 return Air.Inst.Ref.unreachable_value;
7177 }7179 }
...@@ -7208,13 +7210,13 @@ fn analyzeInlineCallArg(...@@ -7208,13 +7210,13 @@ fn analyzeInlineCallArg(
7208 param_block: *Block,7210 param_block: *Block,
7209 arg_src: LazySrcLoc,7211 arg_src: LazySrcLoc,
7210 inst: Zir.Inst.Index,7212 inst: Zir.Inst.Index,
7211 new_fn_info: Type.Payload.Function.Data,7213 new_fn_info: InternPool.Key.FuncType,
7212 arg_i: *usize,7214 arg_i: *usize,
7213 uncasted_args: []const Air.Inst.Ref,7215 uncasted_args: []const Air.Inst.Ref,
7214 is_comptime_call: bool,7216 is_comptime_call: bool,
7215 should_memoize: *bool,7217 should_memoize: *bool,
7216 memoized_call_key: Module.MemoizedCall.Key,7218 memoized_call_key: Module.MemoizedCall.Key,
7217 raw_param_types: []const Type,7219 raw_param_types: []const InternPool.Index,
7218 func_inst: Air.Inst.Ref,7220 func_inst: Air.Inst.Ref,
7219 has_comptime_args: *bool,7221 has_comptime_args: *bool,
7220) !void {7222) !void {
...@@ -7233,13 +7235,14 @@ fn analyzeInlineCallArg(...@@ -7233,13 +7235,14 @@ fn analyzeInlineCallArg(
7233 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];7235 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
7234 const param_ty = param_ty: {7236 const param_ty = param_ty: {
7235 const raw_param_ty = raw_param_types[arg_i.*];7237 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;
7237 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);7239 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();
7239 };7242 };
7240 new_fn_info.param_types[arg_i.*] = param_ty;7243 new_fn_info.param_types[arg_i.*] = param_ty;
7241 const uncasted_arg = uncasted_args[arg_i.*];7244 const uncasted_arg = uncasted_args[arg_i.*];
7242 if (try sema.typeRequiresComptime(param_ty)) {7245 if (try sema.typeRequiresComptime(param_ty.toType())) {
7243 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {7246 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {
7244 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);7247 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
7245 return err;7248 return err;
...@@ -7247,7 +7250,7 @@ fn analyzeInlineCallArg(...@@ -7247,7 +7250,7 @@ fn analyzeInlineCallArg(
7247 } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) {7250 } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) {
7248 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");7251 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
7249 }7252 }
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 = .{
7251 .func_inst = func_inst,7254 .func_inst = func_inst,
7252 .param_i = @intCast(u32, arg_i.*),7255 .param_i = @intCast(u32, arg_i.*),
7253 } }) catch |err| switch (err) {7256 } }) catch |err| switch (err) {
...@@ -7276,7 +7279,7 @@ fn analyzeInlineCallArg(...@@ -7276,7 +7279,7 @@ fn analyzeInlineCallArg(
7276 }7279 }
7277 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();7280 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
7278 memoized_call_key.args[arg_i.*] = .{7281 memoized_call_key.args[arg_i.*] = .{
7279 .ty = param_ty,7282 .ty = param_ty.toType(),
7280 .val = arg_val,7283 .val = arg_val,
7281 };7284 };
7282 } else {7285 } else {
...@@ -7292,7 +7295,7 @@ fn analyzeInlineCallArg(...@@ -7292,7 +7295,7 @@ fn analyzeInlineCallArg(
7292 .param_anytype, .param_anytype_comptime => {7295 .param_anytype, .param_anytype_comptime => {
7293 // No coercion needed.7296 // No coercion needed.
7294 const uncasted_arg = uncasted_args[arg_i.*];7297 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
7297 if (is_comptime_call) {7300 if (is_comptime_call) {
7298 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);7301 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
...@@ -7357,7 +7360,7 @@ fn analyzeGenericCallArg(...@@ -7357,7 +7360,7 @@ fn analyzeGenericCallArg(
7357 uncasted_arg: Air.Inst.Ref,7360 uncasted_arg: Air.Inst.Ref,
7358 comptime_arg: TypedValue,7361 comptime_arg: TypedValue,
7359 runtime_args: []Air.Inst.Ref,7362 runtime_args: []Air.Inst.Ref,
7360 new_fn_info: Type.Payload.Function.Data,7363 new_fn_info: InternPool.Key.FuncType,
7361 runtime_i: *u32,7364 runtime_i: *u32,
7362) !void {7365) !void {
7363 const mod = sema.mod;7366 const mod = sema.mod;
...@@ -7365,7 +7368,7 @@ fn analyzeGenericCallArg(...@@ -7365,7 +7368,7 @@ fn analyzeGenericCallArg(
7365 comptime_arg.ty.hasRuntimeBits(mod) and7368 comptime_arg.ty.hasRuntimeBits(mod) and
7366 !(try sema.typeRequiresComptime(comptime_arg.ty));7369 !(try sema.typeRequiresComptime(comptime_arg.ty));
7367 if (is_runtime) {7370 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();
7369 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);7372 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
7370 try sema.queueFullTypeResolution(param_ty);7373 try sema.queueFullTypeResolution(param_ty);
7371 runtime_args[runtime_i.*] = casted_arg;7374 runtime_args[runtime_i.*] = casted_arg;
...@@ -7387,7 +7390,7 @@ fn instantiateGenericCall(...@@ -7387,7 +7390,7 @@ fn instantiateGenericCall(
7387 func: Air.Inst.Ref,7390 func: Air.Inst.Ref,
7388 func_src: LazySrcLoc,7391 func_src: LazySrcLoc,
7389 call_src: LazySrcLoc,7392 call_src: LazySrcLoc,
7390 func_ty_info: Type.Payload.Function.Data,7393 func_ty_info: InternPool.Key.FuncType,
7391 ensure_result_used: bool,7394 ensure_result_used: bool,
7392 uncasted_args: []const Air.Inst.Ref,7395 uncasted_args: []const Air.Inst.Ref,
7393 call_tag: Air.Inst.Tag,7396 call_tag: Air.Inst.Tag,
...@@ -7431,14 +7434,14 @@ fn instantiateGenericCall(...@@ -7431,14 +7434,14 @@ fn instantiateGenericCall(
7431 var is_anytype = false;7434 var is_anytype = false;
7432 switch (zir_tags[inst]) {7435 switch (zir_tags[inst]) {
7433 .param => {7436 .param => {
7434 is_comptime = func_ty_info.paramIsComptime(i);7437 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, i));
7435 },7438 },
7436 .param_comptime => {7439 .param_comptime => {
7437 is_comptime = true;7440 is_comptime = true;
7438 },7441 },
7439 .param_anytype => {7442 .param_anytype => {
7440 is_anytype = true;7443 is_anytype = true;
7441 is_comptime = func_ty_info.paramIsComptime(i);7444 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, i));
7442 },7445 },
7443 .param_anytype_comptime => {7446 .param_anytype_comptime => {
7444 is_anytype = true;7447 is_anytype = true;
...@@ -7609,7 +7612,7 @@ fn instantiateGenericCall(...@@ -7609,7 +7612,7 @@ fn instantiateGenericCall(
7609 // Make a runtime call to the new function, making sure to omit the comptime args.7612 // Make a runtime call to the new function, making sure to omit the comptime args.
7610 const comptime_args = callee.comptime_args.?;7613 const comptime_args = callee.comptime_args.?;
7611 const func_ty = mod.declPtr(callee.owner_decl).ty;7614 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).?;
7613 const runtime_args_len = @intCast(u32, new_fn_info.param_types.len);7616 const runtime_args_len = @intCast(u32, new_fn_info.param_types.len);
7614 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);7617 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
7615 {7618 {
...@@ -7647,12 +7650,12 @@ fn instantiateGenericCall(...@@ -7647,12 +7650,12 @@ fn instantiateGenericCall(
7647 total_i += 1;7650 total_i += 1;
7648 }7651 }
76497652
7650 try sema.queueFullTypeResolution(new_fn_info.return_type);7653 try sema.queueFullTypeResolution(new_fn_info.return_type.toType());
7651 }7654 }
76527655
7653 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);7656 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)) {
7656 sema.owner_func.?.calls_or_awaits_errorable_fn = true;7659 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
7657 }7660 }
76587661
...@@ -7677,7 +7680,7 @@ fn instantiateGenericCall(...@@ -7677,7 +7680,7 @@ fn instantiateGenericCall(
7677 if (call_tag == .call_always_tail) {7680 if (call_tag == .call_always_tail) {
7678 return sema.handleTailCall(block, call_src, func_ty, result);7681 return sema.handleTailCall(block, call_src, func_ty, result);
7679 }7682 }
7680 if (new_fn_info.return_type.isNoReturn()) {7683 if (new_fn_info.return_type == .noreturn_type) {
7681 _ = try block.addNoOp(.unreach);7684 _ = try block.addNoOp(.unreach);
7682 return Air.Inst.Ref.unreachable_value;7685 return Air.Inst.Ref.unreachable_value;
7683 }7686 }
...@@ -7695,7 +7698,7 @@ fn resolveGenericInstantiationType(...@@ -7695,7 +7698,7 @@ fn resolveGenericInstantiationType(
7695 module_fn: *Module.Fn,7698 module_fn: *Module.Fn,
7696 new_module_func: *Module.Fn,7699 new_module_func: *Module.Fn,
7697 namespace: Namespace.Index,7700 namespace: Namespace.Index,
7698 func_ty_info: Type.Payload.Function.Data,7701 func_ty_info: InternPool.Key.FuncType,
7699 call_src: LazySrcLoc,7702 call_src: LazySrcLoc,
7700 bound_arg_src: ?LazySrcLoc,7703 bound_arg_src: ?LazySrcLoc,
7701) !*Module.Fn {7704) !*Module.Fn {
...@@ -7755,14 +7758,14 @@ fn resolveGenericInstantiationType(...@@ -7755,14 +7758,14 @@ fn resolveGenericInstantiationType(
7755 var is_anytype = false;7758 var is_anytype = false;
7756 switch (zir_tags[inst]) {7759 switch (zir_tags[inst]) {
7757 .param => {7760 .param => {
7758 is_comptime = func_ty_info.paramIsComptime(arg_i);7761 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7759 },7762 },
7760 .param_comptime => {7763 .param_comptime => {
7761 is_comptime = true;7764 is_comptime = true;
7762 },7765 },
7763 .param_anytype => {7766 .param_anytype => {
7764 is_anytype = true;7767 is_anytype = true;
7765 is_comptime = func_ty_info.paramIsComptime(arg_i);7768 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7766 },7769 },
7767 .param_anytype_comptime => {7770 .param_anytype_comptime => {
7768 is_anytype = true;7771 is_anytype = true;
...@@ -7822,13 +7825,13 @@ fn resolveGenericInstantiationType(...@@ -7822,13 +7825,13 @@ fn resolveGenericInstantiationType(
7822 var is_comptime = false;7825 var is_comptime = false;
7823 switch (zir_tags[inst]) {7826 switch (zir_tags[inst]) {
7824 .param => {7827 .param => {
7825 is_comptime = func_ty_info.paramIsComptime(arg_i);7828 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7826 },7829 },
7827 .param_comptime => {7830 .param_comptime => {
7828 is_comptime = true;7831 is_comptime = true;
7829 },7832 },
7830 .param_anytype => {7833 .param_anytype => {
7831 is_comptime = func_ty_info.paramIsComptime(arg_i);7834 is_comptime = func_ty_info.paramIsComptime(@intCast(u5, arg_i));
7832 },7835 },
7833 .param_anytype_comptime => {7836 .param_anytype_comptime => {
7834 is_comptime = true;7837 is_comptime = true;
...@@ -7868,8 +7871,8 @@ fn resolveGenericInstantiationType(...@@ -7868,8 +7871,8 @@ fn resolveGenericInstantiationType(
7868 new_decl.ty = try child_sema.typeOf(new_func_inst).copy(new_decl_arena_allocator);7871 new_decl.ty = try child_sema.typeOf(new_func_inst).copy(new_decl_arena_allocator);
7869 // If the call evaluated to a return type that requires comptime, never mind7872 // If the call evaluated to a return type that requires comptime, never mind
7870 // our generic instantiation. Instead we need to perform a comptime call.7873 // our generic instantiation. Instead we need to perform a comptime call.
7871 const new_fn_info = new_decl.ty.fnInfo();7874 const new_fn_info = mod.typeToFunc(new_decl.ty).?;
7872 if (try sema.typeRequiresComptime(new_fn_info.return_type)) {7875 if (try sema.typeRequiresComptime(new_fn_info.return_type.toType())) {
7873 return error.ComptimeReturn;7876 return error.ComptimeReturn;
7874 }7877 }
7875 // Similarly, if the call evaluated to a generic type we need to instead7878 // Similarly, if the call evaluated to a generic type we need to instead
...@@ -8969,19 +8972,19 @@ fn funcCommon(...@@ -8969,19 +8972,19 @@ fn funcCommon(
8969 // the instantiation, which can depend on comptime parameters.8972 // the instantiation, which can depend on comptime parameters.
8970 // Related proposal: https://github.com/ziglang/zig/issues/118348973 // Related proposal: https://github.com/ziglang/zig/issues/11834
8971 const cc_resolved = cc orelse .Unspecified;8974 const cc_resolved = cc orelse .Unspecified;
8972 const param_types = try sema.arena.alloc(Type, block.params.items.len);8975 const param_types = try sema.arena.alloc(InternPool.Index, block.params.items.len);
8973 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);8976 var comptime_bits: u32 = 0;
8974 for (block.params.items, 0..) |param, i| {8977 for (param_types, block.params.items, 0..) |*dest_param_ty, param, i| {
8975 const is_noalias = blk: {8978 const is_noalias = blk: {
8976 const index = std.math.cast(u5, i) orelse break :blk false;8979 const index = std.math.cast(u5, i) orelse break :blk false;
8977 break :blk @truncate(u1, noalias_bits >> index) != 0;8980 break :blk @truncate(u1, noalias_bits >> index) != 0;
8978 };8981 };
8979 param_types[i] = param.ty;8982 dest_param_ty.* = param.ty.toIntern();
8980 sema.analyzeParameter(8983 sema.analyzeParameter(
8981 block,8984 block,
8982 .unneeded,8985 .unneeded,
8983 param,8986 param,
8984 comptime_params,8987 &comptime_bits,
8985 i,8988 i,
8986 &is_generic,8989 &is_generic,
8987 cc_resolved,8990 cc_resolved,
...@@ -8994,7 +8997,7 @@ fn funcCommon(...@@ -8994,7 +8997,7 @@ fn funcCommon(
8994 block,8997 block,
8995 Module.paramSrc(src_node_offset, mod, decl, i),8998 Module.paramSrc(src_node_offset, mod, decl, i),
8996 param,8999 param,
8997 comptime_params,9000 &comptime_bits,
8998 i,9001 i,
8999 &is_generic,9002 &is_generic,
9000 cc_resolved,9003 cc_resolved,
...@@ -9019,7 +9022,7 @@ fn funcCommon(...@@ -9019,7 +9022,7 @@ fn funcCommon(
9019 else => |e| return e,9022 else => |e| return e,
9020 };9023 };
90219024
9022 const return_type = if (!inferred_error_set or ret_poison)9025 const return_type: Type = if (!inferred_error_set or ret_poison)
9023 bare_return_type9026 bare_return_type
9024 else blk: {9027 else blk: {
9025 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);9028 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
...@@ -9047,7 +9050,9 @@ fn funcCommon(...@@ -9047,7 +9050,9 @@ fn funcCommon(
9047 };9050 };
9048 return sema.failWithOwnedErrorMsg(msg);9051 return sema.failWithOwnedErrorMsg(msg);
9049 }9052 }
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 {
9051 const msg = msg: {9056 const msg = msg: {
9052 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{9057 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
9053 return_type.fmt(sema.mod), @tagName(cc_resolved),9058 return_type.fmt(sema.mod), @tagName(cc_resolved),
...@@ -9141,8 +9146,7 @@ fn funcCommon(...@@ -9141,8 +9146,7 @@ fn funcCommon(
9141 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});9146 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
9142 }9147 }
9143 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;9148 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
9144 for (comptime_params) |ct| is_generic = is_generic or ct;9149 is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
9145 is_generic = is_generic or ret_ty_requires_comptime;
91469150
9147 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {9151 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {
9148 // Make sure that StackTrace's fields are resolved so that the backend can9152 // Make sure that StackTrace's fields are resolved so that the backend can
...@@ -9151,10 +9155,11 @@ fn funcCommon(...@@ -9151,10 +9155,11 @@ fn funcCommon(
9151 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);9155 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
9152 }9156 }
91539157
9154 break :fn_ty try Type.Tag.function.create(sema.arena, .{9158 break :fn_ty try mod.funcType(.{
9155 .param_types = param_types,9159 .param_types = param_types,
9156 .comptime_params = comptime_params.ptr,9160 .noalias_bits = noalias_bits,
9157 .return_type = return_type,9161 .comptime_bits = comptime_bits,
9162 .return_type = return_type.toIntern(),
9158 .cc = cc_resolved,9163 .cc = cc_resolved,
9159 .cc_is_generic = cc == null,9164 .cc_is_generic = cc == null,
9160 .alignment = alignment orelse 0,9165 .alignment = alignment orelse 0,
...@@ -9164,7 +9169,6 @@ fn funcCommon(...@@ -9164,7 +9169,6 @@ fn funcCommon(
9164 .is_var_args = var_args,9169 .is_var_args = var_args,
9165 .is_generic = is_generic,9170 .is_generic = is_generic,
9166 .is_noinline = is_noinline,9171 .is_noinline = is_noinline,
9167 .noalias_bits = noalias_bits,
9168 });9172 });
9169 };9173 };
91709174
...@@ -9203,7 +9207,7 @@ fn funcCommon(...@@ -9203,7 +9207,7 @@ fn funcCommon(
9203 return sema.addType(fn_ty);9207 return sema.addType(fn_ty);
9204 }9208 }
92059209
9206 const is_inline = fn_ty.fnCallingConvention() == .Inline;9210 const is_inline = fn_ty.fnCallingConvention(mod) == .Inline;
9207 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;9211 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;
92089212
9209 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {9213 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {
...@@ -9243,7 +9247,7 @@ fn analyzeParameter(...@@ -9243,7 +9247,7 @@ fn analyzeParameter(
9243 block: *Block,9247 block: *Block,
9244 param_src: LazySrcLoc,9248 param_src: LazySrcLoc,
9245 param: Block.Param,9249 param: Block.Param,
9246 comptime_params: []bool,9250 comptime_bits: *u32,
9247 i: usize,9251 i: usize,
9248 is_generic: *bool,9252 is_generic: *bool,
9249 cc: std.builtin.CallingConvention,9253 cc: std.builtin.CallingConvention,
...@@ -9252,14 +9256,16 @@ fn analyzeParameter(...@@ -9252,14 +9256,16 @@ fn analyzeParameter(
9252) !void {9256) !void {
9253 const mod = sema.mod;9257 const mod = sema.mod;
9254 const requires_comptime = try sema.typeRequiresComptime(param.ty);9258 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 }
9256 const this_generic = param.ty.isGenericPoison();9262 const this_generic = param.ty.isGenericPoison();
9257 is_generic.* = is_generic.* or this_generic;9263 is_generic.* = is_generic.* or this_generic;
9258 const target = mod.getTarget();9264 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)) {
9260 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});9266 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9261 }9267 }
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)) {
9263 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});9269 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9264 }9270 }
9265 if (!param.ty.isValidParamType(mod)) {9271 if (!param.ty.isValidParamType(mod)) {
...@@ -9275,7 +9281,7 @@ fn analyzeParameter(...@@ -9275,7 +9281,7 @@ fn analyzeParameter(
9275 };9281 };
9276 return sema.failWithOwnedErrorMsg(msg);9282 return sema.failWithOwnedErrorMsg(msg);
9277 }9283 }
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)) {
9279 const msg = msg: {9285 const msg = msg: {
9280 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{9286 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
9281 param.ty.fmt(mod), @tagName(cc),9287 param.ty.fmt(mod), @tagName(cc),
...@@ -15986,22 +15992,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15986,22 +15992,18 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15986 ),15992 ),
15987 .Fn => {15993 .Fn => {
15988 // TODO: look into memoizing this result.15994 // TODO: look into memoizing this result.
15989 const info = ty.fnInfo();15995 const info = mod.typeToFunc(ty).?;
1599015996
15991 var params_anon_decl = try block.startAnonDecl();15997 var params_anon_decl = try block.startAnonDecl();
15992 defer params_anon_decl.deinit();15998 defer params_anon_decl.deinit();
1599315999
15994 const param_vals = try params_anon_decl.arena().alloc(Value, info.param_types.len);16000 const param_vals = try params_anon_decl.arena().alloc(Value, info.param_types.len);
15995 for (param_vals, 0..) |*param_val, i| {16001 for (param_vals, info.param_types, 0..) |*param_val, param_ty, i| {
15996 const param_ty = info.param_types[i];16002 const is_generic = param_ty == .generic_poison_type;
15997 const is_generic = param_ty.isGenericPoison();16003 const param_ty_val = try mod.intern_pool.get(mod.gpa, .{ .opt = .{
15998 const param_ty_val = if (is_generic)16004 .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),
15999 Value.null16005 .val = if (is_generic) .none else param_ty,
16000 else16006 } });
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 );
1600516007
16006 const is_noalias = blk: {16008 const is_noalias = blk: {
16007 const index = std.math.cast(u5, i) orelse break :blk false;16009 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...@@ -16015,7 +16017,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16015 // is_noalias: bool,16017 // is_noalias: bool,
16016 Value.makeBool(is_noalias),16018 Value.makeBool(is_noalias),
16017 // type: ?type,16019 // type: ?type,
16018 param_ty_val,16020 param_ty_val.toValue(),
16019 };16021 };
16020 param_val.* = try Value.Tag.aggregate.create(params_anon_decl.arena(), param_fields);16022 param_val.* = try Value.Tag.aggregate.create(params_anon_decl.arena(), param_fields);
16021 }16023 }
...@@ -16059,13 +16061,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16059,13 +16061,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16059 });16061 });
16060 };16062 };
1606116063
16062 const ret_ty_opt = if (!info.return_type.isGenericPoison())16064 const ret_ty_opt = try mod.intern_pool.get(mod.gpa, .{ .opt = .{
16063 try Value.Tag.opt_payload.create(16065 .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),
16064 sema.arena,16066 .val = if (info.return_type == .generic_poison_type) .none else info.return_type,
16065 try Value.Tag.ty.create(sema.arena, info.return_type),16067 } });
16066 )
16067 else
16068 Value.null;
1606916068
16070 const callconv_ty = try sema.getBuiltinType("CallingConvention");16069 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1607116070
...@@ -16080,7 +16079,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -16080,7 +16079,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
16080 // is_var_args: bool,16079 // is_var_args: bool,
16081 Value.makeBool(info.is_var_args),16080 Value.makeBool(info.is_var_args),
16082 // return_type: ?type,16081 // return_type: ?type,
16083 ret_ty_opt,16082 ret_ty_opt.toValue(),
16084 // args: []const Fn.Param,16083 // args: []const Fn.Param,
16085 args_val,16084 args_val,
16086 };16085 };
...@@ -17788,7 +17787,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -17788,7 +17787,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17788 if (inst_data.size != .One) {17787 if (inst_data.size != .One) {
17789 return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});17788 return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});
17790 }17789 }
17791 const fn_align = elem_ty.fnInfo().alignment;17790 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
17792 if (inst_data.flags.has_align and abi_align != 0 and fn_align != 0 and17791 if (inst_data.flags.has_align and abi_align != 0 and fn_align != 0 and
17793 abi_align != fn_align)17792 abi_align != fn_align)
17794 {17793 {
...@@ -18939,7 +18938,7 @@ fn zirReify(...@@ -18939,7 +18938,7 @@ fn zirReify(
18939 if (ptr_size != .One) {18938 if (ptr_size != .One) {
18940 return sema.fail(block, src, "function pointers must be single pointers", .{});18939 return sema.fail(block, src, "function pointers must be single pointers", .{});
18941 }18940 }
18942 const fn_align = elem_ty.fnInfo().alignment;18941 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
18943 if (abi_align != 0 and fn_align != 0 and18942 if (abi_align != 0 and fn_align != 0 and
18944 abi_align != fn_align)18943 abi_align != fn_align)
18945 {18944 {
...@@ -19483,12 +19482,10 @@ fn zirReify(...@@ -19483,12 +19482,10 @@ fn zirReify(
19483 const args_slice_val = args_val.castTag(.slice).?.data;19482 const args_slice_val = args_val.castTag(.slice).?.data;
19484 const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod));19483 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);19485 const param_types = try sema.arena.alloc(InternPool.Index, args_len);
19487 const comptime_params = try sema.arena.alloc(bool, args_len);
1948819486
19489 var noalias_bits: u32 = 0;19487 var noalias_bits: u32 = 0;
19490 var i: usize = 0;19488 for (param_types, 0..) |*param_type, i| {
19491 while (i < args_len) : (i += 1) {
19492 const arg = try args_slice_val.ptr.elemValue(mod, i);19489 const arg = try args_slice_val.ptr.elemValue(mod, i);
19493 const arg_val = arg.castTag(.aggregate).?.data;19490 const arg_val = arg.castTag(.aggregate).?.data;
19494 // TODO use reflection instead of magic numbers here19491 // TODO use reflection instead of magic numbers here
...@@ -19505,25 +19502,22 @@ fn zirReify(...@@ -19505,25 +19502,22 @@ fn zirReify(
1950519502
19506 const param_type_val = param_type_opt_val.optionalValue(mod) orelse19503 const param_type_val = param_type_opt_val.optionalValue(mod) orelse
19507 return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{});19504 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
19510 if (arg_is_noalias) {19507 if (arg_is_noalias) {
19511 if (!param_type.isPtrAtRuntime(mod)) {19508 if (!param_type.toType().isPtrAtRuntime(mod)) {
19512 return sema.fail(block, src, "non-pointer parameter declared noalias", .{});19509 return sema.fail(block, src, "non-pointer parameter declared noalias", .{});
19513 }19510 }
19514 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse19511 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse
19515 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));19512 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
19516 }19513 }
19517
19518 param_types[i] = param_type;
19519 comptime_params[i] = false;
19520 }19514 }
1952119515
19522 var fn_info = Type.Payload.Function.Data{19516 const ty = try mod.funcType(.{
19523 .param_types = param_types,19517 .param_types = param_types,
19524 .comptime_params = comptime_params.ptr,19518 .comptime_bits = 0,
19525 .noalias_bits = noalias_bits,19519 .noalias_bits = noalias_bits,
19526 .return_type = try return_type.toType().copy(sema.arena),19520 .return_type = return_type.toIntern(),
19527 .alignment = alignment,19521 .alignment = alignment,
19528 .cc = cc,19522 .cc = cc,
19529 .is_var_args = is_var_args,19523 .is_var_args = is_var_args,
...@@ -19533,9 +19527,7 @@ fn zirReify(...@@ -19533,9 +19527,7 @@ fn zirReify(
19533 .cc_is_generic = false,19527 .cc_is_generic = false,
19534 .section_is_generic = false,19528 .section_is_generic = false,
19535 .addrspace_is_generic = false,19529 .addrspace_is_generic = false,
19536 };19530 });
19537
19538 const ty = try Type.Tag.function.create(sema.arena, fn_info);
19539 return sema.addType(ty);19531 return sema.addType(ty);
19540 },19532 },
19541 .Frame => return sema.failWithUseOfAsync(block, src),19533 .Frame => return sema.failWithUseOfAsync(block, src),
...@@ -23435,7 +23427,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -23435,7 +23427,7 @@ fn explainWhyTypeIsComptimeInner(
23435 .Pointer => {23427 .Pointer => {
23436 const elem_ty = ty.elemType2(mod);23428 const elem_ty = ty.elemType2(mod);
23437 if (elem_ty.zigTypeTag(mod) == .Fn) {23429 if (elem_ty.zigTypeTag(mod) == .Fn) {
23438 const fn_info = elem_ty.fnInfo();23430 const fn_info = mod.typeToFunc(elem_ty).?;
23439 if (fn_info.is_generic) {23431 if (fn_info.is_generic) {
23440 try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{});23432 try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{});
23441 }23433 }
...@@ -23443,7 +23435,7 @@ fn explainWhyTypeIsComptimeInner(...@@ -23443,7 +23435,7 @@ fn explainWhyTypeIsComptimeInner(
23443 .Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}),23435 .Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}),
23444 else => {},23436 else => {},
23445 }23437 }
23446 if (fn_info.return_type.comptimeOnly(mod)) {23438 if (fn_info.return_type.toType().comptimeOnly(mod)) {
23447 try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{});23439 try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{});
23448 }23440 }
23449 return;23441 return;
...@@ -23543,10 +23535,10 @@ fn validateExternType(...@@ -23543,10 +23535,10 @@ fn validateExternType(
23543 const target = sema.mod.getTarget();23535 const target = sema.mod.getTarget();
23544 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.23536 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.
23545 // The goal is to experiment with more integrated CPU/GPU code.23537 // 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)) {
23547 return true;23539 return true;
23548 }23540 }
23549 return !Type.fnCallingConventionAllowsZigTypes(target, ty.fnCallingConvention());23541 return !target_util.fnCallConvAllowsZigTypes(target, ty.fnCallingConvention(mod));
23550 },23542 },
23551 .Enum => {23543 .Enum => {
23552 return sema.validateExternType(try ty.intTagType(mod), position);23544 return sema.validateExternType(try ty.intTagType(mod), position);
...@@ -23619,7 +23611,7 @@ fn explainWhyTypeIsNotExtern(...@@ -23619,7 +23611,7 @@ fn explainWhyTypeIsNotExtern(
23619 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});23611 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
23620 return;23612 return;
23621 }23613 }
23622 switch (ty.fnCallingConvention()) {23614 switch (ty.fnCallingConvention(mod)) {
23623 .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}),23615 .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}),
23624 .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}),23616 .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}),
23625 .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}),23617 .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}),
...@@ -24548,10 +24540,10 @@ fn fieldCallBind(...@@ -24548,10 +24540,10 @@ fn fieldCallBind(
24548 try sema.addReferencedBy(block, src, decl_idx);24540 try sema.addReferencedBy(block, src, decl_idx);
24549 const decl_val = try sema.analyzeDeclVal(block, src, decl_idx);24541 const decl_val = try sema.analyzeDeclVal(block, src, decl_idx);
24550 const decl_type = sema.typeOf(decl_val);24542 const decl_type = sema.typeOf(decl_val);
24551 if (decl_type.zigTypeTag(mod) == .Fn and24543 if (mod.typeToFunc(decl_type)) |func_type| f: {
24552 decl_type.fnParamLen() >= 1)24544 if (func_type.param_types.len == 0) break :f;
24553 {24545
24554 const first_param_type = decl_type.fnParamType(0);24546 const first_param_type = func_type.param_types[0].toType();
24555 // zig fmt: off24547 // zig fmt: off
24556 if (first_param_type.isGenericPoison() or (24548 if (first_param_type.isGenericPoison() or (
24557 first_param_type.zigTypeTag(mod) == .Pointer and24549 first_param_type.zigTypeTag(mod) == .Pointer and
...@@ -27090,8 +27082,9 @@ fn coerceInMemoryAllowedFns(...@@ -27090,8 +27082,9 @@ fn coerceInMemoryAllowedFns(
27090 dest_src: LazySrcLoc,27082 dest_src: LazySrcLoc,
27091 src_src: LazySrcLoc,27083 src_src: LazySrcLoc,
27092) !InMemoryCoercionResult {27084) !InMemoryCoercionResult {
27093 const dest_info = dest_ty.fnInfo();27085 const mod = sema.mod;
27094 const src_info = src_ty.fnInfo();27086 const dest_info = mod.typeToFunc(dest_ty).?;
27087 const src_info = mod.typeToFunc(src_ty).?;
2709527088
27096 if (dest_info.is_var_args != src_info.is_var_args) {27089 if (dest_info.is_var_args != src_info.is_var_args) {
27097 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };27090 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
...@@ -27108,13 +27101,13 @@ fn coerceInMemoryAllowedFns(...@@ -27108,13 +27101,13 @@ fn coerceInMemoryAllowedFns(
27108 } };27101 } };
27109 }27102 }
2711027103
27111 if (!src_info.return_type.isNoReturn()) {27104 if (src_info.return_type != .noreturn_type) {
27112 const rt = try sema.coerceInMemoryAllowed(block, dest_info.return_type, src_info.return_type, false, target, dest_src, src_src);27105 const rt = try sema.coerceInMemoryAllowed(block, dest_info.return_type.toType(), src_info.return_type.toType(), false, target, dest_src, src_src);
27113 if (rt != .ok) {27106 if (rt != .ok) {
27114 return InMemoryCoercionResult{ .fn_return_type = .{27107 return InMemoryCoercionResult{ .fn_return_type = .{
27115 .child = try rt.dupe(sema.arena),27108 .child = try rt.dupe(sema.arena),
27116 .actual = src_info.return_type,27109 .actual = src_info.return_type.toType(),
27117 .wanted = dest_info.return_type,27110 .wanted = dest_info.return_type.toType(),
27118 } };27111 } };
27119 }27112 }
27120 }27113 }
...@@ -27134,22 +27127,23 @@ fn coerceInMemoryAllowedFns(...@@ -27134,22 +27127,23 @@ fn coerceInMemoryAllowedFns(
27134 }27127 }
2713527128
27136 for (dest_info.param_types, 0..) |dest_param_ty, i| {27129 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)) {
27140 return InMemoryCoercionResult{ .fn_param_comptime = .{27134 return InMemoryCoercionResult{ .fn_param_comptime = .{
27141 .index = i,27135 .index = i,
27142 .wanted = dest_info.comptime_params[i],27136 .wanted = dest_info.paramIsComptime(i_small),
27143 } };27137 } };
27144 }27138 }
2714527139
27146 // Note: Cast direction is reversed here.27140 // 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);
27148 if (param != .ok) {27142 if (param != .ok) {
27149 return InMemoryCoercionResult{ .fn_param = .{27143 return InMemoryCoercionResult{ .fn_param = .{
27150 .child = try param.dupe(sema.arena),27144 .child = try param.dupe(sema.arena),
27151 .actual = src_param_ty,27145 .actual = src_param_ty,
27152 .wanted = dest_param_ty,27146 .wanted = dest_param_ty.toType(),
27153 .index = i,27147 .index = i,
27154 } };27148 } };
27155 }27149 }
...@@ -31205,17 +31199,17 @@ fn resolvePeerTypes(...@@ -31205,17 +31199,17 @@ fn resolvePeerTypes(
31205 return chosen_ty;31199 return chosen_ty;
31206}31200}
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 {
31209 const mod = sema.mod;31203 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)) {
31213 // Ensure the type exists so that backends can assume that.31207 // Ensure the type exists so that backends can assume that.
31214 _ = try sema.getBuiltinType("StackTrace");31208 _ = try sema.getBuiltinType("StackTrace");
31215 }31209 }
3121631210
31217 for (fn_info.param_types) |param_ty| {31211 for (fn_info.param_types) |param_ty| {
31218 try sema.resolveTypeFully(param_ty);31212 try sema.resolveTypeFully(param_ty.toType());
31219 }31213 }
31220}31214}
3122131215
...@@ -31286,16 +31280,16 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -31286,16 +31280,16 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
31286 return sema.resolveTypeLayout(payload_ty);31280 return sema.resolveTypeLayout(payload_ty);
31287 },31281 },
31288 .Fn => {31282 .Fn => {
31289 const info = ty.fnInfo();31283 const info = mod.typeToFunc(ty).?;
31290 if (info.is_generic) {31284 if (info.is_generic) {
31291 // Resolving of generic function types is deferred to when31285 // Resolving of generic function types is deferred to when
31292 // the function is instantiated.31286 // the function is instantiated.
31293 return;31287 return;
31294 }31288 }
31295 for (info.param_types) |param_ty| {31289 for (info.param_types) |param_ty| {
31296 try sema.resolveTypeLayout(param_ty);31290 try sema.resolveTypeLayout(param_ty.toType());
31297 }31291 }
31298 try sema.resolveTypeLayout(info.return_type);31292 try sema.resolveTypeLayout(info.return_type.toType());
31299 },31293 },
31300 else => {},31294 else => {},
31301 }31295 }
...@@ -31615,15 +31609,13 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31615,15 +31609,13 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31615 .error_set_merged,31609 .error_set_merged,
31616 => false,31610 => false,
3161731611
31618 .function => true,
31619
31620 .inferred_alloc_mut => unreachable,31612 .inferred_alloc_mut => unreachable,
31621 .inferred_alloc_const => unreachable,31613 .inferred_alloc_const => unreachable,
3162231614
31623 .pointer => {31615 .pointer => {
31624 const child_ty = ty.childType(mod);31616 const child_ty = ty.childType(mod);
31625 if (child_ty.zigTypeTag(mod) == .Fn) {31617 if (child_ty.zigTypeTag(mod) == .Fn) {
31626 return child_ty.fnInfo().is_generic;31618 return mod.typeToFunc(child_ty).?.is_generic;
31627 } else {31619 } else {
31628 return sema.resolveTypeRequiresComptime(child_ty);31620 return sema.resolveTypeRequiresComptime(child_ty);
31629 }31621 }
...@@ -31644,7 +31636,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31644,7 +31636,7 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31644 .ptr_type => |ptr_type| {31636 .ptr_type => |ptr_type| {
31645 const child_ty = ptr_type.elem_type.toType();31637 const child_ty = ptr_type.elem_type.toType();
31646 if (child_ty.zigTypeTag(mod) == .Fn) {31638 if (child_ty.zigTypeTag(mod) == .Fn) {
31647 return child_ty.fnInfo().is_generic;31639 return mod.typeToFunc(child_ty).?.is_generic;
31648 } else {31640 } else {
31649 return sema.resolveTypeRequiresComptime(child_ty);31641 return sema.resolveTypeRequiresComptime(child_ty);
31650 }31642 }
...@@ -31653,6 +31645,8 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -31653,6 +31645,8 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31653 .vector_type => |vector_type| return sema.resolveTypeRequiresComptime(vector_type.child.toType()),31645 .vector_type => |vector_type| return sema.resolveTypeRequiresComptime(vector_type.child.toType()),
31654 .opt_type => |child| return sema.resolveTypeRequiresComptime(child.toType()),31646 .opt_type => |child| return sema.resolveTypeRequiresComptime(child.toType()),
31655 .error_union_type => |error_union_type| return sema.resolveTypeRequiresComptime(error_union_type.payload_type.toType()),31647 .error_union_type => |error_union_type| return sema.resolveTypeRequiresComptime(error_union_type.payload_type.toType()),
31648 .func_type => true,
31649
31656 .simple_type => |t| switch (t) {31650 .simple_type => |t| switch (t) {
31657 .f16,31651 .f16,
31658 .f32,31652 .f32,
...@@ -31799,16 +31793,16 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {...@@ -31799,16 +31793,16 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
31799 },31793 },
31800 .ErrorUnion => return sema.resolveTypeFully(ty.errorUnionPayload()),31794 .ErrorUnion => return sema.resolveTypeFully(ty.errorUnionPayload()),
31801 .Fn => {31795 .Fn => {
31802 const info = ty.fnInfo();31796 const info = mod.typeToFunc(ty).?;
31803 if (info.is_generic) {31797 if (info.is_generic) {
31804 // Resolving of generic function types is deferred to when31798 // Resolving of generic function types is deferred to when
31805 // the function is instantiated.31799 // the function is instantiated.
31806 return;31800 return;
31807 }31801 }
31808 for (info.param_types) |param_ty| {31802 for (info.param_types) |param_ty| {
31809 try sema.resolveTypeFully(param_ty);31803 try sema.resolveTypeFully(param_ty.toType());
31810 }31804 }
31811 try sema.resolveTypeFully(info.return_type);31805 try sema.resolveTypeFully(info.return_type.toType());
31812 },31806 },
31813 else => {},31807 else => {},
31814 }31808 }
...@@ -31881,7 +31875,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {...@@ -31881,7 +31875,6 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
31881 .none => return ty,31875 .none => return ty,
3188231876
31883 .u1_type,31877 .u1_type,
31884 .u5_type,
31885 .u8_type,31878 .u8_type,
31886 .i8_type,31879 .i8_type,
31887 .u16_type,31880 .u16_type,
...@@ -31941,8 +31934,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {...@@ -31941,8 +31934,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
31941 .zero_u8 => unreachable,31934 .zero_u8 => unreachable,
31942 .one => unreachable,31935 .one => unreachable,
31943 .one_usize => unreachable,31936 .one_usize => unreachable,
31944 .one_u5 => unreachable,31937 .one_u8 => unreachable,
31945 .four_u5 => unreachable,31938 .four_u8 => unreachable,
31946 .negative_one => unreachable,31939 .negative_one => unreachable,
31947 .calling_convention_c => unreachable,31940 .calling_convention_c => unreachable,
31948 .calling_convention_inline => unreachable,31941 .calling_convention_inline => unreachable,
...@@ -32083,14 +32076,14 @@ fn resolveInferredErrorSet(...@@ -32083,14 +32076,14 @@ fn resolveInferredErrorSet(
32083 // `*Module.Fn`. Not only is the function not relevant to the inferred error set32076 // `*Module.Fn`. Not only is the function not relevant to the inferred error set
32084 // in this case, it may be a generic function which would cause an assertion failure32077 // in this case, it may be a generic function which would cause an assertion failure
32085 // if we called `ensureFuncBodyAnalyzed` on it here.32078 // if we called `ensureFuncBodyAnalyzed` on it here.
32086 const ies_func_owner_decl = sema.mod.declPtr(ies.func.owner_decl);32079 const ies_func_owner_decl = mod.declPtr(ies.func.owner_decl);
32087 const ies_func_info = ies_func_owner_decl.ty.fnInfo();32080 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;
32088 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,32081 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
32089 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,32082 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,
32090 // so here we can simply skip this case.32083 // 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) {
32092 assert(ies_func_info.cc == .Inline);32085 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) {
32094 if (ies_func_info.is_generic) {32087 if (ies_func_info.is_generic) {
32095 const msg = msg: {32088 const msg = msg: {
32096 const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{});32089 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...@@ -32285,7 +32278,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3228532278
32286 const prev_field_index = struct_obj.fields.getIndex(field_name).?;32279 const prev_field_index = struct_obj.fields.getIndex(field_name).?;
32287 const prev_field_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{ .index = prev_field_index });32280 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", .{});
32289 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});32282 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});
32290 break :msg msg;32283 break :msg msg;
32291 };32284 };
...@@ -32387,7 +32380,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -32387,7 +32380,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
32387 .index = field_i,32380 .index = field_i,
32388 .range = .type,32381 .range = .type,
32389 });32382 });
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)});
32391 errdefer msg.destroy(sema.gpa);32384 errdefer msg.destroy(sema.gpa);
3239232385
32393 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field.ty, .struct_field);32386 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field.ty, .struct_field);
...@@ -32402,7 +32395,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -32402,7 +32395,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
32402 .index = field_i,32395 .index = field_i,
32403 .range = .type,32396 .range = .type,
32404 });32397 });
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)});
32406 errdefer msg.destroy(sema.gpa);32399 errdefer msg.destroy(sema.gpa);
3240732400
32408 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field.ty);32401 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field.ty);
...@@ -32580,7 +32573,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32580,7 +32573,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32580 // The provided type is an integer type and we must construct the enum tag type here.32573 // The provided type is an integer type and we must construct the enum tag type here.
32581 int_tag_ty = provided_ty;32574 int_tag_ty = provided_ty;
32582 if (int_tag_ty.zigTypeTag(mod) != .Int and int_tag_ty.zigTypeTag(mod) != .ComptimeInt) {32575 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)});
32584 }32577 }
3258532578
32586 if (fields_len > 0) {32579 if (fields_len > 0) {
...@@ -32590,7 +32583,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32590,7 +32583,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32590 const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{});32583 const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{});
32591 errdefer msg.destroy(sema.gpa);32584 errdefer msg.destroy(sema.gpa);
32592 try sema.errNote(&block_scope, tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{32585 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),
32594 fields_len - 1,32587 fields_len - 1,
32595 });32588 });
32596 break :msg msg;32589 break :msg msg;
...@@ -32605,7 +32598,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32605,7 +32598,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32605 union_obj.tag_ty = provided_ty;32598 union_obj.tag_ty = provided_ty;
32606 const enum_type = switch (mod.intern_pool.indexToKey(union_obj.tag_ty.ip_index)) {32599 const enum_type = switch (mod.intern_pool.indexToKey(union_obj.tag_ty.ip_index)) {
32607 .enum_type => |x| x,32600 .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)}),
32609 };32602 };
32610 // The fields of the union must match the enum exactly.32603 // The fields of the union must match the enum exactly.
32611 // A flag per field is used to check for missing and extraneous fields.32604 // 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 {...@@ -32705,7 +32698,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32705 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;32698 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;
32706 const other_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = gop.index }).lazy;32699 const other_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = gop.index }).lazy;
32707 const msg = msg: {32700 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)});
32709 errdefer msg.destroy(gpa);32702 errdefer msg.destroy(gpa);
32710 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});32703 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});
32711 break :msg msg;32704 break :msg msg;
...@@ -32751,7 +32744,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32751,7 +32744,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3275132744
32752 const prev_field_index = union_obj.fields.getIndex(field_name).?;32745 const prev_field_index = union_obj.fields.getIndex(field_name).?;
32753 const prev_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = prev_field_index }).lazy;32746 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", .{});
32755 try sema.errNote(&block_scope, src, msg, "union declared here", .{});32748 try sema.errNote(&block_scope, src, msg, "union declared here", .{});
32756 break :msg msg;32749 break :msg msg;
32757 };32750 };
...@@ -32766,7 +32759,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32766,7 +32759,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32766 .range = .type,32759 .range = .type,
32767 }).lazy;32760 }).lazy;
32768 const msg = try sema.errMsg(&block_scope, ty_src, "no field named '{s}' in enum '{}'", .{32761 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),
32770 });32763 });
32771 errdefer msg.destroy(sema.gpa);32764 errdefer msg.destroy(sema.gpa);
32772 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);32765 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
...@@ -32800,7 +32793,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32800,7 +32793,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32800 .index = field_i,32793 .index = field_i,
32801 .range = .type,32794 .range = .type,
32802 });32795 });
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)});
32804 errdefer msg.destroy(sema.gpa);32797 errdefer msg.destroy(sema.gpa);
3280532798
32806 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field);32799 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field);
...@@ -32815,7 +32808,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -32815,7 +32808,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
32815 .index = field_i,32808 .index = field_i,
32816 .range = .type,32809 .range = .type,
32817 });32810 });
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)});
32819 errdefer msg.destroy(sema.gpa);32812 errdefer msg.destroy(sema.gpa);
3282032813
32821 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);32814 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
...@@ -33060,7 +33053,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33060,7 +33053,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33060 .error_set,33053 .error_set,
33061 .error_set_merged,33054 .error_set_merged,
33062 .error_union,33055 .error_union,
33063 .function,
33064 .error_set_inferred,33056 .error_set_inferred,
33065 .anyframe_T,33057 .anyframe_T,
33066 .pointer,33058 .pointer,
...@@ -33087,7 +33079,12 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33087,7 +33079,12 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33087 return null;33079 return null;
33088 }33080 }
33089 },33081 },
33090 .ptr_type => null,33082
33083 .ptr_type,
33084 .error_union_type,
33085 .func_type,
33086 => null,
33087
33091 .array_type => |array_type| {33088 .array_type => |array_type| {
33092 if (array_type.len == 0)33089 if (array_type.len == 0)
33093 return Value.initTag(.empty_array);33090 return Value.initTag(.empty_array);
...@@ -33102,13 +33099,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -33102,13 +33099,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
33102 return null;33099 return null;
33103 },33100 },
33104 .opt_type => |child| {33101 .opt_type => |child| {
33105 if (child.toType().isNoReturn()) {33102 if (child == .noreturn_type) {
33106 return Value.null;33103 return try mod.nullValue(ty);
33107 } else {33104 } else {
33108 return null;33105 return null;
33109 }33106 }
33110 },33107 },
33111 .error_union_type => null,33108
33112 .simple_type => |t| switch (t) {33109 .simple_type => |t| switch (t) {
33113 .f16,33110 .f16,
33114 .f32,33111 .f32,
...@@ -33674,15 +33671,13 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33674,15 +33671,13 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33674 .error_set_merged,33671 .error_set_merged,
33675 => false,33672 => false,
3367633673
33677 .function => true,
33678
33679 .inferred_alloc_mut => unreachable,33674 .inferred_alloc_mut => unreachable,
33680 .inferred_alloc_const => unreachable,33675 .inferred_alloc_const => unreachable,
3368133676
33682 .pointer => {33677 .pointer => {
33683 const child_ty = ty.childType(mod);33678 const child_ty = ty.childType(mod);
33684 if (child_ty.zigTypeTag(mod) == .Fn) {33679 if (child_ty.zigTypeTag(mod) == .Fn) {
33685 return child_ty.fnInfo().is_generic;33680 return mod.typeToFunc(child_ty).?.is_generic;
33686 } else {33681 } else {
33687 return sema.typeRequiresComptime(child_ty);33682 return sema.typeRequiresComptime(child_ty);
33688 }33683 }
...@@ -33703,7 +33698,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33703,7 +33698,7 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33703 .ptr_type => |ptr_type| {33698 .ptr_type => |ptr_type| {
33704 const child_ty = ptr_type.elem_type.toType();33699 const child_ty = ptr_type.elem_type.toType();
33705 if (child_ty.zigTypeTag(mod) == .Fn) {33700 if (child_ty.zigTypeTag(mod) == .Fn) {
33706 return child_ty.fnInfo().is_generic;33701 return mod.typeToFunc(child_ty).?.is_generic;
33707 } else {33702 } else {
33708 return sema.typeRequiresComptime(child_ty);33703 return sema.typeRequiresComptime(child_ty);
33709 }33704 }
...@@ -33714,6 +33709,8 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {...@@ -33714,6 +33709,8 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33714 .error_union_type => |error_union_type| {33709 .error_union_type => |error_union_type| {
33715 return sema.typeRequiresComptime(error_union_type.payload_type.toType());33710 return sema.typeRequiresComptime(error_union_type.payload_type.toType());
33716 },33711 },
33712 .func_type => true,
33713
33717 .simple_type => |t| return switch (t) {33714 .simple_type => |t| return switch (t) {
33718 .f16,33715 .f16,
33719 .f32,33716 .f32,
...@@ -33870,7 +33867,8 @@ fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 {...@@ -33870,7 +33867,8 @@ fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 {
3387033867
33871/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.33868/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
33872pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {33869pub 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).?;
33874 if (fn_info.is_generic) return false;33872 if (fn_info.is_generic) return false;
33875 if (fn_info.is_var_args) return true;33873 if (fn_info.is_var_args) return true;
33876 switch (fn_info.cc) {33874 switch (fn_info.cc) {
...@@ -33878,7 +33876,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {...@@ -33878,7 +33876,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
33878 .Inline => return false,33876 .Inline => return false,
33879 else => {},33877 else => {},
33880 }33878 }
33881 if (try sema.typeRequiresComptime(fn_info.return_type)) {33879 if (try sema.typeRequiresComptime(fn_info.return_type.toType())) {
33882 return false;33880 return false;
33883 }33881 }
33884 return true;33882 return true;
src/Zir.zig+2-3
...@@ -2052,7 +2052,6 @@ pub const Inst = struct {...@@ -2052,7 +2052,6 @@ pub const Inst = struct {
2052 /// and `[]Ref`.2052 /// and `[]Ref`.
2053 pub const Ref = enum(u32) {2053 pub const Ref = enum(u32) {
2054 u1_type = @enumToInt(InternPool.Index.u1_type),2054 u1_type = @enumToInt(InternPool.Index.u1_type),
2055 u5_type = @enumToInt(InternPool.Index.u5_type),
2056 u8_type = @enumToInt(InternPool.Index.u8_type),2055 u8_type = @enumToInt(InternPool.Index.u8_type),
2057 i8_type = @enumToInt(InternPool.Index.i8_type),2056 i8_type = @enumToInt(InternPool.Index.i8_type),
2058 u16_type = @enumToInt(InternPool.Index.u16_type),2057 u16_type = @enumToInt(InternPool.Index.u16_type),
...@@ -2121,8 +2120,8 @@ pub const Inst = struct {...@@ -2121,8 +2120,8 @@ pub const Inst = struct {
2121 zero_u8 = @enumToInt(InternPool.Index.zero_u8),2120 zero_u8 = @enumToInt(InternPool.Index.zero_u8),
2122 one = @enumToInt(InternPool.Index.one),2121 one = @enumToInt(InternPool.Index.one),
2123 one_usize = @enumToInt(InternPool.Index.one_usize),2122 one_usize = @enumToInt(InternPool.Index.one_usize),
2124 one_u5 = @enumToInt(InternPool.Index.one_u5),2123 one_u8 = @enumToInt(InternPool.Index.one_u8),
2125 four_u5 = @enumToInt(InternPool.Index.four_u5),2124 four_u8 = @enumToInt(InternPool.Index.four_u8),
2126 negative_one = @enumToInt(InternPool.Index.negative_one),2125 negative_one = @enumToInt(InternPool.Index.negative_one),
2127 calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c),2126 calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c),
2128 calling_convention_inline = @enumToInt(InternPool.Index.calling_convention_inline),2127 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 {...@@ -472,7 +472,7 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
472472
473fn gen(self: *Self) !void {473fn gen(self: *Self) !void {
474 const mod = self.bin_file.options.module.?;474 const mod = self.bin_file.options.module.?;
475 const cc = self.fn_type.fnCallingConvention();475 const cc = self.fn_type.fnCallingConvention(mod);
476 if (cc != .Naked) {476 if (cc != .Naked) {
477 // stp fp, lr, [sp, #-16]!477 // stp fp, lr, [sp, #-16]!
478 _ = try self.addInst(.{478 _ = try self.addInst(.{
...@@ -1146,7 +1146,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1146,7 +1146,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1146 .stack_offset => blk: {1146 .stack_offset => blk: {
1147 // self.ret_mcv is an address to where this function1147 // self.ret_mcv is an address to where this function
1148 // should store its result into1148 // should store its result into
1149 const ret_ty = self.fn_type.fnReturnType();1149 const ret_ty = self.fn_type.fnReturnType(mod);
1150 const ptr_ty = try mod.singleMutPtrType(ret_ty);1150 const ptr_ty = try mod.singleMutPtrType(ret_ty);
11511151
1152 // addr_reg will contain the address of where to store the1152 // 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...@@ -4271,7 +4271,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42714271
4272 if (info.return_value == .stack_offset) {4272 if (info.return_value == .stack_offset) {
4273 log.debug("airCall: return by reference", .{});4273 log.debug("airCall: return by reference", .{});
4274 const ret_ty = fn_ty.fnReturnType();4274 const ret_ty = fn_ty.fnReturnType(mod);
4275 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));4275 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));
4276 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));4276 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));
4277 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);4277 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...@@ -4428,10 +4428,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4428}4428}
44294429
4430fn airRet(self: *Self, inst: Air.Inst.Index) !void {4430fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4431 const mod = self.bin_file.options.module.?;
4431 const un_op = self.air.instructions.items(.data)[inst].un_op;4432 const un_op = self.air.instructions.items(.data)[inst].un_op;
4432 const operand = try self.resolveInst(un_op);4433 const operand = try self.resolveInst(un_op);
4433 const ret_ty = self.fn_type.fnReturnType();4434 const ret_ty = self.fn_type.fnReturnType(mod);
4434 const mod = self.bin_file.options.module.?;
44354435
4436 switch (self.ret_mcv) {4436 switch (self.ret_mcv) {
4437 .none => {},4437 .none => {},
...@@ -4460,10 +4460,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -4460,10 +4460,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4460}4460}
44614461
4462fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {4462fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4463 const mod = self.bin_file.options.module.?;
4463 const un_op = self.air.instructions.items(.data)[inst].un_op;4464 const un_op = self.air.instructions.items(.data)[inst].un_op;
4464 const ptr = try self.resolveInst(un_op);4465 const ptr = try self.resolveInst(un_op);
4465 const ptr_ty = self.typeOf(un_op);4466 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
4468 switch (self.ret_mcv) {4469 switch (self.ret_mcv) {
4469 .none => {},4470 .none => {},
...@@ -4483,7 +4484,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4483,7 +4484,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4483 // location.4484 // location.
4484 const op_inst = Air.refToIndex(un_op).?;4485 const op_inst = Air.refToIndex(un_op).?;
4485 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {4486 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {
4486 const mod = self.bin_file.options.module.?;
4487 const abi_size = @intCast(u32, ret_ty.abiSize(mod));4487 const abi_size = @intCast(u32, ret_ty.abiSize(mod));
4488 const abi_align = ret_ty.abiAlignment(mod);4488 const abi_align = ret_ty.abiAlignment(mod);
44894489
...@@ -6226,12 +6226,11 @@ const CallMCValues = struct {...@@ -6226,12 +6226,11 @@ const CallMCValues = struct {
62266226
6227/// Caller must call `CallMCValues.deinit`.6227/// Caller must call `CallMCValues.deinit`.
6228fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {6228fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6229 const cc = fn_ty.fnCallingConvention();6229 const mod = self.bin_file.options.module.?;
6230 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());6230 const fn_info = mod.typeToFunc(fn_ty).?;
6231 defer self.gpa.free(param_types);6231 const cc = fn_info.cc;
6232 fn_ty.fnParamTypes(param_types);
6233 var result: CallMCValues = .{6232 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),
6235 // These undefined values must be populated before returning from this function.6234 // These undefined values must be populated before returning from this function.
6236 .return_value = undefined,6235 .return_value = undefined,
6237 .stack_byte_count = undefined,6236 .stack_byte_count = undefined,
...@@ -6239,8 +6238,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6239,8 +6238,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6239 };6238 };
6240 errdefer self.gpa.free(result.args);6239 errdefer self.gpa.free(result.args);
62416240
6242 const ret_ty = fn_ty.fnReturnType();6241 const ret_ty = fn_ty.fnReturnType(mod);
6243 const mod = self.bin_file.options.module.?;
62446242
6245 switch (cc) {6243 switch (cc) {
6246 .Naked => {6244 .Naked => {
...@@ -6271,8 +6269,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6271,8 +6269,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6271 }6269 }
6272 }6270 }
62736271
6274 for (param_types, 0..) |ty, i| {6272 for (fn_info.param_types, 0..) |ty, i| {
6275 const param_size = @intCast(u32, ty.abiSize(mod));6273 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6276 if (param_size == 0) {6274 if (param_size == 0) {
6277 result.args[i] = .{ .none = {} };6275 result.args[i] = .{ .none = {} };
6278 continue;6276 continue;
...@@ -6280,14 +6278,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6280,14 +6278,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62806278
6281 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned6279 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned
6282 // values to spread across odd-numbered registers.6280 // 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()) {
6284 // Round up NCRN to the next even number6282 // Round up NCRN to the next even number
6285 ncrn += ncrn % 2;6283 ncrn += ncrn % 2;
6286 }6284 }
62876285
6288 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {6286 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
6289 if (param_size <= 8) {6287 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()) };
6291 ncrn += 1;6289 ncrn += 1;
6292 } else {6290 } else {
6293 return self.fail("TODO MCValues with multiple registers", .{});6291 return self.fail("TODO MCValues with multiple registers", .{});
...@@ -6298,7 +6296,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6298,7 +6296,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6298 ncrn = 8;6296 ncrn = 8;
6299 // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided6297 // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided
6300 // that the entire stack space consumed by the arguments is 8-byte aligned.6298 // 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) {
6302 if (nsaa % 8 != 0) {6300 if (nsaa % 8 != 0) {
6303 nsaa += 8 - (nsaa % 8);6301 nsaa += 8 - (nsaa % 8);
6304 }6302 }
...@@ -6336,10 +6334,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6336,10 +6334,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
63366334
6337 var stack_offset: u32 = 0;6335 var stack_offset: u32 = 0;
63386336
6339 for (param_types, 0..) |ty, i| {6337 for (fn_info.param_types, 0..) |ty, i| {
6340 if (ty.abiSize(mod) > 0) {6338 if (ty.toType().abiSize(mod) > 0) {
6341 const param_size = @intCast(u32, ty.abiSize(mod));6339 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6342 const param_alignment = ty.abiAlignment(mod);6340 const param_alignment = ty.toType().abiAlignment(mod);
63436341
6344 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);6342 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
6345 result.args[i] = .{ .stack_argument_offset = stack_offset };6343 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 {...@@ -478,7 +478,7 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
478478
479fn gen(self: *Self) !void {479fn gen(self: *Self) !void {
480 const mod = self.bin_file.options.module.?;480 const mod = self.bin_file.options.module.?;
481 const cc = self.fn_type.fnCallingConvention();481 const cc = self.fn_type.fnCallingConvention(mod);
482 if (cc != .Naked) {482 if (cc != .Naked) {
483 // push {fp, lr}483 // push {fp, lr}
484 const push_reloc = try self.addNop();484 const push_reloc = try self.addNop();
...@@ -1123,7 +1123,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1123,7 +1123,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1123 .stack_offset => blk: {1123 .stack_offset => blk: {
1124 // self.ret_mcv is an address to where this function1124 // self.ret_mcv is an address to where this function
1125 // should store its result into1125 // should store its result into
1126 const ret_ty = self.fn_type.fnReturnType();1126 const ret_ty = self.fn_type.fnReturnType(mod);
1127 const ptr_ty = try mod.singleMutPtrType(ret_ty);1127 const ptr_ty = try mod.singleMutPtrType(ret_ty);
11281128
1129 // addr_reg will contain the address of where to store the1129 // 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...@@ -4250,7 +4250,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4250 // untouched by the parameter passing code4250 // untouched by the parameter passing code
4251 const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: {4251 const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: {
4252 log.debug("airCall: return by reference", .{});4252 log.debug("airCall: return by reference", .{});
4253 const ret_ty = fn_ty.fnReturnType();4253 const ret_ty = fn_ty.fnReturnType(mod);
4254 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));4254 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));
4255 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));4255 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));
4256 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);4256 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...@@ -4350,7 +4350,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4350 if (RegisterManager.indexOfRegIntoTracked(reg) == null) {4350 if (RegisterManager.indexOfRegIntoTracked(reg) == null) {
4351 // Save function return value into a tracked register4351 // Save function return value into a tracked register
4352 log.debug("airCall: copying {} as it is not tracked", .{reg});4352 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);
4354 break :result MCValue{ .register = new_reg };4354 break :result MCValue{ .register = new_reg };
4355 }4355 }
4356 },4356 },
...@@ -4374,10 +4374,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4374,10 +4374,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4374}4374}
43754375
4376fn airRet(self: *Self, inst: Air.Inst.Index) !void {4376fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4377 const mod = self.bin_file.options.module.?;
4377 const un_op = self.air.instructions.items(.data)[inst].un_op;4378 const un_op = self.air.instructions.items(.data)[inst].un_op;
4378 const operand = try self.resolveInst(un_op);4379 const operand = try self.resolveInst(un_op);
4379 const ret_ty = self.fn_type.fnReturnType();4380 const ret_ty = self.fn_type.fnReturnType(mod);
4380 const mod = self.bin_file.options.module.?;
43814381
4382 switch (self.ret_mcv) {4382 switch (self.ret_mcv) {
4383 .none => {},4383 .none => {},
...@@ -4406,10 +4406,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -4406,10 +4406,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4406}4406}
44074407
4408fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {4408fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4409 const mod = self.bin_file.options.module.?;
4409 const un_op = self.air.instructions.items(.data)[inst].un_op;4410 const un_op = self.air.instructions.items(.data)[inst].un_op;
4410 const ptr = try self.resolveInst(un_op);4411 const ptr = try self.resolveInst(un_op);
4411 const ptr_ty = self.typeOf(un_op);4412 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
4414 switch (self.ret_mcv) {4415 switch (self.ret_mcv) {
4415 .none => {},4416 .none => {},
...@@ -4429,7 +4430,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4429,7 +4430,6 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4429 // location.4430 // location.
4430 const op_inst = Air.refToIndex(un_op).?;4431 const op_inst = Air.refToIndex(un_op).?;
4431 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {4432 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {
4432 const mod = self.bin_file.options.module.?;
4433 const abi_size = @intCast(u32, ret_ty.abiSize(mod));4433 const abi_size = @intCast(u32, ret_ty.abiSize(mod));
4434 const abi_align = ret_ty.abiAlignment(mod);4434 const abi_align = ret_ty.abiAlignment(mod);
44354435
...@@ -6171,12 +6171,11 @@ const CallMCValues = struct {...@@ -6171,12 +6171,11 @@ const CallMCValues = struct {
61716171
6172/// Caller must call `CallMCValues.deinit`.6172/// Caller must call `CallMCValues.deinit`.
6173fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {6173fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6174 const cc = fn_ty.fnCallingConvention();6174 const mod = self.bin_file.options.module.?;
6175 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());6175 const fn_info = mod.typeToFunc(fn_ty).?;
6176 defer self.gpa.free(param_types);6176 const cc = fn_info.cc;
6177 fn_ty.fnParamTypes(param_types);
6178 var result: CallMCValues = .{6177 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),
6180 // These undefined values must be populated before returning from this function.6179 // These undefined values must be populated before returning from this function.
6181 .return_value = undefined,6180 .return_value = undefined,
6182 .stack_byte_count = undefined,6181 .stack_byte_count = undefined,
...@@ -6184,8 +6183,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6184,8 +6183,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6184 };6183 };
6185 errdefer self.gpa.free(result.args);6184 errdefer self.gpa.free(result.args);
61866185
6187 const ret_ty = fn_ty.fnReturnType();6186 const ret_ty = fn_ty.fnReturnType(mod);
6188 const mod = self.bin_file.options.module.?;
61896187
6190 switch (cc) {6188 switch (cc) {
6191 .Naked => {6189 .Naked => {
...@@ -6219,11 +6217,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6219,11 +6217,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6219 }6217 }
6220 }6218 }
62216219
6222 for (param_types, 0..) |ty, i| {6220 for (fn_info.param_types, 0..) |ty, i| {
6223 if (ty.abiAlignment(mod) == 8)6221 if (ty.toType().abiAlignment(mod) == 8)
6224 ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2);6222 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));
6227 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {6225 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
6228 if (param_size <= 4) {6226 if (param_size <= 4) {
6229 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };6227 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };
...@@ -6235,7 +6233,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6235,7 +6233,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6235 return self.fail("TODO MCValues split between registers and stack", .{});6233 return self.fail("TODO MCValues split between registers and stack", .{});
6236 } else {6234 } else {
6237 ncrn = 4;6235 ncrn = 4;
6238 if (ty.abiAlignment(mod) == 8)6236 if (ty.toType().abiAlignment(mod) == 8)
6239 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);6237 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
62406238
6241 result.args[i] = .{ .stack_argument_offset = nsaa };6239 result.args[i] = .{ .stack_argument_offset = nsaa };
...@@ -6269,10 +6267,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6269,10 +6267,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62696267
6270 var stack_offset: u32 = 0;6268 var stack_offset: u32 = 0;
62716269
6272 for (param_types, 0..) |ty, i| {6270 for (fn_info.param_types, 0..) |ty, i| {
6273 if (ty.abiSize(mod) > 0) {6271 if (ty.toType().abiSize(mod) > 0) {
6274 const param_size = @intCast(u32, ty.abiSize(mod));6272 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6275 const param_alignment = ty.abiAlignment(mod);6273 const param_alignment = ty.toType().abiAlignment(mod);
62766274
6277 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);6275 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
6278 result.args[i] = .{ .stack_argument_offset = stack_offset };6276 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 {...@@ -347,7 +347,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
347}347}
348348
349fn gen(self: *Self) !void {349fn 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);
351 if (cc != .Naked) {352 if (cc != .Naked) {
352 // TODO Finish function prologue and epilogue for riscv64.353 // 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...@@ -1803,7 +1804,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
1803}1804}
18041805
1805fn ret(self: *Self, mcv: MCValue) !void {1806fn 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);
1807 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);1809 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
1808 // Just add space for an instruction, patch this later1810 // Just add space for an instruction, patch this later
1809 const index = try self.addInst(.{1811 const index = try self.addInst(.{
...@@ -2621,12 +2623,11 @@ const CallMCValues = struct {...@@ -2621,12 +2623,11 @@ const CallMCValues = struct {
26212623
2622/// Caller must call `CallMCValues.deinit`.2624/// Caller must call `CallMCValues.deinit`.
2623fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {2625fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2624 const cc = fn_ty.fnCallingConvention();2626 const mod = self.bin_file.options.module.?;
2625 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());2627 const fn_info = mod.typeToFunc(fn_ty).?;
2626 defer self.gpa.free(param_types);2628 const cc = fn_info.cc;
2627 fn_ty.fnParamTypes(param_types);
2628 var result: CallMCValues = .{2629 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),
2630 // These undefined values must be populated before returning from this function.2631 // These undefined values must be populated before returning from this function.
2631 .return_value = undefined,2632 .return_value = undefined,
2632 .stack_byte_count = undefined,2633 .stack_byte_count = undefined,
...@@ -2634,8 +2635,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -2634,8 +2635,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2634 };2635 };
2635 errdefer self.gpa.free(result.args);2636 errdefer self.gpa.free(result.args);
26362637
2637 const ret_ty = fn_ty.fnReturnType();2638 const ret_ty = fn_ty.fnReturnType(mod);
2638 const mod = self.bin_file.options.module.?;
26392639
2640 switch (cc) {2640 switch (cc) {
2641 .Naked => {2641 .Naked => {
...@@ -2655,8 +2655,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -2655,8 +2655,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2655 var next_stack_offset: u32 = 0;2655 var next_stack_offset: u32 = 0;
2656 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };2656 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
26572657
2658 for (param_types, 0..) |ty, i| {2658 for (fn_info.param_types, 0..) |ty, i| {
2659 const param_size = @intCast(u32, ty.abiSize(mod));2659 const param_size = @intCast(u32, ty.toType().abiSize(mod));
2660 if (param_size <= 8) {2660 if (param_size <= 8) {
2661 if (next_register < argument_registers.len) {2661 if (next_register < argument_registers.len) {
2662 result.args[i] = .{ .register = argument_registers[next_register] };2662 result.args[i] = .{ .register = argument_registers[next_register] };
src/arch/sparc64/CodeGen.zig+11-11
...@@ -363,7 +363,8 @@ pub fn generate(...@@ -363,7 +363,8 @@ pub fn generate(
363}363}
364364
365fn gen(self: *Self) !void {365fn 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);
367 if (cc != .Naked) {368 if (cc != .Naked) {
368 // TODO Finish function prologue and epilogue for sparc64.369 // TODO Finish function prologue and epilogue for sparc64.
369370
...@@ -4458,12 +4459,11 @@ fn realStackOffset(off: u32) u32 {...@@ -4458,12 +4459,11 @@ fn realStackOffset(off: u32) u32 {
44584459
4459/// Caller must call `CallMCValues.deinit`.4460/// Caller must call `CallMCValues.deinit`.
4460fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {4461fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
4461 const cc = fn_ty.fnCallingConvention();4462 const mod = self.bin_file.options.module.?;
4462 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());4463 const fn_info = mod.typeToFunc(fn_ty).?;
4463 defer self.gpa.free(param_types);4464 const cc = fn_info.cc;
4464 fn_ty.fnParamTypes(param_types);
4465 var result: CallMCValues = .{4465 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),
4467 // These undefined values must be populated before returning from this function.4467 // These undefined values must be populated before returning from this function.
4468 .return_value = undefined,4468 .return_value = undefined,
4469 .stack_byte_count = undefined,4469 .stack_byte_count = undefined,
...@@ -4471,8 +4471,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4471,8 +4471,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4471 };4471 };
4472 errdefer self.gpa.free(result.args);4472 errdefer self.gpa.free(result.args);
44734473
4474 const ret_ty = fn_ty.fnReturnType();4474 const ret_ty = fn_ty.fnReturnType(mod);
4475 const mod = self.bin_file.options.module.?;
44764475
4477 switch (cc) {4476 switch (cc) {
4478 .Naked => {4477 .Naked => {
...@@ -4495,8 +4494,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)...@@ -4495,8 +4494,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
4495 .callee => abi.c_abi_int_param_regs_callee_view,4494 .callee => abi.c_abi_int_param_regs_callee_view,
4496 };4495 };
44974496
4498 for (param_types, 0..) |ty, i| {4497 for (fn_info.param_types, 0..) |ty, i| {
4499 const param_size = @intCast(u32, ty.abiSize(mod));4498 const param_size = @intCast(u32, ty.toType().abiSize(mod));
4500 if (param_size <= 8) {4499 if (param_size <= 8) {
4501 if (next_register < argument_registers.len) {4500 if (next_register < argument_registers.len) {
4502 result.args[i] = .{ .register = argument_registers[next_register] };4501 result.args[i] = .{ .register = argument_registers[next_register] };
...@@ -4580,7 +4579,8 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {...@@ -4580,7 +4579,8 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
4580}4579}
45814580
4582fn ret(self: *Self, mcv: MCValue) !void {4581fn 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);
4584 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);4584 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
45854585
4586 // Just add space for a branch instruction, patch this later4586 // 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 {...@@ -1145,7 +1145,7 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
1145fn genFunctype(1145fn genFunctype(
1146 gpa: Allocator,1146 gpa: Allocator,
1147 cc: std.builtin.CallingConvention,1147 cc: std.builtin.CallingConvention,
1148 params: []const Type,1148 params: []const InternPool.Index,
1149 return_type: Type,1149 return_type: Type,
1150 mod: *Module,1150 mod: *Module,
1151) !wasm.Type {1151) !wasm.Type {
...@@ -1170,7 +1170,8 @@ fn genFunctype(...@@ -1170,7 +1170,8 @@ fn genFunctype(
1170 }1170 }
11711171
1172 // param types1172 // param types
1173 for (params) |param_type| {1173 for (params) |param_type_ip| {
1174 const param_type = param_type_ip.toType();
1174 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;1175 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;
11751176
1176 switch (cc) {1177 switch (cc) {
...@@ -1234,9 +1235,9 @@ pub fn generate(...@@ -1234,9 +1235,9 @@ pub fn generate(
1234}1235}
12351236
1236fn genFunc(func: *CodeGen) InnerError!void {1237fn genFunc(func: *CodeGen) InnerError!void {
1237 const fn_info = func.decl.ty.fnInfo();
1238 const mod = func.bin_file.base.options.module.?;1238 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);
1240 defer func_type.deinit(func.gpa);1241 defer func_type.deinit(func.gpa);
1241 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);1242 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);
12421243
...@@ -1345,10 +1346,8 @@ const CallWValues = struct {...@@ -1345,10 +1346,8 @@ const CallWValues = struct {
13451346
1346fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {1347fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
1347 const mod = func.bin_file.base.options.module.?;1348 const mod = func.bin_file.base.options.module.?;
1348 const cc = fn_ty.fnCallingConvention();1349 const fn_info = mod.typeToFunc(fn_ty).?;
1349 const param_types = try func.gpa.alloc(Type, fn_ty.fnParamLen());1350 const cc = fn_info.cc;
1350 defer func.gpa.free(param_types);
1351 fn_ty.fnParamTypes(param_types);
1352 var result: CallWValues = .{1351 var result: CallWValues = .{
1353 .args = &.{},1352 .args = &.{},
1354 .return_value = .none,1353 .return_value = .none,
...@@ -1360,8 +1359,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1360,8 +1359,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13601359
1361 // Check if we store the result as a pointer to the stack rather than1360 // Check if we store the result as a pointer to the stack rather than
1362 // by value1361 // by value
1363 const fn_info = fn_ty.fnInfo();1362 if (firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
1364 if (firstParamSRet(fn_info.cc, fn_info.return_type, mod)) {
1365 // the sret arg will be passed as first argument, therefore we1363 // the sret arg will be passed as first argument, therefore we
1366 // set the `return_value` before allocating locals for regular args.1364 // set the `return_value` before allocating locals for regular args.
1367 result.return_value = .{ .local = .{ .value = func.local_index, .references = 1 } };1365 result.return_value = .{ .local = .{ .value = func.local_index, .references = 1 } };
...@@ -1370,8 +1368,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1370,8 +1368,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13701368
1371 switch (cc) {1369 switch (cc) {
1372 .Unspecified => {1370 .Unspecified => {
1373 for (param_types) |ty| {1371 for (fn_info.param_types) |ty| {
1374 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {1372 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
1375 continue;1373 continue;
1376 }1374 }
13771375
...@@ -1380,8 +1378,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV...@@ -1380,8 +1378,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
1380 }1378 }
1381 },1379 },
1382 .C => {1380 .C => {
1383 for (param_types) |ty| {1381 for (fn_info.param_types) |ty| {
1384 const ty_classes = abi.classifyType(ty, mod);1382 const ty_classes = abi.classifyType(ty.toType(), mod);
1385 for (ty_classes) |class| {1383 for (ty_classes) |class| {
1386 if (class == .none) continue;1384 if (class == .none) continue;
1387 try args.append(.{ .local = .{ .value = func.local_index, .references = 1 } });1385 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 {...@@ -2095,11 +2093,11 @@ fn genBody(func: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2095}2093}
20962094
2097fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {2095fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2096 const mod = func.bin_file.base.options.module.?;
2098 const un_op = func.air.instructions.items(.data)[inst].un_op;2097 const un_op = func.air.instructions.items(.data)[inst].un_op;
2099 const operand = try func.resolveInst(un_op);2098 const operand = try func.resolveInst(un_op);
2100 const fn_info = func.decl.ty.fnInfo();2099 const fn_info = mod.typeToFunc(func.decl.ty).?;
2101 const ret_ty = fn_info.return_type;2100 const ret_ty = fn_info.return_type.toType();
2102 const mod = func.bin_file.base.options.module.?;
21032101
2104 // result must be stored in the stack and we return a pointer2102 // result must be stored in the stack and we return a pointer
2105 // to the stack instead2103 // to the stack instead
...@@ -2146,8 +2144,8 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2146,8 +2144,8 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2146 break :result try func.allocStack(Type.usize); // create pointer to void2144 break :result try func.allocStack(Type.usize); // create pointer to void
2147 }2145 }
21482146
2149 const fn_info = func.decl.ty.fnInfo();2147 const fn_info = mod.typeToFunc(func.decl.ty).?;
2150 if (firstParamSRet(fn_info.cc, fn_info.return_type, mod)) {2148 if (firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
2151 break :result func.return_value;2149 break :result func.return_value;
2152 }2150 }
21532151
...@@ -2163,12 +2161,12 @@ fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2163,12 +2161,12 @@ fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2163 const operand = try func.resolveInst(un_op);2161 const operand = try func.resolveInst(un_op);
2164 const ret_ty = func.typeOf(un_op).childType(mod);2162 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).?;
2167 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {2165 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2168 if (ret_ty.isError(mod)) {2166 if (ret_ty.isError(mod)) {
2169 try func.addImm32(0);2167 try func.addImm32(0);
2170 }2168 }
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)) {
2172 // leave on the stack2170 // leave on the stack
2173 _ = try func.load(operand, ret_ty, 0);2171 _ = try func.load(operand, ret_ty, 0);
2174 }2172 }
...@@ -2191,9 +2189,9 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2191,9 +2189,9 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2191 .Pointer => ty.childType(mod),2189 .Pointer => ty.childType(mod),
2192 else => unreachable,2190 else => unreachable,
2193 };2191 };
2194 const ret_ty = fn_ty.fnReturnType();2192 const ret_ty = fn_ty.fnReturnType(mod);
2195 const fn_info = fn_ty.fnInfo();2193 const fn_info = mod.typeToFunc(fn_ty).?;
2196 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, mod);2194 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod);
21972195
2198 const callee: ?Decl.Index = blk: {2196 const callee: ?Decl.Index = blk: {
2199 const func_val = (try func.air.value(pl_op.operand, mod)) orelse break :blk null;2197 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...@@ -2203,8 +2201,8 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2203 break :blk function.data.owner_decl;2201 break :blk function.data.owner_decl;
2204 } else if (func_val.castTag(.extern_fn)) |extern_fn| {2202 } else if (func_val.castTag(.extern_fn)) |extern_fn| {
2205 const ext_decl = mod.declPtr(extern_fn.data.owner_decl);2203 const ext_decl = mod.declPtr(extern_fn.data.owner_decl);
2206 const ext_info = ext_decl.ty.fnInfo();2204 const ext_info = mod.typeToFunc(ext_decl.ty).?;
2207 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type, mod);2205 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);
2208 defer func_type.deinit(func.gpa);2206 defer func_type.deinit(func.gpa);
2209 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_fn.data.owner_decl);2207 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_fn.data.owner_decl);
2210 const atom = func.bin_file.getAtomPtr(atom_index);2208 const atom = func.bin_file.getAtomPtr(atom_index);
...@@ -2235,7 +2233,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2235,7 +2233,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2235 const arg_ty = func.typeOf(arg);2233 const arg_ty = func.typeOf(arg);
2236 if (!arg_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;2234 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);
2239 }2237 }
22402238
2241 if (callee) |direct| {2239 if (callee) |direct| {
...@@ -2248,7 +2246,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif...@@ -2248,7 +2246,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2248 const operand = try func.resolveInst(pl_op.operand);2246 const operand = try func.resolveInst(pl_op.operand);
2249 try func.emitWValue(operand);2247 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);
2252 defer fn_type.deinit(func.gpa);2250 defer fn_type.deinit(func.gpa);
22532251
2254 const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);2252 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...@@ -2264,7 +2262,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
2264 } else if (first_param_sret) {2262 } else if (first_param_sret) {
2265 break :result_value sret;2263 break :result_value sret;
2266 // TODO: Make this less fragile and optimize2264 // 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) {
2268 const result_local = try func.allocLocal(ret_ty);2266 const result_local = try func.allocLocal(ret_ty);
2269 try func.addLabel(.local_set, result_local.local.value);2267 try func.addLabel(.local_set, result_local.local.value);
2270 const scalar_type = abi.scalarType(ret_ty, mod);2268 const scalar_type = abi.scalarType(ret_ty, mod);
...@@ -2528,7 +2526,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -2528,7 +2526,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2528 const mod = func.bin_file.base.options.module.?;2526 const mod = func.bin_file.base.options.module.?;
2529 const arg_index = func.arg_index;2527 const arg_index = func.arg_index;
2530 const arg = func.args[arg_index];2528 const arg = func.args[arg_index];
2531 const cc = func.decl.ty.fnInfo().cc;2529 const cc = mod.typeToFunc(func.decl.ty).?.cc;
2532 const arg_ty = func.typeOfIndex(inst);2530 const arg_ty = func.typeOfIndex(inst);
2533 if (cc == .C) {2531 if (cc == .C) {
2534 const arg_classes = abi.classifyType(arg_ty, mod);2532 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...@@ -2647,9 +2645,9 @@ fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) Inner
2647 }2645 }
26482646
2649 switch (op) {2647 switch (op) {
2650 .mul => return func.callIntrinsic("__multi3", &.{ ty, ty }, ty, &.{ lhs, rhs }),2648 .mul => return func.callIntrinsic("__multi3", &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }),
2651 .shr => return func.callIntrinsic("__lshrti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }),2649 .shr => return func.callIntrinsic("__lshrti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }),
2652 .shl => return func.callIntrinsic("__ashlti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }),2650 .shl => return func.callIntrinsic("__ashlti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }),
2653 .xor => {2651 .xor => {
2654 const result = try func.allocStack(ty);2652 const result = try func.allocStack(ty);
2655 try func.emitWValue(result);2653 try func.emitWValue(result);
...@@ -2839,7 +2837,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In...@@ -2839,7 +2837,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In
2839 };2837 };
28402838
2841 // fma requires three operands2839 // 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 };
2843 const param_types = param_types_buffer[0..args.len];2841 const param_types = param_types_buffer[0..args.len];
2844 return func.callIntrinsic(fn_name, param_types, ty, args);2842 return func.callIntrinsic(fn_name, param_types, ty, args);
2845}2843}
...@@ -5298,7 +5296,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!...@@ -5298,7 +5296,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
5298 // call __extendhfsf2(f16) f325296 // call __extendhfsf2(f16) f32
5299 const f32_result = try func.callIntrinsic(5297 const f32_result = try func.callIntrinsic(
5300 "__extendhfsf2",5298 "__extendhfsf2",
5301 &.{Type.f16},5299 &.{.f16_type},
5302 Type.f32,5300 Type.f32,
5303 &.{operand},5301 &.{operand},
5304 );5302 );
...@@ -5316,7 +5314,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!...@@ -5316,7 +5314,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
5316 target_util.compilerRtFloatAbbrev(wanted_bits),5314 target_util.compilerRtFloatAbbrev(wanted_bits),
5317 }) catch unreachable;5315 }) catch unreachable;
53185316
5319 return func.callIntrinsic(fn_name, &.{given}, wanted, &.{operand});5317 return func.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand});
5320}5318}
53215319
5322fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5320fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5347,7 +5345,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro...@@ -5347,7 +5345,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
5347 } else operand;5345 } else operand;
53485346
5349 // call __truncsfhf2(f32) f165347 // call __truncsfhf2(f32) f16
5350 return func.callIntrinsic("__truncsfhf2", &.{Type.f32}, Type.f16, &.{op});5348 return func.callIntrinsic("__truncsfhf2", &.{.f32_type}, Type.f16, &.{op});
5351 }5349 }
53525350
5353 var fn_name_buf: [12]u8 = undefined;5351 var fn_name_buf: [12]u8 = undefined;
...@@ -5356,7 +5354,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro...@@ -5356,7 +5354,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
5356 target_util.compilerRtFloatAbbrev(wanted_bits),5354 target_util.compilerRtFloatAbbrev(wanted_bits),
5357 }) catch unreachable;5355 }) catch unreachable;
53585356
5359 return func.callIntrinsic(fn_name, &.{given}, wanted, &.{operand});5357 return func.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand});
5360}5358}
53615359
5362fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {5360fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
...@@ -5842,7 +5840,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5842,7 +5840,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58425840
5843 const bin_op = try func.callIntrinsic(5841 const bin_op = try func.callIntrinsic(
5844 "__multi3",5842 "__multi3",
5845 &[_]Type{Type.i64} ** 4,5843 &[_]InternPool.Index{.i64_type} ** 4,
5846 Type.i128,5844 Type.i128,
5847 &.{ lhs, lhs_shifted, rhs, rhs_shifted },5845 &.{ lhs, lhs_shifted, rhs, rhs_shifted },
5848 );5846 );
...@@ -5866,19 +5864,19 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5866,19 +5864,19 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58665864
5867 const mul1 = try func.callIntrinsic(5865 const mul1 = try func.callIntrinsic(
5868 "__multi3",5866 "__multi3",
5869 &[_]Type{Type.i64} ** 4,5867 &[_]InternPool.Index{.i64_type} ** 4,
5870 Type.i128,5868 Type.i128,
5871 &.{ lhs_lsb, zero, rhs_msb, zero },5869 &.{ lhs_lsb, zero, rhs_msb, zero },
5872 );5870 );
5873 const mul2 = try func.callIntrinsic(5871 const mul2 = try func.callIntrinsic(
5874 "__multi3",5872 "__multi3",
5875 &[_]Type{Type.i64} ** 4,5873 &[_]InternPool.Index{.i64_type} ** 4,
5876 Type.i128,5874 Type.i128,
5877 &.{ rhs_lsb, zero, lhs_msb, zero },5875 &.{ rhs_lsb, zero, lhs_msb, zero },
5878 );5876 );
5879 const mul3 = try func.callIntrinsic(5877 const mul3 = try func.callIntrinsic(
5880 "__multi3",5878 "__multi3",
5881 &[_]Type{Type.i64} ** 4,5879 &[_]InternPool.Index{.i64_type} ** 4,
5882 Type.i128,5880 Type.i128,
5883 &.{ lhs_msb, zero, rhs_msb, zero },5881 &.{ lhs_msb, zero, rhs_msb, zero },
5884 );5882 );
...@@ -5977,7 +5975,7 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5977,7 +5975,7 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5977 // call to compiler-rt `fn fmaf(f32, f32, f32) f32`5975 // call to compiler-rt `fn fmaf(f32, f32, f32) f32`
5978 var result = try func.callIntrinsic(5976 var result = try func.callIntrinsic(
5979 "fmaf",5977 "fmaf",
5980 &.{ Type.f32, Type.f32, Type.f32 },5978 &.{ .f32_type, .f32_type, .f32_type },
5981 Type.f32,5979 Type.f32,
5982 &.{ rhs_ext, lhs_ext, addend_ext },5980 &.{ rhs_ext, lhs_ext, addend_ext },
5983 );5981 );
...@@ -6707,7 +6705,7 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6707,7 +6705,7 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6707fn callIntrinsic(6705fn callIntrinsic(
6708 func: *CodeGen,6706 func: *CodeGen,
6709 name: []const u8,6707 name: []const u8,
6710 param_types: []const Type,6708 param_types: []const InternPool.Index,
6711 return_type: Type,6709 return_type: Type,
6712 args: []const WValue,6710 args: []const WValue,
6713) InnerError!WValue {6711) InnerError!WValue {
...@@ -6735,8 +6733,8 @@ fn callIntrinsic(...@@ -6735,8 +6733,8 @@ fn callIntrinsic(
6735 // Lower all arguments to the stack before we call our function6733 // Lower all arguments to the stack before we call our function
6736 for (args, 0..) |arg, arg_i| {6734 for (args, 0..) |arg, arg_i| {
6737 assert(!(want_sret_param and arg == .stack));6735 assert(!(want_sret_param and arg == .stack));
6738 assert(param_types[arg_i].hasRuntimeBitsIgnoreComptime(mod));6736 assert(param_types[arg_i].toType().hasRuntimeBitsIgnoreComptime(mod));
6739 try func.lowerArg(.C, param_types[arg_i], arg);6737 try func.lowerArg(.C, param_types[arg_i].toType(), arg);
6740 }6738 }
67416739
6742 // Actually call our intrinsic6740 // Actually call our intrinsic
...@@ -6938,7 +6936,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {...@@ -6938,7 +6936,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
6938 try writer.writeByte(std.wasm.opcode(.end));6936 try writer.writeByte(std.wasm.opcode(.end));
69396937
6940 const slice_ty = Type.const_slice_u8_sentinel_0;6938 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);
6942 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);6940 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);
6943}6941}
69446942
src/arch/x86_64/CodeGen.zig+22-12
...@@ -26,6 +26,7 @@ const Liveness = @import("../../Liveness.zig");...@@ -26,6 +26,7 @@ const Liveness = @import("../../Liveness.zig");
26const Lower = @import("Lower.zig");26const Lower = @import("Lower.zig");
27const Mir = @import("Mir.zig");27const Mir = @import("Mir.zig");
28const Module = @import("../../Module.zig");28const Module = @import("../../Module.zig");
29const InternPool = @import("../../InternPool.zig");
29const Target = std.Target;30const Target = std.Target;
30const Type = @import("../../type.zig").Type;31const Type = @import("../../type.zig").Type;
31const TypedValue = @import("../../TypedValue.zig");32const TypedValue = @import("../../TypedValue.zig");
...@@ -697,7 +698,8 @@ pub fn generate(...@@ -697,7 +698,8 @@ pub fn generate(
697 FrameAlloc.init(.{ .size = 0, .alignment = 1 }),698 FrameAlloc.init(.{ .size = 0, .alignment = 1 }),
698 );699 );
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) {
701 error.CodegenFail => return Result{ .fail = function.err_msg.? },703 error.CodegenFail => return Result{ .fail = function.err_msg.? },
702 error.OutOfRegisters => return Result{704 error.OutOfRegisters => return Result{
703 .fail = try ErrorMsg.create(705 .fail = try ErrorMsg.create(
...@@ -1566,7 +1568,7 @@ fn asmMemoryRegisterImmediate(...@@ -1566,7 +1568,7 @@ fn asmMemoryRegisterImmediate(
15661568
1567fn gen(self: *Self) InnerError!void {1569fn gen(self: *Self) InnerError!void {
1568 const mod = self.bin_file.options.module.?;1570 const mod = self.bin_file.options.module.?;
1569 const cc = self.fn_type.fnCallingConvention();1571 const cc = self.fn_type.fnCallingConvention(mod);
1570 if (cc != .Naked) {1572 if (cc != .Naked) {
1571 try self.asmRegister(.{ ._, .push }, .rbp);1573 try self.asmRegister(.{ ._, .push }, .rbp);
1572 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();1574 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...@@ -8042,7 +8044,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8042 else => unreachable,8044 else => unreachable,
8043 };8045 };
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);
8046 defer info.deinit(self);8050 defer info.deinit(self);
80478051
8048 // We need a properly aligned and sized call frame to be able to call this function.8052 // 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...@@ -8083,7 +8087,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8083 const ret_lock = switch (info.return_value.long) {8087 const ret_lock = switch (info.return_value.long) {
8084 .none, .unreach => null,8088 .none, .unreach => null,
8085 .indirect => |reg_off| lock: {8089 .indirect => |reg_off| lock: {
8086 const ret_ty = fn_ty.fnReturnType();8090 const ret_ty = fn_info.return_type.toType();
8087 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));8091 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));
8088 try self.genSetReg(reg_off.reg, Type.usize, .{8092 try self.genSetReg(reg_off.reg, Type.usize, .{
8089 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },8093 .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...@@ -8199,9 +8203,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8199}8203}
82008204
8201fn airRet(self: *Self, inst: Air.Inst.Index) !void {8205fn airRet(self: *Self, inst: Air.Inst.Index) !void {
8206 const mod = self.bin_file.options.module.?;
8202 const un_op = self.air.instructions.items(.data)[inst].un_op;8207 const un_op = self.air.instructions.items(.data)[inst].un_op;
8203 const operand = try self.resolveInst(un_op);8208 const operand = try self.resolveInst(un_op);
8204 const ret_ty = self.fn_type.fnReturnType();8209 const ret_ty = self.fn_type.fnReturnType(mod);
8205 switch (self.ret_mcv.short) {8210 switch (self.ret_mcv.short) {
8206 .none => {},8211 .none => {},
8207 .register => try self.genCopy(ret_ty, self.ret_mcv.short, operand),8212 .register => try self.genCopy(ret_ty, self.ret_mcv.short, operand),
...@@ -11683,18 +11688,23 @@ const CallMCValues = struct {...@@ -11683,18 +11688,23 @@ const CallMCValues = struct {
11683/// Caller must call `CallMCValues.deinit`.11688/// Caller must call `CallMCValues.deinit`.
11684fn resolveCallingConventionValues(11689fn resolveCallingConventionValues(
11685 self: *Self,11690 self: *Self,
11686 fn_ty: Type,11691 fn_info: InternPool.Key.FuncType,
11687 var_args: []const Air.Inst.Ref,11692 var_args: []const Air.Inst.Ref,
11688 stack_frame_base: FrameIndex,11693 stack_frame_base: FrameIndex,
11689) !CallMCValues {11694) !CallMCValues {
11690 const mod = self.bin_file.options.module.?;11695 const mod = self.bin_file.options.module.?;
11691 const cc = fn_ty.fnCallingConvention();11696 const cc = fn_info.cc;
11692 const param_len = fn_ty.fnParamLen();11697 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
11693 const param_types = try self.gpa.alloc(Type, param_len + var_args.len);
11694 defer self.gpa.free(param_types);11698 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 }
11696 // TODO: promote var arg types11703 // 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
11698 var result: CallMCValues = .{11708 var result: CallMCValues = .{
11699 .args = try self.gpa.alloc(MCValue, param_types.len),11709 .args = try self.gpa.alloc(MCValue, param_types.len),
11700 // These undefined values must be populated before returning from this function.11710 // These undefined values must be populated before returning from this function.
...@@ -11704,7 +11714,7 @@ fn resolveCallingConventionValues(...@@ -11704,7 +11714,7 @@ fn resolveCallingConventionValues(
11704 };11714 };
11705 errdefer self.gpa.free(result.args);11715 errdefer self.gpa.free(result.args);
1170611716
11707 const ret_ty = fn_ty.fnReturnType();11717 const ret_ty = fn_info.return_type.toType();
1170811718
11709 switch (cc) {11719 switch (cc) {
11710 .Naked => {11720 .Naked => {
src/codegen.zig+1-1
...@@ -1081,7 +1081,7 @@ fn genDeclRef(...@@ -1081,7 +1081,7 @@ fn genDeclRef(
10811081
1082 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?1082 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
1083 if (tv.ty.castPtrToFn(mod)) |fn_ty| {1083 if (tv.ty.castPtrToFn(mod)) |fn_ty| {
1084 if (fn_ty.fnInfo().is_generic) {1084 if (mod.typeToFunc(fn_ty).?.is_generic) {
1085 return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod) });1085 return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod) });
1086 }1086 }
1087 } else if (tv.ty.zigTypeTag(mod) == .Pointer) {1087 } else if (tv.ty.zigTypeTag(mod) == .Pointer) {
src/codegen/c.zig+7-6
...@@ -1507,7 +1507,7 @@ pub const DeclGen = struct {...@@ -1507,7 +1507,7 @@ pub const DeclGen = struct {
1507 const fn_decl = mod.declPtr(fn_decl_index);1507 const fn_decl = mod.declPtr(fn_decl_index);
1508 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);1508 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).?;
1511 if (fn_info.cc == .Naked) {1511 if (fn_info.cc == .Naked) {
1512 switch (kind) {1512 switch (kind) {
1513 .forward => try w.writeAll("zig_naked_decl "),1513 .forward => try w.writeAll("zig_naked_decl "),
...@@ -1517,7 +1517,7 @@ pub const DeclGen = struct {...@@ -1517,7 +1517,7 @@ pub const DeclGen = struct {
1517 }1517 }
1518 if (fn_decl.val.castTag(.function)) |func_payload|1518 if (fn_decl.val.castTag(.function)) |func_payload|
1519 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");1519 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
1522 const trailing = try renderTypePrefix(1522 const trailing = try renderTypePrefix(
1523 dg.decl_index,1523 dg.decl_index,
...@@ -3455,7 +3455,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {...@@ -3455,7 +3455,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
3455 } else {3455 } else {
3456 try reap(f, inst, &.{un_op});3456 try reap(f, inst, &.{un_op});
3457 // Not even allowed to return void in a naked function.3457 // 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)
3459 try writer.writeAll("return;\n");3459 try writer.writeAll("return;\n");
3460 }3460 }
3461 return .none;3461 return .none;
...@@ -4094,7 +4094,7 @@ fn airCall(...@@ -4094,7 +4094,7 @@ fn airCall(
4094) !CValue {4094) !CValue {
4095 const mod = f.object.dg.module;4095 const mod = f.object.dg.module;
4096 // Not even allowed to call panic in a naked function.4096 // 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
4099 const gpa = f.object.dg.gpa;4099 const gpa = f.object.dg.gpa;
4100 const writer = f.object.writer();4100 const writer = f.object.writer();
...@@ -4143,7 +4143,7 @@ fn airCall(...@@ -4143,7 +4143,7 @@ fn airCall(
4143 else => unreachable,4143 else => unreachable,
4144 };4144 };
41454145
4146 const ret_ty = fn_ty.fnReturnType();4146 const ret_ty = fn_ty.fnReturnType(mod);
4147 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);4147 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
41484148
4149 const result_local = result: {4149 const result_local = result: {
...@@ -4622,8 +4622,9 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4622,8 +4622,9 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {
4622}4622}
46234623
4624fn airUnreach(f: *Function) !CValue {4624fn airUnreach(f: *Function) !CValue {
4625 const mod = f.object.dg.module;
4625 // Not even allowed to call unreachable in a naked function.4626 // 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
4628 try f.object.writer().writeAll("zig_unreachable();\n");4629 try f.object.writer().writeAll("zig_unreachable();\n");
4629 return .none;4630 return .none;
src/codegen/c/type.zig+17-17
...@@ -1720,7 +1720,7 @@ pub const CType = extern union {...@@ -1720,7 +1720,7 @@ pub const CType = extern union {
1720 .Opaque => self.init(.void),1720 .Opaque => self.init(.void),
17211721
1722 .Fn => {1722 .Fn => {
1723 const info = ty.fnInfo();1723 const info = mod.typeToFunc(ty).?;
1724 if (!info.is_generic) {1724 if (!info.is_generic) {
1725 if (lookup.isMutable()) {1725 if (lookup.isMutable()) {
1726 const param_kind: Kind = switch (kind) {1726 const param_kind: Kind = switch (kind) {
...@@ -1728,10 +1728,10 @@ pub const CType = extern union {...@@ -1728,10 +1728,10 @@ pub const CType = extern union {
1728 .complete, .parameter, .global => .parameter,1728 .complete, .parameter, .global => .parameter,
1729 .payload => unreachable,1729 .payload => unreachable,
1730 };1730 };
1731 _ = try lookup.typeToIndex(info.return_type, param_kind);1731 _ = try lookup.typeToIndex(info.return_type.toType(), param_kind);
1732 for (info.param_types) |param_type| {1732 for (info.param_types) |param_type| {
1733 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;1733 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
1734 _ = try lookup.typeToIndex(param_type, param_kind);1734 _ = try lookup.typeToIndex(param_type.toType(), param_kind);
1735 }1735 }
1736 }1736 }
1737 self.init(if (info.is_var_args) .varargs_function else .function);1737 self.init(if (info.is_var_args) .varargs_function else .function);
...@@ -2013,7 +2013,7 @@ pub const CType = extern union {...@@ -2013,7 +2013,7 @@ pub const CType = extern union {
2013 .function,2013 .function,
2014 .varargs_function,2014 .varargs_function,
2015 => {2015 => {
2016 const info = ty.fnInfo();2016 const info = mod.typeToFunc(ty).?;
2017 assert(!info.is_generic);2017 assert(!info.is_generic);
2018 const param_kind: Kind = switch (kind) {2018 const param_kind: Kind = switch (kind) {
2019 .forward, .forward_parameter => .forward_parameter,2019 .forward, .forward_parameter => .forward_parameter,
...@@ -2023,21 +2023,21 @@ pub const CType = extern union {...@@ -2023,21 +2023,21 @@ pub const CType = extern union {
20232023
2024 var c_params_len: usize = 0;2024 var c_params_len: usize = 0;
2025 for (info.param_types) |param_type| {2025 for (info.param_types) |param_type| {
2026 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;2026 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2027 c_params_len += 1;2027 c_params_len += 1;
2028 }2028 }
20292029
2030 const params_pl = try arena.alloc(Index, c_params_len);2030 const params_pl = try arena.alloc(Index, c_params_len);
2031 var c_param_i: usize = 0;2031 var c_param_i: usize = 0;
2032 for (info.param_types) |param_type| {2032 for (info.param_types) |param_type| {
2033 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;2033 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2034 params_pl[c_param_i] = store.set.typeToIndex(param_type, mod, param_kind).?;2034 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
2035 c_param_i += 1;2035 c_param_i += 1;
2036 }2036 }
20372037
2038 const fn_pl = try arena.create(Payload.Function);2038 const fn_pl = try arena.create(Payload.Function);
2039 fn_pl.* = .{ .base = .{ .tag = t }, .data = .{2039 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).?,
2041 .param_types = params_pl,2041 .param_types = params_pl,
2042 } };2042 } };
2043 return initPayload(fn_pl);2043 return initPayload(fn_pl);
...@@ -2145,7 +2145,7 @@ pub const CType = extern union {...@@ -2145,7 +2145,7 @@ pub const CType = extern union {
2145 => {2145 => {
2146 if (ty.zigTypeTag(mod) != .Fn) return false;2146 if (ty.zigTypeTag(mod) != .Fn) return false;
21472147
2148 const info = ty.fnInfo();2148 const info = mod.typeToFunc(ty).?;
2149 assert(!info.is_generic);2149 assert(!info.is_generic);
2150 const data = cty.cast(Payload.Function).?.data;2150 const data = cty.cast(Payload.Function).?.data;
2151 const param_kind: Kind = switch (self.kind) {2151 const param_kind: Kind = switch (self.kind) {
...@@ -2154,18 +2154,18 @@ pub const CType = extern union {...@@ -2154,18 +2154,18 @@ pub const CType = extern union {
2154 .payload => unreachable,2154 .payload => unreachable,
2155 };2155 };
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))
2158 return false;2158 return false;
21592159
2160 var c_param_i: usize = 0;2160 var c_param_i: usize = 0;
2161 for (info.param_types) |param_type| {2161 for (info.param_types) |param_type| {
2162 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;2162 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
21632163
2164 if (c_param_i >= data.param_types.len) return false;2164 if (c_param_i >= data.param_types.len) return false;
2165 const param_cty = data.param_types[c_param_i];2165 const param_cty = data.param_types[c_param_i];
2166 c_param_i += 1;2166 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))
2169 return false;2169 return false;
2170 }2170 }
2171 return c_param_i == data.param_types.len;2171 return c_param_i == data.param_types.len;
...@@ -2258,7 +2258,7 @@ pub const CType = extern union {...@@ -2258,7 +2258,7 @@ pub const CType = extern union {
2258 .function,2258 .function,
2259 .varargs_function,2259 .varargs_function,
2260 => {2260 => {
2261 const info = ty.fnInfo();2261 const info = mod.typeToFunc(ty).?;
2262 assert(!info.is_generic);2262 assert(!info.is_generic);
2263 const param_kind: Kind = switch (self.kind) {2263 const param_kind: Kind = switch (self.kind) {
2264 .forward, .forward_parameter => .forward_parameter,2264 .forward, .forward_parameter => .forward_parameter,
...@@ -2266,10 +2266,10 @@ pub const CType = extern union {...@@ -2266,10 +2266,10 @@ pub const CType = extern union {
2266 .payload => unreachable,2266 .payload => unreachable,
2267 };2267 };
22682268
2269 self.updateHasherRecurse(hasher, info.return_type, param_kind);2269 self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);
2270 for (info.param_types) |param_type| {2270 for (info.param_types) |param_type| {
2271 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;2271 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2272 self.updateHasherRecurse(hasher, param_type, param_kind);2272 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
2273 }2273 }
2274 },2274 },
22752275
src/codegen/llvm.zig+117-118
...@@ -954,17 +954,17 @@ pub const Object = struct {...@@ -954,17 +954,17 @@ pub const Object = struct {
954 builder.positionBuilderAtEnd(entry_block);954 builder.positionBuilderAtEnd(entry_block);
955955
956 // This gets the LLVM values from the function and stores them in `dg.args`.956 // 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).?;
958 const sret = firstParamSRet(fn_info, mod);958 const sret = firstParamSRet(fn_info, mod);
959 const ret_ptr = if (sret) llvm_func.getParam(0) else null;959 const ret_ptr = if (sret) llvm_func.getParam(0) else null;
960 const gpa = dg.gpa;960 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) {
963 .signed => dg.addAttr(llvm_func, 0, "signext"),963 .signed => dg.addAttr(llvm_func, 0, "signext"),
964 .unsigned => dg.addAttr(llvm_func, 0, "zeroext"),964 .unsigned => dg.addAttr(llvm_func, 0, "zeroext"),
965 };965 };
966966
967 const err_return_tracing = fn_info.return_type.isError(mod) and967 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
968 mod.comp.bin_file.options.error_return_tracing;968 mod.comp.bin_file.options.error_return_tracing;
969969
970 const err_ret_trace = if (err_return_tracing)970 const err_ret_trace = if (err_return_tracing)
...@@ -986,7 +986,7 @@ pub const Object = struct {...@@ -986,7 +986,7 @@ pub const Object = struct {
986 .byval => {986 .byval => {
987 assert(!it.byval_attr);987 assert(!it.byval_attr);
988 const param_index = it.zig_index - 1;988 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();
990 const param = llvm_func.getParam(llvm_arg_i);990 const param = llvm_func.getParam(llvm_arg_i);
991 try args.ensureUnusedCapacity(1);991 try args.ensureUnusedCapacity(1);
992992
...@@ -1005,7 +1005,7 @@ pub const Object = struct {...@@ -1005,7 +1005,7 @@ pub const Object = struct {
1005 llvm_arg_i += 1;1005 llvm_arg_i += 1;
1006 },1006 },
1007 .byref => {1007 .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();
1009 const param_llvm_ty = try dg.lowerType(param_ty);1009 const param_llvm_ty = try dg.lowerType(param_ty);
1010 const param = llvm_func.getParam(llvm_arg_i);1010 const param = llvm_func.getParam(llvm_arg_i);
1011 const alignment = param_ty.abiAlignment(mod);1011 const alignment = param_ty.abiAlignment(mod);
...@@ -1024,7 +1024,7 @@ pub const Object = struct {...@@ -1024,7 +1024,7 @@ pub const Object = struct {
1024 }1024 }
1025 },1025 },
1026 .byref_mut => {1026 .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();
1028 const param_llvm_ty = try dg.lowerType(param_ty);1028 const param_llvm_ty = try dg.lowerType(param_ty);
1029 const param = llvm_func.getParam(llvm_arg_i);1029 const param = llvm_func.getParam(llvm_arg_i);
1030 const alignment = param_ty.abiAlignment(mod);1030 const alignment = param_ty.abiAlignment(mod);
...@@ -1044,7 +1044,7 @@ pub const Object = struct {...@@ -1044,7 +1044,7 @@ pub const Object = struct {
1044 },1044 },
1045 .abi_sized_int => {1045 .abi_sized_int => {
1046 assert(!it.byval_attr);1046 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();
1048 const param = llvm_func.getParam(llvm_arg_i);1048 const param = llvm_func.getParam(llvm_arg_i);
1049 llvm_arg_i += 1;1049 llvm_arg_i += 1;
10501050
...@@ -1071,7 +1071,7 @@ pub const Object = struct {...@@ -1071,7 +1071,7 @@ pub const Object = struct {
1071 },1071 },
1072 .slice => {1072 .slice => {
1073 assert(!it.byval_attr);1073 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();
1075 const ptr_info = param_ty.ptrInfo(mod);1075 const ptr_info = param_ty.ptrInfo(mod);
10761076
1077 if (math.cast(u5, it.zig_index - 1)) |i| {1077 if (math.cast(u5, it.zig_index - 1)) |i| {
...@@ -1104,7 +1104,7 @@ pub const Object = struct {...@@ -1104,7 +1104,7 @@ pub const Object = struct {
1104 .multiple_llvm_types => {1104 .multiple_llvm_types => {
1105 assert(!it.byval_attr);1105 assert(!it.byval_attr);
1106 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];1106 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();
1108 const param_llvm_ty = try dg.lowerType(param_ty);1108 const param_llvm_ty = try dg.lowerType(param_ty);
1109 const param_alignment = param_ty.abiAlignment(mod);1109 const param_alignment = param_ty.abiAlignment(mod);
1110 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);1110 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
...@@ -1135,7 +1135,7 @@ pub const Object = struct {...@@ -1135,7 +1135,7 @@ pub const Object = struct {
1135 args.appendAssumeCapacity(casted);1135 args.appendAssumeCapacity(casted);
1136 },1136 },
1137 .float_array => {1137 .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();
1139 const param_llvm_ty = try dg.lowerType(param_ty);1139 const param_llvm_ty = try dg.lowerType(param_ty);
1140 const param = llvm_func.getParam(llvm_arg_i);1140 const param = llvm_func.getParam(llvm_arg_i);
1141 llvm_arg_i += 1;1141 llvm_arg_i += 1;
...@@ -1153,7 +1153,7 @@ pub const Object = struct {...@@ -1153,7 +1153,7 @@ pub const Object = struct {
1153 }1153 }
1154 },1154 },
1155 .i32_array, .i64_array => {1155 .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();
1157 const param_llvm_ty = try dg.lowerType(param_ty);1157 const param_llvm_ty = try dg.lowerType(param_ty);
1158 const param = llvm_func.getParam(llvm_arg_i);1158 const param = llvm_func.getParam(llvm_arg_i);
1159 llvm_arg_i += 1;1159 llvm_arg_i += 1;
...@@ -1182,7 +1182,7 @@ pub const Object = struct {...@@ -1182,7 +1182,7 @@ pub const Object = struct {
1182 const line_number = decl.src_line + 1;1182 const line_number = decl.src_line + 1;
1183 const is_internal_linkage = decl.val.tag() != .extern_fn and1183 const is_internal_linkage = decl.val.tag() != .extern_fn and
1184 !mod.decl_exports.contains(decl_index);1184 !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)
1186 llvm.DIFlags.NoReturn1186 llvm.DIFlags.NoReturn
1187 else1187 else
1188 0;1188 0;
...@@ -2331,26 +2331,26 @@ pub const Object = struct {...@@ -2331,26 +2331,26 @@ pub const Object = struct {
2331 return full_di_ty;2331 return full_di_ty;
2332 },2332 },
2333 .Fn => {2333 .Fn => {
2334 const fn_info = ty.fnInfo();2334 const fn_info = mod.typeToFunc(ty).?;
23352335
2336 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);2336 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);
2337 defer param_di_types.deinit();2337 defer param_di_types.deinit();
23382338
2339 // Return type goes first.2339 // Return type goes first.
2340 if (fn_info.return_type.hasRuntimeBitsIgnoreComptime(mod)) {2340 if (fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) {
2341 const sret = firstParamSRet(fn_info, mod);2341 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();
2343 try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full));2343 try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full));
23442344
2345 if (sret) {2345 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());
2347 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));2347 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2348 }2348 }
2349 } else {2349 } else {
2350 try param_di_types.append(try o.lowerDebugType(Type.void, .full));2350 try param_di_types.append(try o.lowerDebugType(Type.void, .full));
2351 }2351 }
23522352
2353 if (fn_info.return_type.isError(mod) and2353 if (fn_info.return_type.toType().isError(mod) and
2354 o.module.comp.bin_file.options.error_return_tracing)2354 o.module.comp.bin_file.options.error_return_tracing)
2355 {2355 {
2356 const ptr_ty = try mod.singleMutPtrType(o.getStackTraceType());2356 const ptr_ty = try mod.singleMutPtrType(o.getStackTraceType());
...@@ -2358,13 +2358,13 @@ pub const Object = struct {...@@ -2358,13 +2358,13 @@ pub const Object = struct {
2358 }2358 }
23592359
2360 for (fn_info.param_types) |param_ty| {2360 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)) {2363 if (isByRef(param_ty.toType(), mod)) {
2364 const ptr_ty = try mod.singleMutPtrType(param_ty);2364 const ptr_ty = try mod.singleMutPtrType(param_ty.toType());
2365 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));2365 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2366 } else {2366 } 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));
2368 }2368 }
2369 }2369 }
23702370
...@@ -2565,7 +2565,7 @@ pub const DeclGen = struct {...@@ -2565,7 +2565,7 @@ pub const DeclGen = struct {
2565 if (gop.found_existing) return gop.value_ptr.*;2565 if (gop.found_existing) return gop.value_ptr.*;
25662566
2567 assert(decl.has_tv);2567 assert(decl.has_tv);
2568 const fn_info = zig_fn_type.fnInfo();2568 const fn_info = mod.typeToFunc(zig_fn_type).?;
2569 const target = mod.getTarget();2569 const target = mod.getTarget();
2570 const sret = firstParamSRet(fn_info, mod);2570 const sret = firstParamSRet(fn_info, mod);
25712571
...@@ -2598,11 +2598,11 @@ pub const DeclGen = struct {...@@ -2598,11 +2598,11 @@ pub const DeclGen = struct {
2598 dg.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 02598 dg.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 0
2599 dg.addArgAttr(llvm_fn, 0, "noalias");2599 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());
2602 llvm_fn.addSretAttr(raw_llvm_ret_ty);2602 llvm_fn.addSretAttr(raw_llvm_ret_ty);
2603 }2603 }
26042604
2605 const err_return_tracing = fn_info.return_type.isError(mod) and2605 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
2606 mod.comp.bin_file.options.error_return_tracing;2606 mod.comp.bin_file.options.error_return_tracing;
26072607
2608 if (err_return_tracing) {2608 if (err_return_tracing) {
...@@ -2626,13 +2626,13 @@ pub const DeclGen = struct {...@@ -2626,13 +2626,13 @@ pub const DeclGen = struct {
2626 }2626 }
26272627
2628 if (fn_info.alignment != 0) {2628 if (fn_info.alignment != 0) {
2629 llvm_fn.setAlignment(fn_info.alignment);2629 llvm_fn.setAlignment(@intCast(c_uint, fn_info.alignment));
2630 }2630 }
26312631
2632 // Function attributes that are independent of analysis results of the function body.2632 // Function attributes that are independent of analysis results of the function body.
2633 dg.addCommonFnAttributes(llvm_fn);2633 dg.addCommonFnAttributes(llvm_fn);
26342634
2635 if (fn_info.return_type.isNoReturn()) {2635 if (fn_info.return_type == .noreturn_type) {
2636 dg.addFnAttr(llvm_fn, "noreturn");2636 dg.addFnAttr(llvm_fn, "noreturn");
2637 }2637 }
26382638
...@@ -2645,15 +2645,15 @@ pub const DeclGen = struct {...@@ -2645,15 +2645,15 @@ pub const DeclGen = struct {
2645 while (it.next()) |lowering| switch (lowering) {2645 while (it.next()) |lowering| switch (lowering) {
2646 .byval => {2646 .byval => {
2647 const param_index = it.zig_index - 1;2647 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();
2649 if (!isByRef(param_ty, mod)) {2649 if (!isByRef(param_ty, mod)) {
2650 dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);2650 dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
2651 }2651 }
2652 },2652 },
2653 .byref => {2653 .byref => {
2654 const param_ty = fn_info.param_types[it.zig_index - 1];2654 const param_ty = fn_info.param_types[it.zig_index - 1];
2655 const param_llvm_ty = try dg.lowerType(param_ty);2655 const param_llvm_ty = try dg.lowerType(param_ty.toType());
2656 const alignment = param_ty.abiAlignment(mod);2656 const alignment = param_ty.toType().abiAlignment(mod);
2657 dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);2657 dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
2658 },2658 },
2659 .byref_mut => {2659 .byref_mut => {
...@@ -3142,7 +3142,7 @@ pub const DeclGen = struct {...@@ -3142,7 +3142,7 @@ pub const DeclGen = struct {
31423142
3143 fn lowerTypeFn(dg: *DeclGen, fn_ty: Type) Allocator.Error!*llvm.Type {3143 fn lowerTypeFn(dg: *DeclGen, fn_ty: Type) Allocator.Error!*llvm.Type {
3144 const mod = dg.module;3144 const mod = dg.module;
3145 const fn_info = fn_ty.fnInfo();3145 const fn_info = mod.typeToFunc(fn_ty).?;
3146 const llvm_ret_ty = try lowerFnRetTy(dg, fn_info);3146 const llvm_ret_ty = try lowerFnRetTy(dg, fn_info);
31473147
3148 var llvm_params = std.ArrayList(*llvm.Type).init(dg.gpa);3148 var llvm_params = std.ArrayList(*llvm.Type).init(dg.gpa);
...@@ -3152,7 +3152,7 @@ pub const DeclGen = struct {...@@ -3152,7 +3152,7 @@ pub const DeclGen = struct {
3152 try llvm_params.append(dg.context.pointerType(0));3152 try llvm_params.append(dg.context.pointerType(0));
3153 }3153 }
31543154
3155 if (fn_info.return_type.isError(mod) and3155 if (fn_info.return_type.toType().isError(mod) and
3156 mod.comp.bin_file.options.error_return_tracing)3156 mod.comp.bin_file.options.error_return_tracing)
3157 {3157 {
3158 const ptr_ty = try mod.singleMutPtrType(dg.object.getStackTraceType());3158 const ptr_ty = try mod.singleMutPtrType(dg.object.getStackTraceType());
...@@ -3163,19 +3163,19 @@ pub const DeclGen = struct {...@@ -3163,19 +3163,19 @@ pub const DeclGen = struct {
3163 while (it.next()) |lowering| switch (lowering) {3163 while (it.next()) |lowering| switch (lowering) {
3164 .no_bits => continue,3164 .no_bits => continue,
3165 .byval => {3165 .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();
3167 try llvm_params.append(try dg.lowerType(param_ty));3167 try llvm_params.append(try dg.lowerType(param_ty));
3168 },3168 },
3169 .byref, .byref_mut => {3169 .byref, .byref_mut => {
3170 try llvm_params.append(dg.context.pointerType(0));3170 try llvm_params.append(dg.context.pointerType(0));
3171 },3171 },
3172 .abi_sized_int => {3172 .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();
3174 const abi_size = @intCast(c_uint, param_ty.abiSize(mod));3174 const abi_size = @intCast(c_uint, param_ty.abiSize(mod));
3175 try llvm_params.append(dg.context.intType(abi_size * 8));3175 try llvm_params.append(dg.context.intType(abi_size * 8));
3176 },3176 },
3177 .slice => {3177 .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();
3179 var buf: Type.SlicePtrFieldTypeBuffer = undefined;3179 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
3180 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)3180 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
3181 param_ty.optionalChild(mod).slicePtrFieldType(&buf, mod)3181 param_ty.optionalChild(mod).slicePtrFieldType(&buf, mod)
...@@ -3195,7 +3195,7 @@ pub const DeclGen = struct {...@@ -3195,7 +3195,7 @@ pub const DeclGen = struct {
3195 try llvm_params.append(dg.context.intType(16));3195 try llvm_params.append(dg.context.intType(16));
3196 },3196 },
3197 .float_array => |count| {3197 .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();
3199 const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);3199 const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
3200 const field_count = @intCast(c_uint, count);3200 const field_count = @intCast(c_uint, count);
3201 const arr_ty = float_ty.arrayType(field_count);3201 const arr_ty = float_ty.arrayType(field_count);
...@@ -3223,7 +3223,7 @@ pub const DeclGen = struct {...@@ -3223,7 +3223,7 @@ pub const DeclGen = struct {
3223 const mod = dg.module;3223 const mod = dg.module;
3224 const lower_elem_ty = switch (elem_ty.zigTypeTag(mod)) {3224 const lower_elem_ty = switch (elem_ty.zigTypeTag(mod)) {
3225 .Opaque => true,3225 .Opaque => true,
3226 .Fn => !elem_ty.fnInfo().is_generic,3226 .Fn => !mod.typeToFunc(elem_ty).?.is_generic,
3227 .Array => elem_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod),3227 .Array => elem_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod),
3228 else => elem_ty.hasRuntimeBitsIgnoreComptime(mod),3228 else => elem_ty.hasRuntimeBitsIgnoreComptime(mod),
3229 };3229 };
...@@ -4204,7 +4204,7 @@ pub const DeclGen = struct {...@@ -4204,7 +4204,7 @@ pub const DeclGen = struct {
42044204
4205 const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn;4205 const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn;
4206 if ((!is_fn_body and !decl.ty.hasRuntimeBits(mod)) or4206 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))
4208 {4208 {
4209 return self.lowerPtrToVoid(tv.ty);4209 return self.lowerPtrToVoid(tv.ty);
4210 }4210 }
...@@ -4354,7 +4354,7 @@ pub const DeclGen = struct {...@@ -4354,7 +4354,7 @@ pub const DeclGen = struct {
4354 llvm_fn: *llvm.Value,4354 llvm_fn: *llvm.Value,
4355 param_ty: Type,4355 param_ty: Type,
4356 param_index: u32,4356 param_index: u32,
4357 fn_info: Type.Payload.Function.Data,4357 fn_info: InternPool.Key.FuncType,
4358 llvm_arg_i: u32,4358 llvm_arg_i: u32,
4359 ) void {4359 ) void {
4360 const mod = dg.module;4360 const mod = dg.module;
...@@ -4774,8 +4774,8 @@ pub const FuncGen = struct {...@@ -4774,8 +4774,8 @@ pub const FuncGen = struct {
4774 .Pointer => callee_ty.childType(mod),4774 .Pointer => callee_ty.childType(mod),
4775 else => unreachable,4775 else => unreachable,
4776 };4776 };
4777 const fn_info = zig_fn_ty.fnInfo();4777 const fn_info = mod.typeToFunc(zig_fn_ty).?;
4778 const return_type = fn_info.return_type;4778 const return_type = fn_info.return_type.toType();
4779 const llvm_fn = try self.resolveInst(pl_op.operand);4779 const llvm_fn = try self.resolveInst(pl_op.operand);
4780 const target = mod.getTarget();4780 const target = mod.getTarget();
4781 const sret = firstParamSRet(fn_info, mod);4781 const sret = firstParamSRet(fn_info, mod);
...@@ -4790,7 +4790,7 @@ pub const FuncGen = struct {...@@ -4790,7 +4790,7 @@ pub const FuncGen = struct {
4790 break :blk ret_ptr;4790 break :blk ret_ptr;
4791 };4791 };
47924792
4793 const err_return_tracing = fn_info.return_type.isError(mod) and4793 const err_return_tracing = return_type.isError(mod) and
4794 self.dg.module.comp.bin_file.options.error_return_tracing;4794 self.dg.module.comp.bin_file.options.error_return_tracing;
4795 if (err_return_tracing) {4795 if (err_return_tracing) {
4796 try llvm_args.append(self.err_ret_trace.?);4796 try llvm_args.append(self.err_ret_trace.?);
...@@ -4971,14 +4971,14 @@ pub const FuncGen = struct {...@@ -4971,14 +4971,14 @@ pub const FuncGen = struct {
4971 while (it.next()) |lowering| switch (lowering) {4971 while (it.next()) |lowering| switch (lowering) {
4972 .byval => {4972 .byval => {
4973 const param_index = it.zig_index - 1;4973 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();
4975 if (!isByRef(param_ty, mod)) {4975 if (!isByRef(param_ty, mod)) {
4976 self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);4976 self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
4977 }4977 }
4978 },4978 },
4979 .byref => {4979 .byref => {
4980 const param_index = it.zig_index - 1;4980 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();
4982 const param_llvm_ty = try self.dg.lowerType(param_ty);4982 const param_llvm_ty = try self.dg.lowerType(param_ty);
4983 const alignment = param_ty.abiAlignment(mod);4983 const alignment = param_ty.abiAlignment(mod);
4984 self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);4984 self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
...@@ -4998,7 +4998,7 @@ pub const FuncGen = struct {...@@ -4998,7 +4998,7 @@ pub const FuncGen = struct {
49984998
4999 .slice => {4999 .slice => {
5000 assert(!it.byval_attr);5000 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();
5002 const ptr_info = param_ty.ptrInfo(mod);5002 const ptr_info = param_ty.ptrInfo(mod);
5003 const llvm_arg_i = it.llvm_index - 2;5003 const llvm_arg_i = it.llvm_index - 2;
50045004
...@@ -5023,7 +5023,7 @@ pub const FuncGen = struct {...@@ -5023,7 +5023,7 @@ pub const FuncGen = struct {
5023 };5023 };
5024 }5024 }
50255025
5026 if (return_type.isNoReturn() and attr != .AlwaysTail) {5026 if (fn_info.return_type == .noreturn_type and attr != .AlwaysTail) {
5027 return null;5027 return null;
5028 }5028 }
50295029
...@@ -5088,9 +5088,9 @@ pub const FuncGen = struct {...@@ -5088,9 +5088,9 @@ pub const FuncGen = struct {
5088 _ = self.builder.buildRetVoid();5088 _ = self.builder.buildRetVoid();
5089 return null;5089 return null;
5090 }5090 }
5091 const fn_info = self.dg.decl.ty.fnInfo();5091 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;
5092 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {5092 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5093 if (fn_info.return_type.isError(mod)) {5093 if (fn_info.return_type.toType().isError(mod)) {
5094 // Functions with an empty error set are emitted with an error code5094 // Functions with an empty error set are emitted with an error code
5095 // return type and return zero so they can be function pointers coerced5095 // return type and return zero so they can be function pointers coerced
5096 // to functions that return anyerror.5096 // to functions that return anyerror.
...@@ -5135,9 +5135,9 @@ pub const FuncGen = struct {...@@ -5135,9 +5135,9 @@ pub const FuncGen = struct {
5135 const un_op = self.air.instructions.items(.data)[inst].un_op;5135 const un_op = self.air.instructions.items(.data)[inst].un_op;
5136 const ptr_ty = self.typeOf(un_op);5136 const ptr_ty = self.typeOf(un_op);
5137 const ret_ty = ptr_ty.childType(mod);5137 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).?;
5139 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {5139 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5140 if (fn_info.return_type.isError(mod)) {5140 if (fn_info.return_type.toType().isError(mod)) {
5141 // Functions with an empty error set are emitted with an error code5141 // Functions with an empty error set are emitted with an error code
5142 // return type and return zero so they can be function pointers coerced5142 // return type and return zero so they can be function pointers coerced
5143 // to functions that return anyerror.5143 // to functions that return anyerror.
...@@ -6148,25 +6148,21 @@ pub const FuncGen = struct {...@@ -6148,25 +6148,21 @@ pub const FuncGen = struct {
6148 defer self.gpa.free(fqn);6148 defer self.gpa.free(fqn);
61496149
6150 const is_internal_linkage = !mod.decl_exports.contains(decl_index);6150 const is_internal_linkage = !mod.decl_exports.contains(decl_index);
6151 var fn_ty_pl: Type.Payload.Function = .{6151 const fn_ty = try mod.funcType(.{
6152 .base = .{ .tag = .function },6152 .param_types = &.{},
6153 .data = .{6153 .return_type = .void_type,
6154 .param_types = &.{},6154 .alignment = 0,
6155 .comptime_params = undefined,6155 .noalias_bits = 0,
6156 .return_type = Type.void,6156 .comptime_bits = 0,
6157 .alignment = 0,6157 .cc = .Unspecified,
6158 .noalias_bits = 0,6158 .is_var_args = false,
6159 .cc = .Unspecified,6159 .is_generic = false,
6160 .is_var_args = false,6160 .is_noinline = false,
6161 .is_generic = false,6161 .align_is_generic = false,
6162 .is_noinline = false,6162 .cc_is_generic = false,
6163 .align_is_generic = false,6163 .section_is_generic = false,
6164 .cc_is_generic = false,6164 .addrspace_is_generic = false,
6165 .section_is_generic = false,6165 });
6166 .addrspace_is_generic = false,
6167 },
6168 };
6169 const fn_ty = Type.initPayload(&fn_ty_pl.base);
6170 const subprogram = dib.createFunction(6166 const subprogram = dib.createFunction(
6171 di_file.toScope(),6167 di_file.toScope(),
6172 decl.name,6168 decl.name,
...@@ -10546,31 +10542,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {...@@ -10546,31 +10542,31 @@ fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
10546 }10542 }
10547}10543}
1054810544
10549fn firstParamSRet(fn_info: Type.Payload.Function.Data, mod: *Module) bool {10545fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool {
10550 if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime(mod)) return false;10546 if (!fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) return false;
1055110547
10552 const target = mod.getTarget();10548 const target = mod.getTarget();
10553 switch (fn_info.cc) {10549 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),
10555 .C => switch (target.cpu.arch) {10551 .C => switch (target.cpu.arch) {
10556 .mips, .mipsel => return false,10552 .mips, .mipsel => return false,
10557 .x86_64 => switch (target.os.tag) {10553 .x86_64 => switch (target.os.tag) {
10558 .windows => return x86_64_abi.classifyWindows(fn_info.return_type, mod) == .memory,10554 .windows => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10559 else => return firstParamSRetSystemV(fn_info.return_type, mod),10555 else => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
10560 },10556 },
10561 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, mod)[0] == .indirect,10557 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type.toType(), mod)[0] == .indirect,
10562 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, mod) == .memory,10558 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
10563 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type, mod, .ret)) {10559 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type.toType(), mod, .ret)) {
10564 .memory, .i64_array => return true,10560 .memory, .i64_array => return true,
10565 .i32_array => |size| return size != 1,10561 .i32_array => |size| return size != 1,
10566 .byval => return false,10562 .byval => return false,
10567 },10563 },
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,
10569 else => return false, // TODO investigate C ABI for other architectures10565 else => return false, // TODO investigate C ABI for other architectures
10570 },10566 },
10571 .SysV => return firstParamSRetSystemV(fn_info.return_type, mod),10567 .SysV => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
10572 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type, mod) == .memory,10568 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10573 .Stdcall => return !isScalar(mod, fn_info.return_type),10569 .Stdcall => return !isScalar(mod, fn_info.return_type.toType()),
10574 else => return false,10570 else => return false,
10575 }10571 }
10576}10572}
...@@ -10585,13 +10581,14 @@ fn firstParamSRetSystemV(ty: Type, mod: *Module) bool {...@@ -10585,13 +10581,14 @@ fn firstParamSRetSystemV(ty: Type, mod: *Module) bool {
10585/// In order to support the C calling convention, some return types need to be lowered10581/// In order to support the C calling convention, some return types need to be lowered
10586/// completely differently in the function prototype to honor the C ABI, and then10582/// completely differently in the function prototype to honor the C ABI, and then
10587/// be effectively bitcasted to the actual return type.10583/// 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 {
10589 const mod = dg.module;10585 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)) {
10591 // If the return type is an error set or an error union, then we make this10588 // If the return type is an error set or an error union, then we make this
10592 // anyerror return type instead, so that it can be coerced into a function10589 // anyerror return type instead, so that it can be coerced into a function
10593 // pointer type which has anyerror as the return type.10590 // pointer type which has anyerror as the return type.
10594 if (fn_info.return_type.isError(mod)) {10591 if (return_type.isError(mod)) {
10595 return dg.lowerType(Type.anyerror);10592 return dg.lowerType(Type.anyerror);
10596 } else {10593 } else {
10597 return dg.context.voidType();10594 return dg.context.voidType();
...@@ -10600,61 +10597,61 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {...@@ -10600,61 +10597,61 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10600 const target = mod.getTarget();10597 const target = mod.getTarget();
10601 switch (fn_info.cc) {10598 switch (fn_info.cc) {
10602 .Unspecified, .Inline => {10599 .Unspecified, .Inline => {
10603 if (isByRef(fn_info.return_type, mod)) {10600 if (isByRef(return_type, mod)) {
10604 return dg.context.voidType();10601 return dg.context.voidType();
10605 } else {10602 } else {
10606 return dg.lowerType(fn_info.return_type);10603 return dg.lowerType(return_type);
10607 }10604 }
10608 },10605 },
10609 .C => {10606 .C => {
10610 switch (target.cpu.arch) {10607 switch (target.cpu.arch) {
10611 .mips, .mipsel => return dg.lowerType(fn_info.return_type),10608 .mips, .mipsel => return dg.lowerType(return_type),
10612 .x86_64 => switch (target.os.tag) {10609 .x86_64 => switch (target.os.tag) {
10613 .windows => return lowerWin64FnRetTy(dg, fn_info),10610 .windows => return lowerWin64FnRetTy(dg, fn_info),
10614 else => return lowerSystemVFnRetTy(dg, fn_info),10611 else => return lowerSystemVFnRetTy(dg, fn_info),
10615 },10612 },
10616 .wasm32 => {10613 .wasm32 => {
10617 if (isScalar(mod, fn_info.return_type)) {10614 if (isScalar(mod, return_type)) {
10618 return dg.lowerType(fn_info.return_type);10615 return dg.lowerType(return_type);
10619 }10616 }
10620 const classes = wasm_c_abi.classifyType(fn_info.return_type, mod);10617 const classes = wasm_c_abi.classifyType(return_type, mod);
10621 if (classes[0] == .indirect or classes[0] == .none) {10618 if (classes[0] == .indirect or classes[0] == .none) {
10622 return dg.context.voidType();10619 return dg.context.voidType();
10623 }10620 }
1062410621
10625 assert(classes[0] == .direct and classes[1] == .none);10622 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);
10627 const abi_size = scalar_type.abiSize(mod);10624 const abi_size = scalar_type.abiSize(mod);
10628 return dg.context.intType(@intCast(c_uint, abi_size * 8));10625 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10629 },10626 },
10630 .aarch64, .aarch64_be => {10627 .aarch64, .aarch64_be => {
10631 switch (aarch64_c_abi.classifyType(fn_info.return_type, mod)) {10628 switch (aarch64_c_abi.classifyType(return_type, mod)) {
10632 .memory => return dg.context.voidType(),10629 .memory => return dg.context.voidType(),
10633 .float_array => return dg.lowerType(fn_info.return_type),10630 .float_array => return dg.lowerType(return_type),
10634 .byval => return dg.lowerType(fn_info.return_type),10631 .byval => return dg.lowerType(return_type),
10635 .integer => {10632 .integer => {
10636 const bit_size = fn_info.return_type.bitSize(mod);10633 const bit_size = return_type.bitSize(mod);
10637 return dg.context.intType(@intCast(c_uint, bit_size));10634 return dg.context.intType(@intCast(c_uint, bit_size));
10638 },10635 },
10639 .double_integer => return dg.context.intType(64).arrayType(2),10636 .double_integer => return dg.context.intType(64).arrayType(2),
10640 }10637 }
10641 },10638 },
10642 .arm, .armeb => {10639 .arm, .armeb => {
10643 switch (arm_c_abi.classifyType(fn_info.return_type, mod, .ret)) {10640 switch (arm_c_abi.classifyType(return_type, mod, .ret)) {
10644 .memory, .i64_array => return dg.context.voidType(),10641 .memory, .i64_array => return dg.context.voidType(),
10645 .i32_array => |len| if (len == 1) {10642 .i32_array => |len| if (len == 1) {
10646 return dg.context.intType(32);10643 return dg.context.intType(32);
10647 } else {10644 } else {
10648 return dg.context.voidType();10645 return dg.context.voidType();
10649 },10646 },
10650 .byval => return dg.lowerType(fn_info.return_type),10647 .byval => return dg.lowerType(return_type),
10651 }10648 }
10652 },10649 },
10653 .riscv32, .riscv64 => {10650 .riscv32, .riscv64 => {
10654 switch (riscv_c_abi.classifyType(fn_info.return_type, mod)) {10651 switch (riscv_c_abi.classifyType(return_type, mod)) {
10655 .memory => return dg.context.voidType(),10652 .memory => return dg.context.voidType(),
10656 .integer => {10653 .integer => {
10657 const bit_size = fn_info.return_type.bitSize(mod);10654 const bit_size = return_type.bitSize(mod);
10658 return dg.context.intType(@intCast(c_uint, bit_size));10655 return dg.context.intType(@intCast(c_uint, bit_size));
10659 },10656 },
10660 .double_integer => {10657 .double_integer => {
...@@ -10664,50 +10661,52 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {...@@ -10664,50 +10661,52 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10664 };10661 };
10665 return dg.context.structType(&llvm_types_buffer, 2, .False);10662 return dg.context.structType(&llvm_types_buffer, 2, .False);
10666 },10663 },
10667 .byval => return dg.lowerType(fn_info.return_type),10664 .byval => return dg.lowerType(return_type),
10668 }10665 }
10669 },10666 },
10670 // TODO investigate C ABI for other architectures10667 // TODO investigate C ABI for other architectures
10671 else => return dg.lowerType(fn_info.return_type),10668 else => return dg.lowerType(return_type),
10672 }10669 }
10673 },10670 },
10674 .Win64 => return lowerWin64FnRetTy(dg, fn_info),10671 .Win64 => return lowerWin64FnRetTy(dg, fn_info),
10675 .SysV => return lowerSystemVFnRetTy(dg, fn_info),10672 .SysV => return lowerSystemVFnRetTy(dg, fn_info),
10676 .Stdcall => {10673 .Stdcall => {
10677 if (isScalar(mod, fn_info.return_type)) {10674 if (isScalar(mod, return_type)) {
10678 return dg.lowerType(fn_info.return_type);10675 return dg.lowerType(return_type);
10679 } else {10676 } else {
10680 return dg.context.voidType();10677 return dg.context.voidType();
10681 }10678 }
10682 },10679 },
10683 else => return dg.lowerType(fn_info.return_type),10680 else => return dg.lowerType(return_type),
10684 }10681 }
10685}10682}
1068610683
10687fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {10684fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
10688 const mod = dg.module;10685 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)) {
10690 .integer => {10688 .integer => {
10691 if (isScalar(mod, fn_info.return_type)) {10689 if (isScalar(mod, return_type)) {
10692 return dg.lowerType(fn_info.return_type);10690 return dg.lowerType(return_type);
10693 } else {10691 } else {
10694 const abi_size = fn_info.return_type.abiSize(mod);10692 const abi_size = return_type.abiSize(mod);
10695 return dg.context.intType(@intCast(c_uint, abi_size * 8));10693 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10696 }10694 }
10697 },10695 },
10698 .win_i128 => return dg.context.intType(64).vectorType(2),10696 .win_i128 => return dg.context.intType(64).vectorType(2),
10699 .memory => return dg.context.voidType(),10697 .memory => return dg.context.voidType(),
10700 .sse => return dg.lowerType(fn_info.return_type),10698 .sse => return dg.lowerType(return_type),
10701 else => unreachable,10699 else => unreachable,
10702 }10700 }
10703}10701}
1070410702
10705fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {10703fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
10706 const mod = dg.module;10704 const mod = dg.module;
10707 if (isScalar(mod, fn_info.return_type)) {10705 const return_type = fn_info.return_type.toType();
10708 return dg.lowerType(fn_info.return_type);10706 if (isScalar(mod, return_type)) {
10707 return dg.lowerType(return_type);
10709 }10708 }
10710 const classes = x86_64_abi.classifySystemV(fn_info.return_type, mod, .ret);10709 const classes = x86_64_abi.classifySystemV(return_type, mod, .ret);
10711 if (classes[0] == .memory) {10710 if (classes[0] == .memory) {
10712 return dg.context.voidType();10711 return dg.context.voidType();
10713 }10712 }
...@@ -10748,7 +10747,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm...@@ -10748,7 +10747,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm
10748 }10747 }
10749 }10748 }
10750 if (classes[0] == .integer and classes[1] == .none) {10749 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);
10752 return dg.context.intType(@intCast(c_uint, abi_size * 8));10751 return dg.context.intType(@intCast(c_uint, abi_size * 8));
10753 }10752 }
10754 return dg.context.structType(&llvm_types_buffer, llvm_types_index, .False);10753 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...@@ -10756,7 +10755,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm
1075610755
10757const ParamTypeIterator = struct {10756const ParamTypeIterator = struct {
10758 dg: *DeclGen,10757 dg: *DeclGen,
10759 fn_info: Type.Payload.Function.Data,10758 fn_info: InternPool.Key.FuncType,
10760 zig_index: u32,10759 zig_index: u32,
10761 llvm_index: u32,10760 llvm_index: u32,
10762 llvm_types_len: u32,10761 llvm_types_len: u32,
...@@ -10781,7 +10780,7 @@ const ParamTypeIterator = struct {...@@ -10781,7 +10780,7 @@ const ParamTypeIterator = struct {
10781 if (it.zig_index >= it.fn_info.param_types.len) return null;10780 if (it.zig_index >= it.fn_info.param_types.len) return null;
10782 const ty = it.fn_info.param_types[it.zig_index];10781 const ty = it.fn_info.param_types[it.zig_index];
10783 it.byval_attr = false;10782 it.byval_attr = false;
10784 return nextInner(it, ty);10783 return nextInner(it, ty.toType());
10785 }10784 }
1078610785
10787 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.10786 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
...@@ -10793,7 +10792,7 @@ const ParamTypeIterator = struct {...@@ -10793,7 +10792,7 @@ const ParamTypeIterator = struct {
10793 return nextInner(it, fg.typeOf(args[it.zig_index]));10792 return nextInner(it, fg.typeOf(args[it.zig_index]));
10794 }10793 }
10795 } else {10794 } 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());
10797 }10796 }
10798 }10797 }
1079910798
...@@ -11009,7 +11008,7 @@ const ParamTypeIterator = struct {...@@ -11009,7 +11008,7 @@ const ParamTypeIterator = struct {
11009 }11008 }
11010};11009};
1101111010
11012fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTypeIterator {11011fn iterateParamTypes(dg: *DeclGen, fn_info: InternPool.Key.FuncType) ParamTypeIterator {
11013 return .{11012 return .{
11014 .dg = dg,11013 .dg = dg,
11015 .fn_info = fn_info,11014 .fn_info = fn_info,
src/codegen/spirv.zig+11-11
...@@ -1227,8 +1227,9 @@ pub const DeclGen = struct {...@@ -1227,8 +1227,9 @@ pub const DeclGen = struct {
1227 },1227 },
1228 .Fn => switch (repr) {1228 .Fn => switch (repr) {
1229 .direct => {1229 .direct => {
1230 const fn_info = mod.typeToFunc(ty).?;
1230 // TODO: Put this somewhere in Sema.zig1231 // TODO: Put this somewhere in Sema.zig
1231 if (ty.fnIsVarArgs())1232 if (fn_info.is_var_args)
1232 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});1233 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});
12331234
1234 const param_ty_refs = try self.gpa.alloc(CacheRef, ty.fnParamLen());1235 const param_ty_refs = try self.gpa.alloc(CacheRef, ty.fnParamLen());
...@@ -1546,18 +1547,17 @@ pub const DeclGen = struct {...@@ -1546,18 +1547,17 @@ pub const DeclGen = struct {
1546 assert(decl.ty.zigTypeTag(mod) == .Fn);1547 assert(decl.ty.zigTypeTag(mod) == .Fn);
1547 const prototype_id = try self.resolveTypeId(decl.ty);1548 const prototype_id = try self.resolveTypeId(decl.ty);
1548 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{1549 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)),
1550 .id_result = decl_id,1551 .id_result = decl_id,
1551 .function_control = .{}, // TODO: We can set inline here if the type requires it.1552 .function_control = .{}, // TODO: We can set inline here if the type requires it.
1552 .function_type = prototype_id,1553 .function_type = prototype_id,
1553 });1554 });
15541555
1555 const params = decl.ty.fnParamLen();1556 const fn_info = mod.typeToFunc(decl.ty).?;
1556 var i: usize = 0;
15571557
1558 try self.args.ensureUnusedCapacity(self.gpa, params);1558 try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
1559 while (i < params) : (i += 1) {1559 for (fn_info.param_types) |param_type| {
1560 const param_type_id = try self.resolveTypeId(decl.ty.fnParamType(i));1560 const param_type_id = try self.resolveTypeId(param_type.toType());
1561 const arg_result_id = self.spv.allocId();1561 const arg_result_id = self.spv.allocId();
1562 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{1562 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
1563 .id_result_type = param_type_id,1563 .id_result_type = param_type_id,
...@@ -3338,10 +3338,10 @@ pub const DeclGen = struct {...@@ -3338,10 +3338,10 @@ pub const DeclGen = struct {
3338 .Pointer => return self.fail("cannot call function pointers", .{}),3338 .Pointer => return self.fail("cannot call function pointers", .{}),
3339 else => unreachable,3339 else => unreachable,
3340 };3340 };
3341 const fn_info = zig_fn_ty.fnInfo();3341 const fn_info = mod.typeToFunc(zig_fn_ty).?;
3342 const return_type = fn_info.return_type;3342 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());
3345 const result_id = self.spv.allocId();3345 const result_id = self.spv.allocId();
3346 const callee_id = try self.resolve(pl_op.operand);3346 const callee_id = try self.resolve(pl_op.operand);
33473347
...@@ -3368,11 +3368,11 @@ pub const DeclGen = struct {...@@ -3368,11 +3368,11 @@ pub const DeclGen = struct {
3368 .id_ref_3 = params[0..n_params],3368 .id_ref_3 = params[0..n_params],
3369 });3369 });
33703370
3371 if (return_type.isNoReturn()) {3371 if (return_type == .noreturn_type) {
3372 try self.func.body.emit(self.spv.gpa, .OpUnreachable, {});3372 try self.func.body.emit(self.spv.gpa, .OpUnreachable, {});
3373 }3373 }
33743374
3375 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(mod)) {3375 if (self.liveness.isUnused(inst) or !return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) {
3376 return null;3376 return null;
3377 }3377 }
33783378
src/link/Coff.zig+1-1
...@@ -1430,7 +1430,7 @@ pub fn updateDeclExports(...@@ -1430,7 +1430,7 @@ pub fn updateDeclExports(
1430 .x86 => std.builtin.CallingConvention.Stdcall,1430 .x86 => std.builtin.CallingConvention.Stdcall,
1431 else => std.builtin.CallingConvention.C,1431 else => std.builtin.CallingConvention.C,
1432 };1432 };
1433 const decl_cc = exported_decl.ty.fnCallingConvention();1433 const decl_cc = exported_decl.ty.fnCallingConvention(mod);
1434 if (decl_cc == .C and mem.eql(u8, exp.options.name, "main") and1434 if (decl_cc == .C and mem.eql(u8, exp.options.name, "main") and
1435 self.base.options.link_libc)1435 self.base.options.link_libc)
1436 {1436 {
src/link/Dwarf.zig+1-1
...@@ -1022,7 +1022,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)...@@ -1022,7 +1022,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
1022 const decl_name_with_null = decl_name[0 .. decl_name.len + 1];1022 const decl_name_with_null = decl_name[0 .. decl_name.len + 1];
1023 try dbg_info_buffer.ensureUnusedCapacity(25 + decl_name_with_null.len);1023 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);
1026 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);1026 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);
1027 if (fn_ret_has_bits) {1027 if (fn_ret_has_bits) {
1028 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.subprogram));1028 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)...@@ -131,12 +131,12 @@ pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index)
131131
132pub fn updateDeclExports(132pub fn updateDeclExports(
133 self: *SpirV,133 self: *SpirV,
134 module: *Module,134 mod: *Module,
135 decl_index: Module.Decl.Index,135 decl_index: Module.Decl.Index,
136 exports: []const *Module.Export,136 exports: []const *Module.Export,
137) !void {137) !void {
138 const decl = module.declPtr(decl_index);138 const decl = mod.declPtr(decl_index);
139 if (decl.val.tag() == .function and decl.ty.fnCallingConvention() == .Kernel) {139 if (decl.val.tag() == .function and decl.ty.fnCallingConvention(mod) == .Kernel) {
140 // TODO: Unify with resolveDecl in spirv.zig.140 // TODO: Unify with resolveDecl in spirv.zig.
141 const entry = try self.decl_link.getOrPut(decl_index);141 const entry = try self.decl_link.getOrPut(decl_index);
142 if (!entry.found_existing) {142 if (!entry.found_existing) {
src/target.zig+11
...@@ -649,3 +649,14 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {...@@ -649,3 +649,14 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {
649 else => "o", // Non-standard649 else => "o", // Non-standard
650 };650 };
651}651}
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 {...@@ -42,8 +42,6 @@ pub const Type = struct {
42 .error_set_merged,42 .error_set_merged,
43 => return .ErrorSet,43 => return .ErrorSet,
4444
45 .function => return .Fn,
46
47 .pointer,45 .pointer,
48 .inferred_alloc_const,46 .inferred_alloc_const,
49 .inferred_alloc_mut,47 .inferred_alloc_mut,
...@@ -66,6 +64,7 @@ pub const Type = struct {...@@ -66,6 +64,7 @@ pub const Type = struct {
66 .union_type => return .Union,64 .union_type => return .Union,
67 .opaque_type => return .Opaque,65 .opaque_type => return .Opaque,
68 .enum_type => return .Enum,66 .enum_type => return .Enum,
67 .func_type => return .Fn,
69 .simple_type => |s| switch (s) {68 .simple_type => |s| switch (s) {
70 .f16,69 .f16,
71 .f32,70 .f32,
...@@ -344,53 +343,6 @@ pub const Type = struct {...@@ -344,53 +343,6 @@ pub const Type = struct {
344 return true;343 return true;
345 },344 },
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
394 .pointer,346 .pointer,
395 .inferred_alloc_const,347 .inferred_alloc_const,
396 .inferred_alloc_mut,348 .inferred_alloc_mut,
...@@ -501,32 +453,6 @@ pub const Type = struct {...@@ -501,32 +453,6 @@ pub const Type = struct {
501 std.hash.autoHash(hasher, ies);453 std.hash.autoHash(hasher, ies);
502 },454 },
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
530 .pointer,456 .pointer,
531 .inferred_alloc_const,457 .inferred_alloc_const,
532 .inferred_alloc_mut,458 .inferred_alloc_mut,
...@@ -631,30 +557,6 @@ pub const Type = struct {...@@ -631,30 +557,6 @@ pub const Type = struct {
631 };557 };
632 },558 },
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 },
658 .pointer => {560 .pointer => {
659 const payload = self.castTag(.pointer).?.data;561 const payload = self.castTag(.pointer).?.data;
660 const sent: ?Value = if (payload.sentinel) |some|562 const sent: ?Value = if (payload.sentinel) |some|
...@@ -766,32 +668,6 @@ pub const Type = struct {...@@ -766,32 +668,6 @@ pub const Type = struct {
766 while (true) {668 while (true) {
767 const t = ty.tag();669 const t = ty.tag();
768 switch (t) {670 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
795 .anyframe_T => {671 .anyframe_T => {
796 const return_type = ty.castTag(.anyframe_T).?.data;672 const return_type = ty.castTag(.anyframe_T).?.data;
797 try writer.print("anyframe->", .{});673 try writer.print("anyframe->", .{});
...@@ -909,48 +785,6 @@ pub const Type = struct {...@@ -909,48 +785,6 @@ pub const Type = struct {
909 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");785 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
910 },786 },
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
954 .error_union => {788 .error_union => {
955 const error_union = ty.castTag(.error_union).?.data;789 const error_union = ty.castTag(.error_union).?.data;
956 try print(error_union.error_set, writer, mod);790 try print(error_union.error_set, writer, mod);
...@@ -1158,6 +992,48 @@ pub const Type = struct {...@@ -1158,6 +992,48 @@ pub const Type = struct {
1158 const decl = mod.declPtr(enum_type.decl);992 const decl = mod.declPtr(enum_type.decl);
1159 try decl.renderFullyQualifiedName(mod, writer);993 try decl.renderFullyQualifiedName(mod, writer);
1160 },994 },
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
1162 // values, not types1038 // values, not types
1163 .undef => unreachable,1039 .undef => unreachable,
...@@ -1174,6 +1050,11 @@ pub const Type = struct {...@@ -1174,6 +1050,11 @@ pub const Type = struct {
1174 }1050 }
1175 }1051 }
11761052
1053 pub fn toIntern(ty: Type) InternPool.Index {
1054 assert(ty.ip_index != .none);
1055 return ty.ip_index;
1056 }
1057
1177 pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value {1058 pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value {
1178 if (self.ip_index != .none) return self.ip_index.toValue();1059 if (self.ip_index != .none) return self.ip_index.toValue();
1179 switch (self.tag()) {1060 switch (self.tag()) {
...@@ -1223,7 +1104,7 @@ pub const Type = struct {...@@ -1223,7 +1104,7 @@ pub const Type = struct {
1223 if (ignore_comptime_only) {1104 if (ignore_comptime_only) {
1224 return true;1105 return true;
1225 } else if (ty.childType(mod).zigTypeTag(mod) == .Fn) {1106 } 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;
1227 } else if (strat == .sema) {1108 } else if (strat == .sema) {
1228 return !(try strat.sema.typeRequiresComptime(ty));1109 return !(try strat.sema.typeRequiresComptime(ty));
1229 } else {1110 } else {
...@@ -1231,12 +1112,6 @@ pub const Type = struct {...@@ -1231,12 +1112,6 @@ pub const Type = struct {
1231 }1112 }
1232 },1113 },
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
1240 .optional => {1115 .optional => {
1241 const child_ty = ty.optionalChild(mod);1116 const child_ty = ty.optionalChild(mod);
1242 if (child_ty.isNoReturn()) {1117 if (child_ty.isNoReturn()) {
...@@ -1262,7 +1137,7 @@ pub const Type = struct {...@@ -1262,7 +1137,7 @@ pub const Type = struct {
1262 // to comptime-only types do not, with the exception of function pointers.1137 // to comptime-only types do not, with the exception of function pointers.
1263 if (ignore_comptime_only) return true;1138 if (ignore_comptime_only) return true;
1264 const child_ty = ptr_type.elem_type.toType();1139 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;
1266 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));1141 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));
1267 return !comptimeOnly(ty, mod);1142 return !comptimeOnly(ty, mod);
1268 },1143 },
...@@ -1293,6 +1168,13 @@ pub const Type = struct {...@@ -1293,6 +1168,13 @@ pub const Type = struct {
1293 }1168 }
1294 },1169 },
1295 .error_union_type => @panic("TODO"),1170 .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
1296 .simple_type => |t| switch (t) {1178 .simple_type => |t| switch (t) {
1297 .f16,1179 .f16,
1298 .f32,1180 .f32,
...@@ -1436,8 +1318,6 @@ pub const Type = struct {...@@ -1436,8 +1318,6 @@ pub const Type = struct {
1436 .error_set_single,1318 .error_set_single,
1437 .error_set_inferred,1319 .error_set_inferred,
1438 .error_set_merged,1320 .error_set_merged,
1439 // These are function bodies, not function pointers.
1440 .function,
1441 .error_union,1321 .error_union,
1442 .anyframe_T,1322 .anyframe_T,
1443 => false,1323 => false,
...@@ -1448,12 +1328,21 @@ pub const Type = struct {...@@ -1448,12 +1328,21 @@ pub const Type = struct {
1448 .optional => ty.isPtrLikeOptional(mod),1328 .optional => ty.isPtrLikeOptional(mod),
1449 },1329 },
1450 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {1330 else => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1451 .int_type => true,1331 .int_type,
1452 .ptr_type => true,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
1453 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),1343 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
1454 .vector_type => true,
1455 .opt_type => |child| child.toType().isPtrLikeOptional(mod),1344 .opt_type => |child| child.toType().isPtrLikeOptional(mod),
1456 .error_union_type => false,1345
1457 .simple_type => |t| switch (t) {1346 .simple_type => |t| switch (t) {
1458 .f16,1347 .f16,
1459 .f32,1348 .f32,
...@@ -1509,12 +1398,10 @@ pub const Type = struct {...@@ -1509,12 +1398,10 @@ pub const Type = struct {
1509 };1398 };
1510 return struct_obj.layout != .Auto;1399 return struct_obj.layout != .Auto;
1511 },1400 },
1512 .anon_struct_type => false,
1513 .union_type => |union_type| switch (union_type.runtime_tag) {1401 .union_type => |union_type| switch (union_type.runtime_tag) {
1514 .none, .safety => mod.unionPtr(union_type.index).layout != .Auto,1402 .none, .safety => mod.unionPtr(union_type.index).layout != .Auto,
1515 .tagged => false,1403 .tagged => false,
1516 },1404 },
1517 .opaque_type => false,
1518 .enum_type => |enum_type| switch (enum_type.tag_mode) {1405 .enum_type => |enum_type| switch (enum_type.tag_mode) {
1519 .auto => false,1406 .auto => false,
1520 .explicit, .nonexhaustive => true,1407 .explicit, .nonexhaustive => true,
...@@ -1546,7 +1433,7 @@ pub const Type = struct {...@@ -1546,7 +1433,7 @@ pub const Type = struct {
1546 pub fn isFnOrHasRuntimeBits(ty: Type, mod: *Module) bool {1433 pub fn isFnOrHasRuntimeBits(ty: Type, mod: *Module) bool {
1547 switch (ty.zigTypeTag(mod)) {1434 switch (ty.zigTypeTag(mod)) {
1548 .Fn => {1435 .Fn => {
1549 const fn_info = ty.fnInfo();1436 const fn_info = mod.typeToFunc(ty).?;
1550 if (fn_info.is_generic) return false;1437 if (fn_info.is_generic) return false;
1551 if (fn_info.is_var_args) return true;1438 if (fn_info.is_var_args) return true;
1552 switch (fn_info.cc) {1439 switch (fn_info.cc) {
...@@ -1555,7 +1442,7 @@ pub const Type = struct {...@@ -1555,7 +1442,7 @@ pub const Type = struct {
1555 .Inline => return false,1442 .Inline => return false,
1556 else => {},1443 else => {},
1557 }1444 }
1558 if (fn_info.return_type.comptimeOnly(mod)) return false;1445 if (fn_info.return_type.toType().comptimeOnly(mod)) return false;
1559 return true;1446 return true;
1560 },1447 },
1561 else => return ty.hasRuntimeBits(mod),1448 else => return ty.hasRuntimeBits(mod),
...@@ -1707,13 +1594,6 @@ pub const Type = struct {...@@ -1707,13 +1594,6 @@ pub const Type = struct {
1707 switch (ty.ip_index) {1594 switch (ty.ip_index) {
1708 .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = 0 },1595 .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = 0 },
1709 .none => switch (ty.tag()) {1596 .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
1717 .pointer,1597 .pointer,
1718 .anyframe_T,1598 .anyframe_T,
1719 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },1599 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
...@@ -1753,6 +1633,13 @@ pub const Type = struct {...@@ -1753,6 +1633,13 @@ pub const Type = struct {
17531633
1754 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),1634 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
1755 .error_union_type => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),1635 .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
1756 .simple_type => |t| switch (t) {1643 .simple_type => |t| switch (t) {
1757 .bool,1644 .bool,
1758 .atomic_order,1645 .atomic_order,
...@@ -2086,7 +1973,6 @@ pub const Type = struct {...@@ -2086,7 +1973,6 @@ pub const Type = struct {
2086 .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 },1973 .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 },
20871974
2088 .none => switch (ty.tag()) {1975 .none => switch (ty.tag()) {
2089 .function => unreachable, // represents machine code; not a pointer
2090 .inferred_alloc_const => unreachable,1976 .inferred_alloc_const => unreachable,
2091 .inferred_alloc_mut => unreachable,1977 .inferred_alloc_mut => unreachable,
20921978
...@@ -2187,6 +2073,7 @@ pub const Type = struct {...@@ -2187,6 +2073,7 @@ pub const Type = struct {
21872073
2188 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),2074 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
2189 .error_union_type => @panic("TODO"),2075 .error_union_type => @panic("TODO"),
2076 .func_type => unreachable, // represents machine code; not a pointer
2190 .simple_type => |t| switch (t) {2077 .simple_type => |t| switch (t) {
2191 .bool,2078 .bool,
2192 .atomic_order,2079 .atomic_order,
...@@ -2408,7 +2295,6 @@ pub const Type = struct {...@@ -2408,7 +2295,6 @@ pub const Type = struct {
24082295
2409 switch (ty.ip_index) {2296 switch (ty.ip_index) {
2410 .none => switch (ty.tag()) {2297 .none => switch (ty.tag()) {
2411 .function => unreachable, // represents machine code; not a pointer
2412 .inferred_alloc_const => unreachable,2298 .inferred_alloc_const => unreachable,
2413 .inferred_alloc_mut => unreachable,2299 .inferred_alloc_mut => unreachable,
24142300
...@@ -2453,6 +2339,7 @@ pub const Type = struct {...@@ -2453,6 +2339,7 @@ pub const Type = struct {
2453 },2339 },
2454 .opt_type => @panic("TODO"),2340 .opt_type => @panic("TODO"),
2455 .error_union_type => @panic("TODO"),2341 .error_union_type => @panic("TODO"),
2342 .func_type => unreachable, // represents machine code; not a pointer
2456 .simple_type => |t| switch (t) {2343 .simple_type => |t| switch (t) {
2457 .f16 => return 16,2344 .f16 => return 16,
2458 .f32 => return 32,2345 .f32 => return 32,
...@@ -3271,6 +3158,7 @@ pub const Type = struct {...@@ -3271,6 +3158,7 @@ pub const Type = struct {
32713158
3272 .opt_type => unreachable,3159 .opt_type => unreachable,
3273 .error_union_type => unreachable,3160 .error_union_type => unreachable,
3161 .func_type => unreachable,
3274 .simple_type => unreachable, // handled via Index enum tag above3162 .simple_type => unreachable, // handled via Index enum tag above
32753163
3276 .union_type => unreachable,3164 .union_type => unreachable,
...@@ -3356,54 +3244,22 @@ pub const Type = struct {...@@ -3356,54 +3244,22 @@ pub const Type = struct {
3356 };3244 };
3357 }3245 }
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
3383 /// Asserts the type is a function or a function pointer.3247 /// Asserts the type is a function or a function pointer.
3384 pub fn fnReturnType(ty: Type) Type {3248 pub fn fnReturnType(ty: Type, mod: *Module) Type {
3385 const fn_ty = switch (ty.tag()) {3249 return fnReturnTypeIp(ty, mod.intern_pool);
3386 .pointer => ty.castTag(.pointer).?.data.pointee_type,
3387 .function => ty,
3388 else => unreachable,
3389 };
3390 return fn_ty.castTag(.function).?.data.return_type;
3391 }3250 }
33923251
3393 /// Asserts the type is a function.3252 pub fn fnReturnTypeIp(ty: Type, ip: InternPool) Type {
3394 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {3253 return switch (ip.indexToKey(ty.ip_index)) {
3395 return self.castTag(.function).?.data.cc;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();
3396 }3258 }
33973259
3398 /// Asserts the type is a function.3260 /// Asserts the type is a function.
3399 pub fn fnCallingConventionAllowsZigTypes(target: Target, cc: std.builtin.CallingConvention) bool {3261 pub fn fnCallingConvention(ty: Type, mod: *Module) std.builtin.CallingConvention {
3400 return switch (cc) {3262 return mod.intern_pool.indexToKey(ty.ip_index).func_type.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 };
3407 }3263 }
34083264
3409 pub fn isValidParamType(self: Type, mod: *const Module) bool {3265 pub fn isValidParamType(self: Type, mod: *const Module) bool {
...@@ -3421,12 +3277,8 @@ pub const Type = struct {...@@ -3421,12 +3277,8 @@ pub const Type = struct {
3421 }3277 }
34223278
3423 /// Asserts the type is a function.3279 /// Asserts the type is a function.
3424 pub fn fnIsVarArgs(self: Type) bool {3280 pub fn fnIsVarArgs(ty: Type, mod: *Module) bool {
3425 return self.castTag(.function).?.data.is_var_args;3281 return mod.intern_pool.indexToKey(ty.ip_index).func_type.is_var_args;
3426 }
3427
3428 pub fn fnInfo(ty: Type) Payload.Function.Data {
3429 return ty.castTag(.function).?.data;
3430 }3282 }
34313283
3432 pub fn isNumeric(ty: Type, mod: *const Module) bool {3284 pub fn isNumeric(ty: Type, mod: *const Module) bool {
...@@ -3474,7 +3326,6 @@ pub const Type = struct {...@@ -3474,7 +3326,6 @@ pub const Type = struct {
3474 .error_set_single,3326 .error_set_single,
3475 .error_set,3327 .error_set,
3476 .error_set_merged,3328 .error_set_merged,
3477 .function,
3478 .error_set_inferred,3329 .error_set_inferred,
3479 .anyframe_T,3330 .anyframe_T,
3480 .pointer,3331 .pointer,
...@@ -3500,7 +3351,12 @@ pub const Type = struct {...@@ -3500,7 +3351,12 @@ pub const Type = struct {
3500 return null;3351 return null;
3501 }3352 }
3502 },3353 },
3503 .ptr_type => return null,3354
3355 .ptr_type,
3356 .error_union_type,
3357 .func_type,
3358 => return null,
3359
3504 .array_type => |array_type| {3360 .array_type => |array_type| {
3505 if (array_type.len == 0)3361 if (array_type.len == 0)
3506 return Value.initTag(.empty_array);3362 return Value.initTag(.empty_array);
...@@ -3514,13 +3370,13 @@ pub const Type = struct {...@@ -3514,13 +3370,13 @@ pub const Type = struct {
3514 return null;3370 return null;
3515 },3371 },
3516 .opt_type => |child| {3372 .opt_type => |child| {
3517 if (child.toType().isNoReturn()) {3373 if (child == .noreturn_type) {
3518 return Value.null;3374 return try mod.nullValue(ty);
3519 } else {3375 } else {
3520 return null;3376 return null;
3521 }3377 }
3522 },3378 },
3523 .error_union_type => return null,3379
3524 .simple_type => |t| switch (t) {3380 .simple_type => |t| switch (t) {
3525 .f16,3381 .f16,
3526 .f32,3382 .f32,
...@@ -3682,9 +3538,6 @@ pub const Type = struct {...@@ -3682,9 +3538,6 @@ pub const Type = struct {
3682 .error_set_merged,3538 .error_set_merged,
3683 => false,3539 => false,
36843540
3685 // These are function bodies, not function pointers.
3686 .function => true,
3687
3688 .inferred_alloc_mut => unreachable,3541 .inferred_alloc_mut => unreachable,
3689 .inferred_alloc_const => unreachable,3542 .inferred_alloc_const => unreachable,
36903543
...@@ -3721,6 +3574,9 @@ pub const Type = struct {...@@ -3721,6 +3574,9 @@ pub const Type = struct {
3721 .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod),3574 .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod),
3722 .opt_type => |child| child.toType().comptimeOnly(mod),3575 .opt_type => |child| child.toType().comptimeOnly(mod),
3723 .error_union_type => |error_union_type| error_union_type.payload_type.toType().comptimeOnly(mod),3576 .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
3724 .simple_type => |t| switch (t) {3580 .simple_type => |t| switch (t) {
3725 .f16,3581 .f16,
3726 .f32,3582 .f32,
...@@ -4367,6 +4223,10 @@ pub const Type = struct {...@@ -4367,6 +4223,10 @@ pub const Type = struct {
4367 return ty.ip_index == .generic_poison_type;4223 return ty.ip_index == .generic_poison_type;
4368 }4224 }
43694225
4226 pub fn isBoundFn(ty: Type) bool {
4227 return ty.ip_index == .none and ty.tag() == .bound_fn;
4228 }
4229
4370 /// This enum does not directly correspond to `std.builtin.TypeId` because4230 /// This enum does not directly correspond to `std.builtin.TypeId` because
4371 /// it has extra enum tags in it, as a way of using less memory. For example,4231 /// it has extra enum tags in it, as a way of using less memory. For example,
4372 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types4232 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
...@@ -4383,7 +4243,6 @@ pub const Type = struct {...@@ -4383,7 +4243,6 @@ pub const Type = struct {
4383 // After this, the tag requires a payload.4243 // After this, the tag requires a payload.
43844244
4385 pointer,4245 pointer,
4386 function,
4387 optional,4246 optional,
4388 error_union,4247 error_union,
4389 anyframe_T,4248 anyframe_T,
...@@ -4411,7 +4270,6 @@ pub const Type = struct {...@@ -4411,7 +4270,6 @@ pub const Type = struct {
4411 .error_set_merged => Payload.ErrorSetMerged,4270 .error_set_merged => Payload.ErrorSetMerged,
44124271
4413 .pointer => Payload.Pointer,4272 .pointer => Payload.Pointer,
4414 .function => Payload.Function,
4415 .error_union => Payload.ErrorUnion,4273 .error_union => Payload.ErrorUnion,
4416 .error_set_single => Payload.Name,4274 .error_set_single => Payload.Name,
4417 };4275 };
...@@ -4508,36 +4366,6 @@ pub const Type = struct {...@@ -4508,36 +4366,6 @@ pub const Type = struct {
4508 data: u16,4366 data: u16,
4509 };4367 };
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
4541 pub const ErrorSet = struct {4369 pub const ErrorSet = struct {
4542 pub const base_tag = Tag.error_set;4370 pub const base_tag = Tag.error_set;
45434371
src/value.zig+5
...@@ -602,6 +602,11 @@ pub const Value = struct {...@@ -602,6 +602,11 @@ pub const Value = struct {
602 return result;602 return result;
603 }603 }
604604
605 pub fn toIntern(val: Value) InternPool.Index {
606 assert(val.ip_index != .none);
607 return val.ip_index;
608 }
609
605 /// Asserts that the value is representable as a type.610 /// Asserts that the value is representable as a type.
606 pub fn toType(self: Value) Type {611 pub fn toType(self: Value) Type {
607 if (self.ip_index != .none) return self.ip_index.toType();612 if (self.ip_index != .none) return self.ip_index.toType();