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