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