| author | |
| committer | |
| log | 8dbd29cc4588cf118532a816d74b78f62999b636 |
| tree | 0fc19e694d1ad7366dd2b7153dd0d4647d3a9159 |
| parent | 0386730777da858908aaba4ef96fb5bd48faafc9 |
| parent | 6a63c8653ae9121f1cbcee49d32ec4f8deaf0b65 |
| signature |
Legalize: implement scalarization and safety check expansion92 files changed, 4020 insertions(+), 1681 deletions(-)
build.zig+2-2| ... | ... | @@ -437,8 +437,8 @@ pub fn build(b: *std.Build) !void { |
| 437 | 437 | .skip_non_native = skip_non_native, |
| 438 | 438 | .skip_libc = skip_libc, |
| 439 | 439 | .use_llvm = use_llvm, |
| 440 | // 2262585344 was observed on an x86_64-linux-gnu host. | |
| 441 | .max_rss = 2488843878, | |
| 440 | // 2520100864 was observed on an x86_64-linux-gnu host. | |
| 441 | .max_rss = 2772110950, | |
| 442 | 442 | })); |
| 443 | 443 | |
| 444 | 444 | test_modules_step.dependOn(tests.addModuleTests(b, .{ |
doc/langref/test_intCast_builtin.zig+1-1| ... | ... | @@ -5,4 +5,4 @@ test "integer cast panic" { |
| 5 | 5 | _ = b; |
| 6 | 6 | } |
| 7 | 7 | |
| 8 | // test_error=cast truncated bits | |
| 8 | // test_error=integer does not fit in destination type |
lib/std/Target.zig+6-21| ... | ... | @@ -1246,11 +1246,7 @@ pub const Cpu = struct { |
| 1246 | 1246 | |
| 1247 | 1247 | /// Adds the specified feature set but not its dependencies. |
| 1248 | 1248 | pub fn addFeatureSet(set: *Set, other_set: Set) void { |
| 1249 | if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff) { | |
| 1250 | for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* |= other_set_int; | |
| 1251 | } else { | |
| 1252 | set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints); | |
| 1253 | } | |
| 1249 | set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints); | |
| 1254 | 1250 | } |
| 1255 | 1251 | |
| 1256 | 1252 | /// Removes the specified feature but not its dependents. |
| ... | ... | @@ -1262,11 +1258,7 @@ pub const Cpu = struct { |
| 1262 | 1258 | |
| 1263 | 1259 | /// Removes the specified feature but not its dependents. |
| 1264 | 1260 | pub fn removeFeatureSet(set: *Set, other_set: Set) void { |
| 1265 | if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff) { | |
| 1266 | for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* &= ~other_set_int; | |
| 1267 | } else { | |
| 1268 | set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints); | |
| 1269 | } | |
| 1261 | set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints); | |
| 1270 | 1262 | } |
| 1271 | 1263 | |
| 1272 | 1264 | pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void { |
| ... | ... | @@ -1295,17 +1287,10 @@ pub const Cpu = struct { |
| 1295 | 1287 | } |
| 1296 | 1288 | |
| 1297 | 1289 | pub fn isSuperSetOf(set: Set, other_set: Set) bool { |
| 1298 | if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff) { | |
| 1299 | var result = true; | |
| 1300 | for (&set.ints, other_set.ints) |*set_int, other_set_int| | |
| 1301 | result = result and (set_int.* & other_set_int) == other_set_int; | |
| 1302 | return result; | |
| 1303 | } else { | |
| 1304 | const V = @Vector(usize_count, usize); | |
| 1305 | const set_v: V = set.ints; | |
| 1306 | const other_v: V = other_set.ints; | |
| 1307 | return @reduce(.And, (set_v & other_v) == other_v); | |
| 1308 | } | |
| 1290 | const V = @Vector(usize_count, usize); | |
| 1291 | const set_v: V = set.ints; | |
| 1292 | const other_v: V = other_set.ints; | |
| 1293 | return @reduce(.And, (set_v & other_v) == other_v); | |
| 1309 | 1294 | } |
| 1310 | 1295 | }; |
| 1311 | 1296 |
lib/std/array_hash_map.zig+4-13| ... | ... | @@ -889,19 +889,10 @@ pub fn ArrayHashMapUnmanaged( |
| 889 | 889 | self.pointer_stability.lock(); |
| 890 | 890 | defer self.pointer_stability.unlock(); |
| 891 | 891 | |
| 892 | if (new_capacity <= linear_scan_max) { | |
| 893 | try self.entries.ensureTotalCapacity(gpa, new_capacity); | |
| 894 | return; | |
| 895 | } | |
| 896 | ||
| 897 | if (self.index_header) |header| { | |
| 898 | if (new_capacity <= header.capacity()) { | |
| 899 | try self.entries.ensureTotalCapacity(gpa, new_capacity); | |
| 900 | return; | |
| 901 | } | |
| 902 | } | |
| 903 | ||
| 904 | 892 | try self.entries.ensureTotalCapacity(gpa, new_capacity); |
| 893 | if (new_capacity <= linear_scan_max) return; | |
| 894 | if (self.index_header) |header| if (new_capacity <= header.capacity()) return; | |
| 895 | ||
| 905 | 896 | const new_bit_index = try IndexHeader.findBitIndex(new_capacity); |
| 906 | 897 | const new_header = try IndexHeader.alloc(gpa, new_bit_index); |
| 907 | 898 | |
| ... | ... | @@ -2116,7 +2107,7 @@ const IndexHeader = struct { |
| 2116 | 2107 | |
| 2117 | 2108 | fn findBitIndex(desired_capacity: usize) Allocator.Error!u8 { |
| 2118 | 2109 | if (desired_capacity > max_capacity) return error.OutOfMemory; |
| 2119 | var new_bit_index = @as(u8, @intCast(std.math.log2_int_ceil(usize, desired_capacity))); | |
| 2110 | var new_bit_index: u8 = @intCast(std.math.log2_int_ceil(usize, desired_capacity)); | |
| 2120 | 2111 | if (desired_capacity > index_capacities[new_bit_index]) new_bit_index += 1; |
| 2121 | 2112 | if (new_bit_index < min_bit_index) new_bit_index = min_bit_index; |
| 2122 | 2113 | assert(desired_capacity <= index_capacities[new_bit_index]); |
lib/std/crypto/chacha20.zig+3-6| ... | ... | @@ -499,15 +499,12 @@ fn ChaChaNonVecImpl(comptime rounds_nb: usize) type { |
| 499 | 499 | fn ChaChaImpl(comptime rounds_nb: usize) type { |
| 500 | 500 | switch (builtin.cpu.arch) { |
| 501 | 501 | .x86_64 => { |
| 502 | const has_avx2 = std.Target.x86.featureSetHas(builtin.cpu.features, .avx2); | |
| 503 | const has_avx512f = std.Target.x86.featureSetHas(builtin.cpu.features, .avx512f); | |
| 504 | if (builtin.zig_backend != .stage2_x86_64 and has_avx512f) return ChaChaVecImpl(rounds_nb, 4); | |
| 505 | if (has_avx2) return ChaChaVecImpl(rounds_nb, 2); | |
| 502 | if (builtin.zig_backend != .stage2_x86_64 and std.Target.x86.featureSetHas(builtin.cpu.features, .avx512f)) return ChaChaVecImpl(rounds_nb, 4); | |
| 503 | if (std.Target.x86.featureSetHas(builtin.cpu.features, .avx2)) return ChaChaVecImpl(rounds_nb, 2); | |
| 506 | 504 | return ChaChaVecImpl(rounds_nb, 1); |
| 507 | 505 | }, |
| 508 | 506 | .aarch64 => { |
| 509 | const has_neon = std.Target.aarch64.featureSetHas(builtin.cpu.features, .neon); | |
| 510 | if (has_neon) return ChaChaVecImpl(rounds_nb, 4); | |
| 507 | if (builtin.zig_backend != .stage2_aarch64 and std.Target.aarch64.featureSetHas(builtin.cpu.features, .neon)) return ChaChaVecImpl(rounds_nb, 4); | |
| 511 | 508 | return ChaChaNonVecImpl(rounds_nb); |
| 512 | 509 | }, |
| 513 | 510 | else => return ChaChaNonVecImpl(rounds_nb), |
lib/std/debug.zig+2-8| ... | ... | @@ -78,13 +78,9 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type { |
| 78 | 78 | @branchHint(.cold); |
| 79 | 79 | call("invalid error code", @returnAddress()); |
| 80 | 80 | } |
| 81 | pub fn castTruncatedData() noreturn { | |
| 81 | pub fn integerOutOfBounds() noreturn { | |
| 82 | 82 | @branchHint(.cold); |
| 83 | call("integer cast truncated bits", @returnAddress()); | |
| 84 | } | |
| 85 | pub fn negativeToUnsigned() noreturn { | |
| 86 | @branchHint(.cold); | |
| 87 | call("attempt to cast negative value to unsigned integer", @returnAddress()); | |
| 83 | call("integer does not fit in destination type", @returnAddress()); | |
| 88 | 84 | } |
| 89 | 85 | pub fn integerOverflow() noreturn { |
| 90 | 86 | @branchHint(.cold); |
| ... | ... | @@ -126,8 +122,6 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type { |
| 126 | 122 | @branchHint(.cold); |
| 127 | 123 | call("for loop over objects with non-equal lengths", @returnAddress()); |
| 128 | 124 | } |
| 129 | /// Delete after next zig1.wasm update | |
| 130 | pub const memcpyLenMismatch = copyLenMismatch; | |
| 131 | 125 | pub fn copyLenMismatch() noreturn { |
| 132 | 126 | @branchHint(.cold); |
| 133 | 127 | call("source and destination arguments have non-equal lengths", @returnAddress()); |
lib/std/debug/no_panic.zig+1-9| ... | ... | @@ -65,12 +65,7 @@ pub fn invalidErrorCode() noreturn { |
| 65 | 65 | @trap(); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | pub fn castTruncatedData() noreturn { | |
| 69 | @branchHint(.cold); | |
| 70 | @trap(); | |
| 71 | } | |
| 72 | ||
| 73 | pub fn negativeToUnsigned() noreturn { | |
| 68 | pub fn integerOutOfBounds() noreturn { | |
| 74 | 69 | @branchHint(.cold); |
| 75 | 70 | @trap(); |
| 76 | 71 | } |
| ... | ... | @@ -125,9 +120,6 @@ pub fn forLenMismatch() noreturn { |
| 125 | 120 | @trap(); |
| 126 | 121 | } |
| 127 | 122 | |
| 128 | /// Delete after next zig1.wasm update | |
| 129 | pub const memcpyLenMismatch = copyLenMismatch; | |
| 130 | ||
| 131 | 123 | pub fn copyLenMismatch() noreturn { |
| 132 | 124 | @branchHint(.cold); |
| 133 | 125 | @trap(); |
lib/std/debug/simple_panic.zig+2-9| ... | ... | @@ -72,12 +72,8 @@ pub fn invalidErrorCode() noreturn { |
| 72 | 72 | call("invalid error code", null); |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | pub fn castTruncatedData() noreturn { | |
| 76 | call("integer cast truncated bits", null); | |
| 77 | } | |
| 78 | ||
| 79 | pub fn negativeToUnsigned() noreturn { | |
| 80 | call("attempt to cast negative value to unsigned integer", null); | |
| 75 | pub fn integerOutOfBounds() noreturn { | |
| 76 | call("integer does not fit in destination type", null); | |
| 81 | 77 | } |
| 82 | 78 | |
| 83 | 79 | pub fn integerOverflow() noreturn { |
| ... | ... | @@ -120,9 +116,6 @@ pub fn forLenMismatch() noreturn { |
| 120 | 116 | call("for loop over objects with non-equal lengths", null); |
| 121 | 117 | } |
| 122 | 118 | |
| 123 | /// Delete after next zig1.wasm update | |
| 124 | pub const memcpyLenMismatch = copyLenMismatch; | |
| 125 | ||
| 126 | 119 | pub fn copyLenMismatch() noreturn { |
| 127 | 120 | call("source and destination have non-equal lengths", null); |
| 128 | 121 | } |
lib/std/hash/xxhash.zig-3| ... | ... | @@ -780,7 +780,6 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64) |
| 780 | 780 | } |
| 781 | 781 | |
| 782 | 782 | test "xxhash3" { |
| 783 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 784 | 783 | if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23807 |
| 785 | 784 | |
| 786 | 785 | const H = XxHash3; |
| ... | ... | @@ -814,7 +813,6 @@ test "xxhash3" { |
| 814 | 813 | } |
| 815 | 814 | |
| 816 | 815 | test "xxhash3 smhasher" { |
| 817 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 818 | 816 | if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23807 |
| 819 | 817 | |
| 820 | 818 | const Test = struct { |
| ... | ... | @@ -828,7 +826,6 @@ test "xxhash3 smhasher" { |
| 828 | 826 | } |
| 829 | 827 | |
| 830 | 828 | test "xxhash3 iterative api" { |
| 831 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 832 | 829 | if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23807 |
| 833 | 830 | |
| 834 | 831 | const Test = struct { |
lib/std/simd.zig-8| ... | ... | @@ -231,8 +231,6 @@ pub fn extract( |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | 233 | test "vector patterns" { |
| 234 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 235 | ||
| 236 | 234 | const base = @Vector(4, u32){ 10, 20, 30, 40 }; |
| 237 | 235 | const other_base = @Vector(4, u32){ 55, 66, 77, 88 }; |
| 238 | 236 | |
| ... | ... | @@ -302,8 +300,6 @@ pub fn reverseOrder(vec: anytype) @TypeOf(vec) { |
| 302 | 300 | } |
| 303 | 301 | |
| 304 | 302 | test "vector shifting" { |
| 305 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 306 | ||
| 307 | 303 | const base = @Vector(4, u32){ 10, 20, 30, 40 }; |
| 308 | 304 | |
| 309 | 305 | try std.testing.expectEqual([4]u32{ 30, 40, 999, 999 }, shiftElementsLeft(base, 2, 999)); |
| ... | ... | @@ -368,9 +364,6 @@ pub fn countElementsWithValue(vec: anytype, value: std.meta.Child(@TypeOf(vec))) |
| 368 | 364 | } |
| 369 | 365 | |
| 370 | 366 | test "vector searching" { |
| 371 | if (builtin.zig_backend == .stage2_x86_64 and | |
| 372 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3)) return error.SkipZigTest; | |
| 373 | ||
| 374 | 367 | const base = @Vector(8, u32){ 6, 4, 7, 4, 4, 2, 3, 7 }; |
| 375 | 368 | |
| 376 | 369 | try std.testing.expectEqual(@as(?u3, 1), firstIndexOfValue(base, 4)); |
| ... | ... | @@ -462,7 +455,6 @@ pub fn prefixScan(comptime op: std.builtin.ReduceOp, comptime hop: isize, vec: a |
| 462 | 455 | } |
| 463 | 456 | |
| 464 | 457 | test "vector prefix scan" { |
| 465 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 466 | 458 | if ((builtin.cpu.arch == .armeb or builtin.cpu.arch == .thumbeb) and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/22060 |
| 467 | 459 | if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21893 |
| 468 | 460 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
lib/std/zig/AstGen.zig+21-1| ... | ... | @@ -11194,6 +11194,7 @@ fn rvalueInner( |
| 11194 | 11194 | const as_void = @as(u64, @intFromEnum(Zir.Inst.Ref.void_type)) << 32; |
| 11195 | 11195 | const as_comptime_int = @as(u64, @intFromEnum(Zir.Inst.Ref.comptime_int_type)) << 32; |
| 11196 | 11196 | const as_usize = @as(u64, @intFromEnum(Zir.Inst.Ref.usize_type)) << 32; |
| 11197 | const as_u1 = @as(u64, @intFromEnum(Zir.Inst.Ref.u1_type)) << 32; | |
| 11197 | 11198 | const as_u8 = @as(u64, @intFromEnum(Zir.Inst.Ref.u8_type)) << 32; |
| 11198 | 11199 | switch ((@as(u64, @intFromEnum(ty_inst)) << 32) | @as(u64, @intFromEnum(result))) { |
| 11199 | 11200 | as_ty | @intFromEnum(Zir.Inst.Ref.u1_type), |
| ... | ... | @@ -11237,10 +11238,11 @@ fn rvalueInner( |
| 11237 | 11238 | as_ty | @intFromEnum(Zir.Inst.Ref.null_type), |
| 11238 | 11239 | as_ty | @intFromEnum(Zir.Inst.Ref.undefined_type), |
| 11239 | 11240 | as_ty | @intFromEnum(Zir.Inst.Ref.enum_literal_type), |
| 11241 | as_ty | @intFromEnum(Zir.Inst.Ref.ptr_usize_type), | |
| 11242 | as_ty | @intFromEnum(Zir.Inst.Ref.ptr_const_comptime_int_type), | |
| 11240 | 11243 | as_ty | @intFromEnum(Zir.Inst.Ref.manyptr_u8_type), |
| 11241 | 11244 | as_ty | @intFromEnum(Zir.Inst.Ref.manyptr_const_u8_type), |
| 11242 | 11245 | as_ty | @intFromEnum(Zir.Inst.Ref.manyptr_const_u8_sentinel_0_type), |
| 11243 | as_ty | @intFromEnum(Zir.Inst.Ref.single_const_pointer_to_comptime_int_type), | |
| 11244 | 11246 | as_ty | @intFromEnum(Zir.Inst.Ref.slice_const_u8_type), |
| 11245 | 11247 | as_ty | @intFromEnum(Zir.Inst.Ref.slice_const_u8_sentinel_0_type), |
| 11246 | 11248 | as_ty | @intFromEnum(Zir.Inst.Ref.anyerror_void_error_union_type), |
| ... | ... | @@ -11249,27 +11251,45 @@ fn rvalueInner( |
| 11249 | 11251 | as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero), |
| 11250 | 11252 | as_comptime_int | @intFromEnum(Zir.Inst.Ref.one), |
| 11251 | 11253 | as_comptime_int | @intFromEnum(Zir.Inst.Ref.negative_one), |
| 11254 | as_usize | @intFromEnum(Zir.Inst.Ref.undef_usize), | |
| 11252 | 11255 | as_usize | @intFromEnum(Zir.Inst.Ref.zero_usize), |
| 11253 | 11256 | as_usize | @intFromEnum(Zir.Inst.Ref.one_usize), |
| 11257 | as_u1 | @intFromEnum(Zir.Inst.Ref.undef_u1), | |
| 11258 | as_u1 | @intFromEnum(Zir.Inst.Ref.zero_u1), | |
| 11259 | as_u1 | @intFromEnum(Zir.Inst.Ref.one_u1), | |
| 11254 | 11260 | as_u8 | @intFromEnum(Zir.Inst.Ref.zero_u8), |
| 11255 | 11261 | as_u8 | @intFromEnum(Zir.Inst.Ref.one_u8), |
| 11256 | 11262 | as_u8 | @intFromEnum(Zir.Inst.Ref.four_u8), |
| 11263 | as_bool | @intFromEnum(Zir.Inst.Ref.undef_bool), | |
| 11257 | 11264 | as_bool | @intFromEnum(Zir.Inst.Ref.bool_true), |
| 11258 | 11265 | as_bool | @intFromEnum(Zir.Inst.Ref.bool_false), |
| 11259 | 11266 | as_void | @intFromEnum(Zir.Inst.Ref.void_value), |
| 11260 | 11267 | => return result, // type of result is already correct |
| 11261 | 11268 | |
| 11269 | as_bool | @intFromEnum(Zir.Inst.Ref.undef) => return .undef_bool, | |
| 11270 | as_usize | @intFromEnum(Zir.Inst.Ref.undef) => return .undef_usize, | |
| 11271 | as_usize | @intFromEnum(Zir.Inst.Ref.undef_u1) => return .undef_usize, | |
| 11272 | as_u1 | @intFromEnum(Zir.Inst.Ref.undef) => return .undef_u1, | |
| 11273 | ||
| 11262 | 11274 | as_usize | @intFromEnum(Zir.Inst.Ref.zero) => return .zero_usize, |
| 11275 | as_u1 | @intFromEnum(Zir.Inst.Ref.zero) => return .zero_u1, | |
| 11263 | 11276 | as_u8 | @intFromEnum(Zir.Inst.Ref.zero) => return .zero_u8, |
| 11264 | 11277 | as_usize | @intFromEnum(Zir.Inst.Ref.one) => return .one_usize, |
| 11278 | as_u1 | @intFromEnum(Zir.Inst.Ref.one) => return .one_u1, | |
| 11265 | 11279 | as_u8 | @intFromEnum(Zir.Inst.Ref.one) => return .one_u8, |
| 11266 | 11280 | as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero_usize) => return .zero, |
| 11281 | as_u1 | @intFromEnum(Zir.Inst.Ref.zero_usize) => return .zero_u1, | |
| 11267 | 11282 | as_u8 | @intFromEnum(Zir.Inst.Ref.zero_usize) => return .zero_u8, |
| 11268 | 11283 | as_comptime_int | @intFromEnum(Zir.Inst.Ref.one_usize) => return .one, |
| 11284 | as_u1 | @intFromEnum(Zir.Inst.Ref.one_usize) => return .one_u1, | |
| 11269 | 11285 | as_u8 | @intFromEnum(Zir.Inst.Ref.one_usize) => return .one_u8, |
| 11286 | as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero_u1) => return .zero, | |
| 11270 | 11287 | as_comptime_int | @intFromEnum(Zir.Inst.Ref.zero_u8) => return .zero, |
| 11288 | as_usize | @intFromEnum(Zir.Inst.Ref.zero_u1) => return .zero_usize, | |
| 11271 | 11289 | as_usize | @intFromEnum(Zir.Inst.Ref.zero_u8) => return .zero_usize, |
| 11290 | as_comptime_int | @intFromEnum(Zir.Inst.Ref.one_u1) => return .one, | |
| 11272 | 11291 | as_comptime_int | @intFromEnum(Zir.Inst.Ref.one_u8) => return .one, |
| 11292 | as_usize | @intFromEnum(Zir.Inst.Ref.one_u1) => return .one_usize, | |
| 11273 | 11293 | as_usize | @intFromEnum(Zir.Inst.Ref.one_u8) => return .one_usize, |
| 11274 | 11294 | |
| 11275 | 11295 | // Need an explicit type coercion instruction. |
lib/std/zig/Zir.zig+8-2| ... | ... | @@ -2142,7 +2142,7 @@ pub const Inst = struct { |
| 2142 | 2142 | ref_start_index = static_len, |
| 2143 | 2143 | _, |
| 2144 | 2144 | |
| 2145 | pub const static_len = 118; | |
| 2145 | pub const static_len = 124; | |
| 2146 | 2146 | |
| 2147 | 2147 | pub fn toRef(i: Index) Inst.Ref { |
| 2148 | 2148 | return @enumFromInt(@intFromEnum(Index.ref_start_index) + @intFromEnum(i)); |
| ... | ... | @@ -2220,10 +2220,11 @@ pub const Inst = struct { |
| 2220 | 2220 | null_type, |
| 2221 | 2221 | undefined_type, |
| 2222 | 2222 | enum_literal_type, |
| 2223 | ptr_usize_type, | |
| 2224 | ptr_const_comptime_int_type, | |
| 2223 | 2225 | manyptr_u8_type, |
| 2224 | 2226 | manyptr_const_u8_type, |
| 2225 | 2227 | manyptr_const_u8_sentinel_0_type, |
| 2226 | single_const_pointer_to_comptime_int_type, | |
| 2227 | 2228 | slice_const_u8_type, |
| 2228 | 2229 | slice_const_u8_sentinel_0_type, |
| 2229 | 2230 | vector_8_i8_type, |
| ... | ... | @@ -2279,11 +2280,16 @@ pub const Inst = struct { |
| 2279 | 2280 | generic_poison_type, |
| 2280 | 2281 | empty_tuple_type, |
| 2281 | 2282 | undef, |
| 2283 | undef_bool, | |
| 2284 | undef_usize, | |
| 2285 | undef_u1, | |
| 2282 | 2286 | zero, |
| 2283 | 2287 | zero_usize, |
| 2288 | zero_u1, | |
| 2284 | 2289 | zero_u8, |
| 2285 | 2290 | one, |
| 2286 | 2291 | one_usize, |
| 2292 | one_u1, | |
| 2287 | 2293 | one_u8, |
| 2288 | 2294 | four_u8, |
| 2289 | 2295 | negative_one, |
src/Air.zig+144-37| ... | ... | @@ -50,8 +50,6 @@ pub const Inst = struct { |
| 50 | 50 | /// is the same as both operands. |
| 51 | 51 | /// The panic handler function must be populated before lowering AIR |
| 52 | 52 | /// that contains this instruction. |
| 53 | /// This instruction will only be emitted if the backend has the | |
| 54 | /// feature `safety_checked_instructions`. | |
| 55 | 53 | /// Uses the `bin_op` field. |
| 56 | 54 | add_safe, |
| 57 | 55 | /// Float addition. The instruction is allowed to have equal or more |
| ... | ... | @@ -79,8 +77,6 @@ pub const Inst = struct { |
| 79 | 77 | /// is the same as both operands. |
| 80 | 78 | /// The panic handler function must be populated before lowering AIR |
| 81 | 79 | /// that contains this instruction. |
| 82 | /// This instruction will only be emitted if the backend has the | |
| 83 | /// feature `safety_checked_instructions`. | |
| 84 | 80 | /// Uses the `bin_op` field. |
| 85 | 81 | sub_safe, |
| 86 | 82 | /// Float subtraction. The instruction is allowed to have equal or more |
| ... | ... | @@ -108,8 +104,6 @@ pub const Inst = struct { |
| 108 | 104 | /// is the same as both operands. |
| 109 | 105 | /// The panic handler function must be populated before lowering AIR |
| 110 | 106 | /// that contains this instruction. |
| 111 | /// This instruction will only be emitted if the backend has the | |
| 112 | /// feature `safety_checked_instructions`. | |
| 113 | 107 | /// Uses the `bin_op` field. |
| 114 | 108 | mul_safe, |
| 115 | 109 | /// Float multiplication. The instruction is allowed to have equal or more |
| ... | ... | @@ -705,9 +699,21 @@ pub const Inst = struct { |
| 705 | 699 | /// equal to the scalar value. |
| 706 | 700 | /// Uses the `ty_op` field. |
| 707 | 701 | splat, |
| 708 | /// Constructs a vector by selecting elements from `a` and `b` based on `mask`. | |
| 709 | /// Uses the `ty_pl` field with payload `Shuffle`. | |
| 710 | shuffle, | |
| 702 | /// Constructs a vector by selecting elements from a single vector based on a mask. Each | |
| 703 | /// mask element is either an index into the vector, or a comptime-known value, or "undef". | |
| 704 | /// Uses the `ty_pl` field, where the payload index points to: | |
| 705 | /// 1. mask_elem: ShuffleOneMask // for each `mask_len`, which comes from `ty_pl.ty` | |
| 706 | /// 2. operand: Ref // guaranteed not to be an interned value | |
| 707 | /// See `unwrapShuffleOne`. | |
| 708 | shuffle_one, | |
| 709 | /// Constructs a vector by selecting elements from two vectors based on a mask. Each mask | |
| 710 | /// element is either an index into one of the vectors, or "undef". | |
| 711 | /// Uses the `ty_pl` field, where the payload index points to: | |
| 712 | /// 1. mask_elem: ShuffleOneMask // for each `mask_len`, which comes from `ty_pl.ty` | |
| 713 | /// 2. operand_a: Ref // guaranteed not to be an interned value | |
| 714 | /// 3. operand_b: Ref // guaranteed not to be an interned value | |
| 715 | /// See `unwrapShuffleTwo`. | |
| 716 | shuffle_two, | |
| 711 | 717 | /// Constructs a vector element-wise from `a` or `b` based on `pred`. |
| 712 | 718 | /// Uses the `pl_op` field with `pred` as operand, and payload `Bin`. |
| 713 | 719 | select, |
| ... | ... | @@ -1011,10 +1017,11 @@ pub const Inst = struct { |
| 1011 | 1017 | null_type = @intFromEnum(InternPool.Index.null_type), |
| 1012 | 1018 | undefined_type = @intFromEnum(InternPool.Index.undefined_type), |
| 1013 | 1019 | enum_literal_type = @intFromEnum(InternPool.Index.enum_literal_type), |
| 1020 | ptr_usize_type = @intFromEnum(InternPool.Index.ptr_usize_type), | |
| 1021 | ptr_const_comptime_int_type = @intFromEnum(InternPool.Index.ptr_const_comptime_int_type), | |
| 1014 | 1022 | manyptr_u8_type = @intFromEnum(InternPool.Index.manyptr_u8_type), |
| 1015 | 1023 | manyptr_const_u8_type = @intFromEnum(InternPool.Index.manyptr_const_u8_type), |
| 1016 | 1024 | manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type), |
| 1017 | single_const_pointer_to_comptime_int_type = @intFromEnum(InternPool.Index.single_const_pointer_to_comptime_int_type), | |
| 1018 | 1025 | slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type), |
| 1019 | 1026 | slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type), |
| 1020 | 1027 | vector_8_i8_type = @intFromEnum(InternPool.Index.vector_8_i8_type), |
| ... | ... | @@ -1070,11 +1077,16 @@ pub const Inst = struct { |
| 1070 | 1077 | generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type), |
| 1071 | 1078 | empty_tuple_type = @intFromEnum(InternPool.Index.empty_tuple_type), |
| 1072 | 1079 | undef = @intFromEnum(InternPool.Index.undef), |
| 1080 | undef_bool = @intFromEnum(InternPool.Index.undef_bool), | |
| 1081 | undef_usize = @intFromEnum(InternPool.Index.undef_usize), | |
| 1082 | undef_u1 = @intFromEnum(InternPool.Index.undef_u1), | |
| 1073 | 1083 | zero = @intFromEnum(InternPool.Index.zero), |
| 1074 | 1084 | zero_usize = @intFromEnum(InternPool.Index.zero_usize), |
| 1085 | zero_u1 = @intFromEnum(InternPool.Index.zero_u1), | |
| 1075 | 1086 | zero_u8 = @intFromEnum(InternPool.Index.zero_u8), |
| 1076 | 1087 | one = @intFromEnum(InternPool.Index.one), |
| 1077 | 1088 | one_usize = @intFromEnum(InternPool.Index.one_usize), |
| 1089 | one_u1 = @intFromEnum(InternPool.Index.one_u1), | |
| 1078 | 1090 | one_u8 = @intFromEnum(InternPool.Index.one_u8), |
| 1079 | 1091 | four_u8 = @intFromEnum(InternPool.Index.four_u8), |
| 1080 | 1092 | negative_one = @intFromEnum(InternPool.Index.negative_one), |
| ... | ... | @@ -1121,7 +1133,7 @@ pub const Inst = struct { |
| 1121 | 1133 | } |
| 1122 | 1134 | |
| 1123 | 1135 | pub fn toType(ref: Ref) Type { |
| 1124 | return Type.fromInterned(ref.toInterned().?); | |
| 1136 | return .fromInterned(ref.toInterned().?); | |
| 1125 | 1137 | } |
| 1126 | 1138 | }; |
| 1127 | 1139 | |
| ... | ... | @@ -1241,10 +1253,10 @@ pub const CondBr = struct { |
| 1241 | 1253 | else_body_len: u32, |
| 1242 | 1254 | branch_hints: BranchHints, |
| 1243 | 1255 | pub const BranchHints = packed struct(u32) { |
| 1244 | true: std.builtin.BranchHint, | |
| 1245 | false: std.builtin.BranchHint, | |
| 1246 | then_cov: CoveragePoint, | |
| 1247 | else_cov: CoveragePoint, | |
| 1256 | true: std.builtin.BranchHint = .none, | |
| 1257 | false: std.builtin.BranchHint = .none, | |
| 1258 | then_cov: CoveragePoint = .none, | |
| 1259 | else_cov: CoveragePoint = .none, | |
| 1248 | 1260 | _: u24 = 0, |
| 1249 | 1261 | }; |
| 1250 | 1262 | }; |
| ... | ... | @@ -1299,13 +1311,6 @@ pub const FieldParentPtr = struct { |
| 1299 | 1311 | field_index: u32, |
| 1300 | 1312 | }; |
| 1301 | 1313 | |
| 1302 | pub const Shuffle = struct { | |
| 1303 | a: Inst.Ref, | |
| 1304 | b: Inst.Ref, | |
| 1305 | mask: InternPool.Index, | |
| 1306 | mask_len: u32, | |
| 1307 | }; | |
| 1308 | ||
| 1309 | 1314 | pub const VectorCmp = struct { |
| 1310 | 1315 | lhs: Inst.Ref, |
| 1311 | 1316 | rhs: Inst.Ref, |
| ... | ... | @@ -1320,6 +1325,64 @@ pub const VectorCmp = struct { |
| 1320 | 1325 | } |
| 1321 | 1326 | }; |
| 1322 | 1327 | |
| 1328 | /// Used by `Inst.Tag.shuffle_one`. Represents a mask element which either indexes into a | |
| 1329 | /// runtime-known vector, or is a comptime-known value. | |
| 1330 | pub const ShuffleOneMask = packed struct(u32) { | |
| 1331 | index: u31, | |
| 1332 | kind: enum(u1) { elem, value }, | |
| 1333 | pub fn elem(idx: u32) ShuffleOneMask { | |
| 1334 | return .{ .index = @intCast(idx), .kind = .elem }; | |
| 1335 | } | |
| 1336 | pub fn value(val: Value) ShuffleOneMask { | |
| 1337 | return .{ .index = @intCast(@intFromEnum(val.toIntern())), .kind = .value }; | |
| 1338 | } | |
| 1339 | pub const Unwrapped = union(enum) { | |
| 1340 | /// The resulting element is this index into the runtime vector. | |
| 1341 | elem: u32, | |
| 1342 | /// The resulting element is this comptime-known value. | |
| 1343 | /// It is correctly typed. It might be `undefined`. | |
| 1344 | value: InternPool.Index, | |
| 1345 | }; | |
| 1346 | pub fn unwrap(raw: ShuffleOneMask) Unwrapped { | |
| 1347 | return switch (raw.kind) { | |
| 1348 | .elem => .{ .elem = raw.index }, | |
| 1349 | .value => .{ .value = @enumFromInt(raw.index) }, | |
| 1350 | }; | |
| 1351 | } | |
| 1352 | }; | |
| 1353 | ||
| 1354 | /// Used by `Inst.Tag.shuffle_two`. Represents a mask element which either indexes into one | |
| 1355 | /// of two runtime-known vectors, or is undefined. | |
| 1356 | pub const ShuffleTwoMask = enum(u32) { | |
| 1357 | undef = std.math.maxInt(u32), | |
| 1358 | _, | |
| 1359 | pub fn aElem(idx: u32) ShuffleTwoMask { | |
| 1360 | return @enumFromInt(idx << 1); | |
| 1361 | } | |
| 1362 | pub fn bElem(idx: u32) ShuffleTwoMask { | |
| 1363 | return @enumFromInt(idx << 1 | 1); | |
| 1364 | } | |
| 1365 | pub const Unwrapped = union(enum) { | |
| 1366 | /// The resulting element is this index into the first runtime vector. | |
| 1367 | a_elem: u32, | |
| 1368 | /// The resulting element is this index into the second runtime vector. | |
| 1369 | b_elem: u32, | |
| 1370 | /// The resulting element is `undefined`. | |
| 1371 | undef, | |
| 1372 | }; | |
| 1373 | pub fn unwrap(raw: ShuffleTwoMask) Unwrapped { | |
| 1374 | switch (raw) { | |
| 1375 | .undef => return .undef, | |
| 1376 | _ => {}, | |
| 1377 | } | |
| 1378 | const x = @intFromEnum(raw); | |
| 1379 | return switch (@as(u1, @truncate(x))) { | |
| 1380 | 0 => .{ .a_elem = x >> 1 }, | |
| 1381 | 1 => .{ .b_elem = x >> 1 }, | |
| 1382 | }; | |
| 1383 | } | |
| 1384 | }; | |
| 1385 | ||
| 1323 | 1386 | /// Trailing: |
| 1324 | 1387 | /// 0. `Inst.Ref` for every outputs_len |
| 1325 | 1388 | /// 1. `Inst.Ref` for every inputs_len |
| ... | ... | @@ -1393,7 +1456,7 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index { |
| 1393 | 1456 | |
| 1394 | 1457 | pub fn typeOf(air: *const Air, inst: Air.Inst.Ref, ip: *const InternPool) Type { |
| 1395 | 1458 | if (inst.toInterned()) |ip_index| { |
| 1396 | return Type.fromInterned(ip.typeOf(ip_index)); | |
| 1459 | return .fromInterned(ip.typeOf(ip_index)); | |
| 1397 | 1460 | } else { |
| 1398 | 1461 | return air.typeOfIndex(inst.toIndex().?, ip); |
| 1399 | 1462 | } |
| ... | ... | @@ -1483,7 +1546,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1483 | 1546 | .is_non_err_ptr, |
| 1484 | 1547 | .is_named_enum_value, |
| 1485 | 1548 | .error_set_has_value, |
| 1486 | => return Type.bool, | |
| 1549 | => return .bool, | |
| 1487 | 1550 | |
| 1488 | 1551 | .alloc, |
| 1489 | 1552 | .ret_ptr, |
| ... | ... | @@ -1503,7 +1566,6 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1503 | 1566 | .cmpxchg_weak, |
| 1504 | 1567 | .cmpxchg_strong, |
| 1505 | 1568 | .slice, |
| 1506 | .shuffle, | |
| 1507 | 1569 | .aggregate_init, |
| 1508 | 1570 | .union_init, |
| 1509 | 1571 | .field_parent_ptr, |
| ... | ... | @@ -1517,6 +1579,8 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1517 | 1579 | .ptr_sub, |
| 1518 | 1580 | .try_ptr, |
| 1519 | 1581 | .try_ptr_cold, |
| 1582 | .shuffle_one, | |
| 1583 | .shuffle_two, | |
| 1520 | 1584 | => return datas[@intFromEnum(inst)].ty_pl.ty.toType(), |
| 1521 | 1585 | |
| 1522 | 1586 | .not, |
| ... | ... | @@ -1574,7 +1638,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1574 | 1638 | .ret_load, |
| 1575 | 1639 | .unreach, |
| 1576 | 1640 | .trap, |
| 1577 | => return Type.noreturn, | |
| 1641 | => return .noreturn, | |
| 1578 | 1642 | |
| 1579 | 1643 | .breakpoint, |
| 1580 | 1644 | .dbg_stmt, |
| ... | ... | @@ -1597,22 +1661,22 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1597 | 1661 | .set_err_return_trace, |
| 1598 | 1662 | .vector_store_elem, |
| 1599 | 1663 | .c_va_end, |
| 1600 | => return Type.void, | |
| 1664 | => return .void, | |
| 1601 | 1665 | |
| 1602 | 1666 | .slice_len, |
| 1603 | 1667 | .ret_addr, |
| 1604 | 1668 | .frame_addr, |
| 1605 | 1669 | .save_err_return_trace_index, |
| 1606 | => return Type.usize, | |
| 1670 | => return .usize, | |
| 1607 | 1671 | |
| 1608 | .wasm_memory_grow => return Type.isize, | |
| 1609 | .wasm_memory_size => return Type.usize, | |
| 1672 | .wasm_memory_grow => return .isize, | |
| 1673 | .wasm_memory_size => return .usize, | |
| 1610 | 1674 | |
| 1611 | .tag_name, .error_name => return Type.slice_const_u8_sentinel_0, | |
| 1675 | .tag_name, .error_name => return .slice_const_u8_sentinel_0, | |
| 1612 | 1676 | |
| 1613 | 1677 | .call, .call_always_tail, .call_never_tail, .call_never_inline => { |
| 1614 | 1678 | const callee_ty = air.typeOf(datas[@intFromEnum(inst)].pl_op.operand, ip); |
| 1615 | return Type.fromInterned(ip.funcTypeReturnType(callee_ty.toIntern())); | |
| 1679 | return .fromInterned(ip.funcTypeReturnType(callee_ty.toIntern())); | |
| 1616 | 1680 | }, |
| 1617 | 1681 | |
| 1618 | 1682 | .slice_elem_val, .ptr_elem_val, .array_elem_val => { |
| ... | ... | @@ -1630,7 +1694,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1630 | 1694 | |
| 1631 | 1695 | .reduce, .reduce_optimized => { |
| 1632 | 1696 | const operand_ty = air.typeOf(datas[@intFromEnum(inst)].reduce.operand, ip); |
| 1633 | return Type.fromInterned(ip.indexToKey(operand_ty.ip_index).vector_type.child); | |
| 1697 | return .fromInterned(ip.indexToKey(operand_ty.ip_index).vector_type.child); | |
| 1634 | 1698 | }, |
| 1635 | 1699 | |
| 1636 | 1700 | .mul_add => return air.typeOf(datas[@intFromEnum(inst)].pl_op.operand, ip), |
| ... | ... | @@ -1641,7 +1705,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1641 | 1705 | |
| 1642 | 1706 | .@"try", .try_cold => { |
| 1643 | 1707 | const err_union_ty = air.typeOf(datas[@intFromEnum(inst)].pl_op.operand, ip); |
| 1644 | return Type.fromInterned(ip.indexToKey(err_union_ty.ip_index).error_union_type.payload_type); | |
| 1708 | return .fromInterned(ip.indexToKey(err_union_ty.ip_index).error_union_type.payload_type); | |
| 1645 | 1709 | }, |
| 1646 | 1710 | |
| 1647 | 1711 | .tlv_dllimport_ptr => return .fromInterned(datas[@intFromEnum(inst)].ty_nav.ty), |
| ... | ... | @@ -1649,7 +1713,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) |
| 1649 | 1713 | .work_item_id, |
| 1650 | 1714 | .work_group_size, |
| 1651 | 1715 | .work_group_id, |
| 1652 | => return Type.u32, | |
| 1716 | => return .u32, | |
| 1653 | 1717 | |
| 1654 | 1718 | .inferred_alloc => unreachable, |
| 1655 | 1719 | .inferred_alloc_comptime => unreachable, |
| ... | ... | @@ -1696,7 +1760,7 @@ pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref { |
| 1696 | 1760 | /// Returns `null` if runtime-known. |
| 1697 | 1761 | pub fn value(air: Air, inst: Inst.Ref, pt: Zcu.PerThread) !?Value { |
| 1698 | 1762 | if (inst.toInterned()) |ip_index| { |
| 1699 | return Value.fromInterned(ip_index); | |
| 1763 | return .fromInterned(ip_index); | |
| 1700 | 1764 | } |
| 1701 | 1765 | const index = inst.toIndex().?; |
| 1702 | 1766 | return air.typeOfIndex(index, &pt.zcu.intern_pool).onePossibleValue(pt); |
| ... | ... | @@ -1903,7 +1967,8 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { |
| 1903 | 1967 | .reduce, |
| 1904 | 1968 | .reduce_optimized, |
| 1905 | 1969 | .splat, |
| 1906 | .shuffle, | |
| 1970 | .shuffle_one, | |
| 1971 | .shuffle_two, | |
| 1907 | 1972 | .select, |
| 1908 | 1973 | .is_named_enum_value, |
| 1909 | 1974 | .tag_name, |
| ... | ... | @@ -2030,6 +2095,48 @@ pub fn unwrapSwitch(air: *const Air, switch_inst: Inst.Index) UnwrappedSwitch { |
| 2030 | 2095 | }; |
| 2031 | 2096 | } |
| 2032 | 2097 | |
| 2098 | pub fn unwrapShuffleOne(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index) struct { | |
| 2099 | result_ty: Type, | |
| 2100 | operand: Inst.Ref, | |
| 2101 | mask: []const ShuffleOneMask, | |
| 2102 | } { | |
| 2103 | const inst = air.instructions.get(@intFromEnum(inst_index)); | |
| 2104 | switch (inst.tag) { | |
| 2105 | .shuffle_one => {}, | |
| 2106 | else => unreachable, // assertion failure | |
| 2107 | } | |
| 2108 | const result_ty: Type = .fromInterned(inst.data.ty_pl.ty.toInterned().?); | |
| 2109 | const mask_len: u32 = result_ty.vectorLen(zcu); | |
| 2110 | const extra_idx = inst.data.ty_pl.payload; | |
| 2111 | return .{ | |
| 2112 | .result_ty = result_ty, | |
| 2113 | .operand = @enumFromInt(air.extra.items[extra_idx + mask_len]), | |
| 2114 | .mask = @ptrCast(air.extra.items[extra_idx..][0..mask_len]), | |
| 2115 | }; | |
| 2116 | } | |
| 2117 | ||
| 2118 | pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index) struct { | |
| 2119 | result_ty: Type, | |
| 2120 | operand_a: Inst.Ref, | |
| 2121 | operand_b: Inst.Ref, | |
| 2122 | mask: []const ShuffleTwoMask, | |
| 2123 | } { | |
| 2124 | const inst = air.instructions.get(@intFromEnum(inst_index)); | |
| 2125 | switch (inst.tag) { | |
| 2126 | .shuffle_two => {}, | |
| 2127 | else => unreachable, // assertion failure | |
| 2128 | } | |
| 2129 | const result_ty: Type = .fromInterned(inst.data.ty_pl.ty.toInterned().?); | |
| 2130 | const mask_len: u32 = result_ty.vectorLen(zcu); | |
| 2131 | const extra_idx = inst.data.ty_pl.payload; | |
| 2132 | return .{ | |
| 2133 | .result_ty = result_ty, | |
| 2134 | .operand_a = @enumFromInt(air.extra.items[extra_idx + mask_len + 0]), | |
| 2135 | .operand_b = @enumFromInt(air.extra.items[extra_idx + mask_len + 1]), | |
| 2136 | .mask = @ptrCast(air.extra.items[extra_idx..][0..mask_len]), | |
| 2137 | }; | |
| 2138 | } | |
| 2139 | ||
| 2033 | 2140 | pub const typesFullyResolved = types_resolved.typesFullyResolved; |
| 2034 | 2141 | pub const typeFullyResolved = types_resolved.checkType; |
| 2035 | 2142 | pub const valFullyResolved = types_resolved.checkVal; |
src/Air/Legalize.zig+1710-120| ... | ... | @@ -1,147 +1,1737 @@ |
| 1 | zcu: *const Zcu, | |
| 2 | air: Air, | |
| 3 | features: std.enums.EnumSet(Feature), | |
| 1 | pt: Zcu.PerThread, | |
| 2 | air_instructions: std.MultiArrayList(Air.Inst), | |
| 3 | air_extra: std.ArrayListUnmanaged(u32), | |
| 4 | features: *const Features, | |
| 4 | 5 | |
| 5 | 6 | pub const Feature = enum { |
| 7 | scalarize_add, | |
| 8 | scalarize_add_safe, | |
| 9 | scalarize_add_optimized, | |
| 10 | scalarize_add_wrap, | |
| 11 | scalarize_add_sat, | |
| 12 | scalarize_sub, | |
| 13 | scalarize_sub_safe, | |
| 14 | scalarize_sub_optimized, | |
| 15 | scalarize_sub_wrap, | |
| 16 | scalarize_sub_sat, | |
| 17 | scalarize_mul, | |
| 18 | scalarize_mul_safe, | |
| 19 | scalarize_mul_optimized, | |
| 20 | scalarize_mul_wrap, | |
| 21 | scalarize_mul_sat, | |
| 22 | scalarize_div_float, | |
| 23 | scalarize_div_float_optimized, | |
| 24 | scalarize_div_trunc, | |
| 25 | scalarize_div_trunc_optimized, | |
| 26 | scalarize_div_floor, | |
| 27 | scalarize_div_floor_optimized, | |
| 28 | scalarize_div_exact, | |
| 29 | scalarize_div_exact_optimized, | |
| 30 | scalarize_rem, | |
| 31 | scalarize_rem_optimized, | |
| 32 | scalarize_mod, | |
| 33 | scalarize_mod_optimized, | |
| 34 | scalarize_max, | |
| 35 | scalarize_min, | |
| 36 | scalarize_add_with_overflow, | |
| 37 | scalarize_sub_with_overflow, | |
| 38 | scalarize_mul_with_overflow, | |
| 39 | scalarize_shl_with_overflow, | |
| 40 | scalarize_bit_and, | |
| 41 | scalarize_bit_or, | |
| 42 | scalarize_shr, | |
| 43 | scalarize_shr_exact, | |
| 44 | scalarize_shl, | |
| 45 | scalarize_shl_exact, | |
| 46 | scalarize_shl_sat, | |
| 47 | scalarize_xor, | |
| 48 | scalarize_not, | |
| 49 | scalarize_bitcast, | |
| 50 | scalarize_clz, | |
| 51 | scalarize_ctz, | |
| 52 | scalarize_popcount, | |
| 53 | scalarize_byte_swap, | |
| 54 | scalarize_bit_reverse, | |
| 55 | scalarize_sqrt, | |
| 56 | scalarize_sin, | |
| 57 | scalarize_cos, | |
| 58 | scalarize_tan, | |
| 59 | scalarize_exp, | |
| 60 | scalarize_exp2, | |
| 61 | scalarize_log, | |
| 62 | scalarize_log2, | |
| 63 | scalarize_log10, | |
| 64 | scalarize_abs, | |
| 65 | scalarize_floor, | |
| 66 | scalarize_ceil, | |
| 67 | scalarize_round, | |
| 68 | scalarize_trunc_float, | |
| 69 | scalarize_neg, | |
| 70 | scalarize_neg_optimized, | |
| 71 | scalarize_cmp_vector, | |
| 72 | scalarize_cmp_vector_optimized, | |
| 73 | scalarize_fptrunc, | |
| 74 | scalarize_fpext, | |
| 75 | scalarize_intcast, | |
| 76 | scalarize_intcast_safe, | |
| 77 | scalarize_trunc, | |
| 78 | scalarize_int_from_float, | |
| 79 | scalarize_int_from_float_optimized, | |
| 80 | scalarize_float_from_int, | |
| 81 | scalarize_shuffle_one, | |
| 82 | scalarize_shuffle_two, | |
| 83 | scalarize_select, | |
| 84 | scalarize_mul_add, | |
| 85 | ||
| 6 | 86 | /// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs) |
| 7 | remove_shift_vector_rhs_splat, | |
| 87 | unsplat_shift_rhs, | |
| 8 | 88 | /// Legalize reduce of a one element vector to a bitcast |
| 9 | 89 | reduce_one_elem_to_bitcast, |
| 90 | ||
| 91 | /// Replace `intcast_safe` with an explicit safety check which `call`s the panic function on failure. | |
| 92 | /// Not compatible with `scalarize_intcast_safe`. | |
| 93 | expand_intcast_safe, | |
| 94 | /// Replace `add_safe` with an explicit safety check which `call`s the panic function on failure. | |
| 95 | /// Not compatible with `scalarize_add_safe`. | |
| 96 | expand_add_safe, | |
| 97 | /// Replace `sub_safe` with an explicit safety check which `call`s the panic function on failure. | |
| 98 | /// Not compatible with `scalarize_sub_safe`. | |
| 99 | expand_sub_safe, | |
| 100 | /// Replace `mul_safe` with an explicit safety check which `call`s the panic function on failure. | |
| 101 | /// Not compatible with `scalarize_mul_safe`. | |
| 102 | expand_mul_safe, | |
| 103 | ||
| 104 | fn scalarize(tag: Air.Inst.Tag) Feature { | |
| 105 | return switch (tag) { | |
| 106 | else => unreachable, | |
| 107 | .add => .scalarize_add, | |
| 108 | .add_safe => .scalarize_add_safe, | |
| 109 | .add_optimized => .scalarize_add_optimized, | |
| 110 | .add_wrap => .scalarize_add_wrap, | |
| 111 | .add_sat => .scalarize_add_sat, | |
| 112 | .sub => .scalarize_sub, | |
| 113 | .sub_safe => .scalarize_sub_safe, | |
| 114 | .sub_optimized => .scalarize_sub_optimized, | |
| 115 | .sub_wrap => .scalarize_sub_wrap, | |
| 116 | .sub_sat => .scalarize_sub_sat, | |
| 117 | .mul => .scalarize_mul, | |
| 118 | .mul_safe => .scalarize_mul_safe, | |
| 119 | .mul_optimized => .scalarize_mul_optimized, | |
| 120 | .mul_wrap => .scalarize_mul_wrap, | |
| 121 | .mul_sat => .scalarize_mul_sat, | |
| 122 | .div_float => .scalarize_div_float, | |
| 123 | .div_float_optimized => .scalarize_div_float_optimized, | |
| 124 | .div_trunc => .scalarize_div_trunc, | |
| 125 | .div_trunc_optimized => .scalarize_div_trunc_optimized, | |
| 126 | .div_floor => .scalarize_div_floor, | |
| 127 | .div_floor_optimized => .scalarize_div_floor_optimized, | |
| 128 | .div_exact => .scalarize_div_exact, | |
| 129 | .div_exact_optimized => .scalarize_div_exact_optimized, | |
| 130 | .rem => .scalarize_rem, | |
| 131 | .rem_optimized => .scalarize_rem_optimized, | |
| 132 | .mod => .scalarize_mod, | |
| 133 | .mod_optimized => .scalarize_mod_optimized, | |
| 134 | .max => .scalarize_max, | |
| 135 | .min => .scalarize_min, | |
| 136 | .add_with_overflow => .scalarize_add_with_overflow, | |
| 137 | .sub_with_overflow => .scalarize_sub_with_overflow, | |
| 138 | .mul_with_overflow => .scalarize_mul_with_overflow, | |
| 139 | .shl_with_overflow => .scalarize_shl_with_overflow, | |
| 140 | .bit_and => .scalarize_bit_and, | |
| 141 | .bit_or => .scalarize_bit_or, | |
| 142 | .shr => .scalarize_shr, | |
| 143 | .shr_exact => .scalarize_shr_exact, | |
| 144 | .shl => .scalarize_shl, | |
| 145 | .shl_exact => .scalarize_shl_exact, | |
| 146 | .shl_sat => .scalarize_shl_sat, | |
| 147 | .xor => .scalarize_xor, | |
| 148 | .not => .scalarize_not, | |
| 149 | .bitcast => .scalarize_bitcast, | |
| 150 | .clz => .scalarize_clz, | |
| 151 | .ctz => .scalarize_ctz, | |
| 152 | .popcount => .scalarize_popcount, | |
| 153 | .byte_swap => .scalarize_byte_swap, | |
| 154 | .bit_reverse => .scalarize_bit_reverse, | |
| 155 | .sqrt => .scalarize_sqrt, | |
| 156 | .sin => .scalarize_sin, | |
| 157 | .cos => .scalarize_cos, | |
| 158 | .tan => .scalarize_tan, | |
| 159 | .exp => .scalarize_exp, | |
| 160 | .exp2 => .scalarize_exp2, | |
| 161 | .log => .scalarize_log, | |
| 162 | .log2 => .scalarize_log2, | |
| 163 | .log10 => .scalarize_log10, | |
| 164 | .abs => .scalarize_abs, | |
| 165 | .floor => .scalarize_floor, | |
| 166 | .ceil => .scalarize_ceil, | |
| 167 | .round => .scalarize_round, | |
| 168 | .trunc_float => .scalarize_trunc_float, | |
| 169 | .neg => .scalarize_neg, | |
| 170 | .neg_optimized => .scalarize_neg_optimized, | |
| 171 | .cmp_vector => .scalarize_cmp_vector, | |
| 172 | .cmp_vector_optimized => .scalarize_cmp_vector_optimized, | |
| 173 | .fptrunc => .scalarize_fptrunc, | |
| 174 | .fpext => .scalarize_fpext, | |
| 175 | .intcast => .scalarize_intcast, | |
| 176 | .intcast_safe => .scalarize_intcast_safe, | |
| 177 | .trunc => .scalarize_trunc, | |
| 178 | .int_from_float => .scalarize_int_from_float, | |
| 179 | .int_from_float_optimized => .scalarize_int_from_float_optimized, | |
| 180 | .float_from_int => .scalarize_float_from_int, | |
| 181 | .shuffle_one => .scalarize_shuffle_one, | |
| 182 | .shuffle_two => .scalarize_shuffle_two, | |
| 183 | .select => .scalarize_selects, | |
| 184 | .mul_add => .scalarize_mul_add, | |
| 185 | }; | |
| 186 | } | |
| 10 | 187 | }; |
| 11 | 188 | |
| 12 | pub const Features = std.enums.EnumFieldStruct(Feature, bool, false); | |
| 189 | pub const Features = std.enums.EnumSet(Feature); | |
| 190 | ||
| 191 | pub const Error = std.mem.Allocator.Error; | |
| 13 | 192 | |
| 14 | pub fn legalize(air: *Air, backend: std.builtin.CompilerBackend, zcu: *const Zcu) std.mem.Allocator.Error!void { | |
| 193 | pub fn legalize(air: *Air, pt: Zcu.PerThread, features: *const Features) Error!void { | |
| 194 | dev.check(.legalize); | |
| 195 | assert(!features.bits.eql(.initEmpty())); // backend asked to run legalize, but no features were enabled | |
| 15 | 196 | var l: Legalize = .{ |
| 16 | .zcu = zcu, | |
| 17 | .air = air.*, | |
| 18 | .features = features: switch (backend) { | |
| 19 | .other, .stage1 => unreachable, | |
| 20 | inline .stage2_llvm, | |
| 21 | .stage2_c, | |
| 22 | .stage2_wasm, | |
| 23 | .stage2_arm, | |
| 24 | .stage2_x86_64, | |
| 25 | .stage2_aarch64, | |
| 26 | .stage2_x86, | |
| 27 | .stage2_riscv64, | |
| 28 | .stage2_sparc64, | |
| 29 | .stage2_spirv64, | |
| 30 | .stage2_powerpc, | |
| 31 | => |ct_backend| { | |
| 32 | const Backend = codegen.importBackend(ct_backend) orelse break :features .initEmpty(); | |
| 33 | break :features if (@hasDecl(Backend, "legalize_features")) | |
| 34 | .init(Backend.legalize_features) | |
| 35 | else | |
| 36 | .initEmpty(); | |
| 37 | }, | |
| 38 | _ => unreachable, | |
| 39 | }, | |
| 197 | .pt = pt, | |
| 198 | .air_instructions = air.instructions.toMultiArrayList(), | |
| 199 | .air_extra = air.extra, | |
| 200 | .features = features, | |
| 201 | }; | |
| 202 | defer air.* = l.getTmpAir(); | |
| 203 | const main_extra = l.extraData(Air.Block, l.air_extra.items[@intFromEnum(Air.ExtraIndex.main_block)]); | |
| 204 | try l.legalizeBody(main_extra.end, main_extra.data.body_len); | |
| 205 | } | |
| 206 | ||
| 207 | fn getTmpAir(l: *const Legalize) Air { | |
| 208 | return .{ | |
| 209 | .instructions = l.air_instructions.slice(), | |
| 210 | .extra = l.air_extra, | |
| 40 | 211 | }; |
| 41 | defer air.* = l.air; | |
| 42 | if (!l.features.bits.eql(.initEmpty())) try l.legalizeBody(l.air.getMainBody()); | |
| 43 | 212 | } |
| 44 | 213 | |
| 45 | fn legalizeBody(l: *Legalize, body: []const Air.Inst.Index) std.mem.Allocator.Error!void { | |
| 46 | const zcu = l.zcu; | |
| 214 | fn typeOf(l: *const Legalize, ref: Air.Inst.Ref) Type { | |
| 215 | return l.getTmpAir().typeOf(ref, &l.pt.zcu.intern_pool); | |
| 216 | } | |
| 217 | ||
| 218 | fn typeOfIndex(l: *const Legalize, inst: Air.Inst.Index) Type { | |
| 219 | return l.getTmpAir().typeOfIndex(inst, &l.pt.zcu.intern_pool); | |
| 220 | } | |
| 221 | ||
| 222 | fn extraData(l: *const Legalize, comptime T: type, index: usize) @TypeOf(Air.extraData(undefined, T, undefined)) { | |
| 223 | return l.getTmpAir().extraData(T, index); | |
| 224 | } | |
| 225 | ||
| 226 | fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void { | |
| 227 | const zcu = l.pt.zcu; | |
| 47 | 228 | const ip = &zcu.intern_pool; |
| 48 | const tags = l.air.instructions.items(.tag); | |
| 49 | const data = l.air.instructions.items(.data); | |
| 50 | for (body) |inst| inst: switch (tags[@intFromEnum(inst)]) { | |
| 51 | else => {}, | |
| 52 | ||
| 53 | .shl, | |
| 54 | .shl_exact, | |
| 55 | .shl_sat, | |
| 56 | .shr, | |
| 57 | .shr_exact, | |
| 58 | => |air_tag| if (l.features.contains(.remove_shift_vector_rhs_splat)) done: { | |
| 59 | const bin_op = data[@intFromEnum(inst)].bin_op; | |
| 60 | const ty = l.air.typeOf(bin_op.rhs, ip); | |
| 61 | if (!ty.isVector(zcu)) break :done; | |
| 62 | if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) { | |
| 63 | else => {}, | |
| 64 | .aggregate => |aggregate| switch (aggregate.storage) { | |
| 65 | else => {}, | |
| 66 | .repeated_elem => |splat| continue :inst l.replaceInst(inst, air_tag, .{ .bin_op = .{ | |
| 67 | .lhs = bin_op.lhs, | |
| 68 | .rhs = Air.internedToRef(splat), | |
| 69 | } }), | |
| 70 | }, | |
| 71 | } else { | |
| 72 | const rhs_inst = bin_op.rhs.toIndex().?; | |
| 73 | switch (tags[@intFromEnum(rhs_inst)]) { | |
| 74 | else => {}, | |
| 75 | .splat => continue :inst l.replaceInst(inst, air_tag, .{ .bin_op = .{ | |
| 76 | .lhs = bin_op.lhs, | |
| 77 | .rhs = data[@intFromEnum(rhs_inst)].ty_op.operand, | |
| 229 | for (0..body_len) |body_index| { | |
| 230 | const inst: Air.Inst.Index = @enumFromInt(l.air_extra.items[body_start + body_index]); | |
| 231 | inst: switch (l.air_instructions.items(.tag)[@intFromEnum(inst)]) { | |
| 232 | .arg, | |
| 233 | => {}, | |
| 234 | inline .add, | |
| 235 | .add_optimized, | |
| 236 | .add_wrap, | |
| 237 | .add_sat, | |
| 238 | .sub, | |
| 239 | .sub_optimized, | |
| 240 | .sub_wrap, | |
| 241 | .sub_sat, | |
| 242 | .mul, | |
| 243 | .mul_optimized, | |
| 244 | .mul_wrap, | |
| 245 | .mul_sat, | |
| 246 | .div_float, | |
| 247 | .div_float_optimized, | |
| 248 | .div_trunc, | |
| 249 | .div_trunc_optimized, | |
| 250 | .div_floor, | |
| 251 | .div_floor_optimized, | |
| 252 | .div_exact, | |
| 253 | .div_exact_optimized, | |
| 254 | .rem, | |
| 255 | .rem_optimized, | |
| 256 | .mod, | |
| 257 | .mod_optimized, | |
| 258 | .max, | |
| 259 | .min, | |
| 260 | .bit_and, | |
| 261 | .bit_or, | |
| 262 | .xor, | |
| 263 | => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) { | |
| 264 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op; | |
| 265 | if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op); | |
| 266 | }, | |
| 267 | .add_safe => if (l.features.contains(.expand_add_safe)) { | |
| 268 | assert(!l.features.contains(.scalarize_add_safe)); // it doesn't make sense to do both | |
| 269 | continue :inst l.replaceInst(inst, .block, try l.safeArithmeticBlockPayload(inst, .add_with_overflow)); | |
| 270 | } else if (l.features.contains(.scalarize_add_safe)) { | |
| 271 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op; | |
| 272 | if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op); | |
| 273 | }, | |
| 274 | .sub_safe => if (l.features.contains(.expand_sub_safe)) { | |
| 275 | assert(!l.features.contains(.scalarize_sub_safe)); // it doesn't make sense to do both | |
| 276 | continue :inst l.replaceInst(inst, .block, try l.safeArithmeticBlockPayload(inst, .sub_with_overflow)); | |
| 277 | } else if (l.features.contains(.scalarize_sub_safe)) { | |
| 278 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op; | |
| 279 | if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op); | |
| 280 | }, | |
| 281 | .mul_safe => if (l.features.contains(.expand_mul_safe)) { | |
| 282 | assert(!l.features.contains(.scalarize_mul_safe)); // it doesn't make sense to do both | |
| 283 | continue :inst l.replaceInst(inst, .block, try l.safeArithmeticBlockPayload(inst, .mul_with_overflow)); | |
| 284 | } else if (l.features.contains(.scalarize_mul_safe)) { | |
| 285 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op; | |
| 286 | if (l.typeOf(bin_op.lhs).isVector(zcu)) continue :inst try l.scalarize(inst, .bin_op); | |
| 287 | }, | |
| 288 | .ptr_add, | |
| 289 | .ptr_sub, | |
| 290 | => {}, | |
| 291 | inline .add_with_overflow, | |
| 292 | .sub_with_overflow, | |
| 293 | .mul_with_overflow, | |
| 294 | .shl_with_overflow, | |
| 295 | => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) { | |
| 296 | const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 297 | if (ty_pl.ty.toType().fieldType(0, zcu).isVector(zcu)) continue :inst l.replaceInst(inst, .block, try l.scalarizeOverflowBlockPayload(inst)); | |
| 298 | }, | |
| 299 | .alloc, | |
| 300 | => {}, | |
| 301 | .inferred_alloc, | |
| 302 | .inferred_alloc_comptime, | |
| 303 | => unreachable, | |
| 304 | .ret_ptr, | |
| 305 | .assembly, | |
| 306 | => {}, | |
| 307 | inline .shr, | |
| 308 | .shr_exact, | |
| 309 | .shl, | |
| 310 | .shl_exact, | |
| 311 | .shl_sat, | |
| 312 | => |air_tag| done: { | |
| 313 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(inst)].bin_op; | |
| 314 | if (!l.typeOf(bin_op.rhs).isVector(zcu)) break :done; | |
| 315 | if (l.features.contains(.unsplat_shift_rhs)) { | |
| 316 | if (bin_op.rhs.toInterned()) |rhs_ip_index| switch (ip.indexToKey(rhs_ip_index)) { | |
| 317 | else => {}, | |
| 318 | .aggregate => |aggregate| switch (aggregate.storage) { | |
| 319 | else => {}, | |
| 320 | .repeated_elem => |splat| continue :inst l.replaceInst(inst, air_tag, .{ .bin_op = .{ | |
| 321 | .lhs = bin_op.lhs, | |
| 322 | .rhs = Air.internedToRef(splat), | |
| 323 | } }), | |
| 324 | }, | |
| 325 | } else { | |
| 326 | const rhs_inst = bin_op.rhs.toIndex().?; | |
| 327 | switch (l.air_instructions.items(.tag)[@intFromEnum(rhs_inst)]) { | |
| 328 | else => {}, | |
| 329 | .splat => continue :inst l.replaceInst(inst, air_tag, .{ .bin_op = .{ | |
| 330 | .lhs = bin_op.lhs, | |
| 331 | .rhs = l.air_instructions.items(.data)[@intFromEnum(rhs_inst)].ty_op.operand, | |
| 332 | } }), | |
| 333 | } | |
| 334 | } | |
| 335 | } | |
| 336 | if (l.features.contains(comptime .scalarize(air_tag))) continue :inst try l.scalarize(inst, .bin_op); | |
| 337 | }, | |
| 338 | inline .not, | |
| 339 | .clz, | |
| 340 | .ctz, | |
| 341 | .popcount, | |
| 342 | .byte_swap, | |
| 343 | .bit_reverse, | |
| 344 | .abs, | |
| 345 | .fptrunc, | |
| 346 | .fpext, | |
| 347 | .intcast, | |
| 348 | .trunc, | |
| 349 | .int_from_float, | |
| 350 | .int_from_float_optimized, | |
| 351 | .float_from_int, | |
| 352 | => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) { | |
| 353 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op; | |
| 354 | if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op); | |
| 355 | }, | |
| 356 | inline .bitcast, | |
| 357 | => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) { | |
| 358 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op; | |
| 359 | const to_ty = ty_op.ty.toType(); | |
| 360 | const from_ty = l.typeOf(ty_op.operand); | |
| 361 | if (to_ty.isVector(zcu) and from_ty.isVector(zcu) and to_ty.vectorLen(zcu) == from_ty.vectorLen(zcu)) | |
| 362 | continue :inst try l.scalarize(inst, .ty_op); | |
| 363 | }, | |
| 364 | .intcast_safe => if (l.features.contains(.expand_intcast_safe)) { | |
| 365 | assert(!l.features.contains(.scalarize_intcast_safe)); // it doesn't make sense to do both | |
| 366 | continue :inst l.replaceInst(inst, .block, try l.safeIntcastBlockPayload(inst)); | |
| 367 | } else if (l.features.contains(.scalarize_intcast_safe)) { | |
| 368 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op; | |
| 369 | if (ty_op.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_op); | |
| 370 | }, | |
| 371 | .block, | |
| 372 | .loop, | |
| 373 | => { | |
| 374 | const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 375 | const extra = l.extraData(Air.Block, ty_pl.payload); | |
| 376 | try l.legalizeBody(extra.end, extra.data.body_len); | |
| 377 | }, | |
| 378 | .repeat, | |
| 379 | .br, | |
| 380 | .trap, | |
| 381 | .breakpoint, | |
| 382 | .ret_addr, | |
| 383 | .frame_addr, | |
| 384 | .call, | |
| 385 | .call_always_tail, | |
| 386 | .call_never_tail, | |
| 387 | .call_never_inline, | |
| 388 | => {}, | |
| 389 | inline .sqrt, | |
| 390 | .sin, | |
| 391 | .cos, | |
| 392 | .tan, | |
| 393 | .exp, | |
| 394 | .exp2, | |
| 395 | .log, | |
| 396 | .log2, | |
| 397 | .log10, | |
| 398 | .floor, | |
| 399 | .ceil, | |
| 400 | .round, | |
| 401 | .trunc_float, | |
| 402 | .neg, | |
| 403 | .neg_optimized, | |
| 404 | => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) { | |
| 405 | const un_op = l.air_instructions.items(.data)[@intFromEnum(inst)].un_op; | |
| 406 | if (l.typeOf(un_op).isVector(zcu)) continue :inst try l.scalarize(inst, .un_op); | |
| 407 | }, | |
| 408 | .cmp_lt, | |
| 409 | .cmp_lt_optimized, | |
| 410 | .cmp_lte, | |
| 411 | .cmp_lte_optimized, | |
| 412 | .cmp_eq, | |
| 413 | .cmp_eq_optimized, | |
| 414 | .cmp_gte, | |
| 415 | .cmp_gte_optimized, | |
| 416 | .cmp_gt, | |
| 417 | .cmp_gt_optimized, | |
| 418 | .cmp_neq, | |
| 419 | .cmp_neq_optimized, | |
| 420 | => {}, | |
| 421 | inline .cmp_vector, | |
| 422 | .cmp_vector_optimized, | |
| 423 | => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) { | |
| 424 | const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 425 | if (ty_pl.ty.toType().isVector(zcu)) continue :inst try l.scalarize(inst, .ty_pl_vector_cmp); | |
| 426 | }, | |
| 427 | .cond_br, | |
| 428 | => { | |
| 429 | const pl_op = l.air_instructions.items(.data)[@intFromEnum(inst)].pl_op; | |
| 430 | const extra = l.extraData(Air.CondBr, pl_op.payload); | |
| 431 | try l.legalizeBody(extra.end, extra.data.then_body_len); | |
| 432 | try l.legalizeBody(extra.end + extra.data.then_body_len, extra.data.else_body_len); | |
| 433 | }, | |
| 434 | .switch_br, | |
| 435 | .loop_switch_br, | |
| 436 | => { | |
| 437 | const pl_op = l.air_instructions.items(.data)[@intFromEnum(inst)].pl_op; | |
| 438 | const extra = l.extraData(Air.SwitchBr, pl_op.payload); | |
| 439 | const hint_bag_count = std.math.divCeil(usize, extra.data.cases_len + 1, 10) catch unreachable; | |
| 440 | var extra_index = extra.end + hint_bag_count; | |
| 441 | for (0..extra.data.cases_len) |_| { | |
| 442 | const case_extra = l.extraData(Air.SwitchBr.Case, extra_index); | |
| 443 | const case_body_start = case_extra.end + case_extra.data.items_len + case_extra.data.ranges_len * 2; | |
| 444 | try l.legalizeBody(case_body_start, case_extra.data.body_len); | |
| 445 | extra_index = case_body_start + case_extra.data.body_len; | |
| 446 | } | |
| 447 | try l.legalizeBody(extra_index, extra.data.else_body_len); | |
| 448 | }, | |
| 449 | .switch_dispatch, | |
| 450 | => {}, | |
| 451 | .@"try", | |
| 452 | .try_cold, | |
| 453 | => { | |
| 454 | const pl_op = l.air_instructions.items(.data)[@intFromEnum(inst)].pl_op; | |
| 455 | const extra = l.extraData(Air.Try, pl_op.payload); | |
| 456 | try l.legalizeBody(extra.end, extra.data.body_len); | |
| 457 | }, | |
| 458 | .try_ptr, | |
| 459 | .try_ptr_cold, | |
| 460 | => { | |
| 461 | const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 462 | const extra = l.extraData(Air.TryPtr, ty_pl.payload); | |
| 463 | try l.legalizeBody(extra.end, extra.data.body_len); | |
| 464 | }, | |
| 465 | .dbg_stmt, | |
| 466 | .dbg_empty_stmt, | |
| 467 | => {}, | |
| 468 | .dbg_inline_block, | |
| 469 | => { | |
| 470 | const ty_pl = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 471 | const extra = l.extraData(Air.DbgInlineBlock, ty_pl.payload); | |
| 472 | try l.legalizeBody(extra.end, extra.data.body_len); | |
| 473 | }, | |
| 474 | .dbg_var_ptr, | |
| 475 | .dbg_var_val, | |
| 476 | .dbg_arg_inline, | |
| 477 | .is_null, | |
| 478 | .is_non_null, | |
| 479 | .is_null_ptr, | |
| 480 | .is_non_null_ptr, | |
| 481 | .is_err, | |
| 482 | .is_non_err, | |
| 483 | .is_err_ptr, | |
| 484 | .is_non_err_ptr, | |
| 485 | .bool_and, | |
| 486 | .bool_or, | |
| 487 | .load, | |
| 488 | .ret, | |
| 489 | .ret_safe, | |
| 490 | .ret_load, | |
| 491 | .store, | |
| 492 | .store_safe, | |
| 493 | .unreach, | |
| 494 | => {}, | |
| 495 | .optional_payload, | |
| 496 | .optional_payload_ptr, | |
| 497 | .optional_payload_ptr_set, | |
| 498 | .wrap_optional, | |
| 499 | .unwrap_errunion_payload, | |
| 500 | .unwrap_errunion_err, | |
| 501 | .unwrap_errunion_payload_ptr, | |
| 502 | .unwrap_errunion_err_ptr, | |
| 503 | .errunion_payload_ptr_set, | |
| 504 | .wrap_errunion_payload, | |
| 505 | .wrap_errunion_err, | |
| 506 | .struct_field_ptr, | |
| 507 | .struct_field_ptr_index_0, | |
| 508 | .struct_field_ptr_index_1, | |
| 509 | .struct_field_ptr_index_2, | |
| 510 | .struct_field_ptr_index_3, | |
| 511 | .struct_field_val, | |
| 512 | .set_union_tag, | |
| 513 | .get_union_tag, | |
| 514 | .slice, | |
| 515 | .slice_len, | |
| 516 | .slice_ptr, | |
| 517 | .ptr_slice_len_ptr, | |
| 518 | .ptr_slice_ptr_ptr, | |
| 519 | .array_elem_val, | |
| 520 | .slice_elem_val, | |
| 521 | .slice_elem_ptr, | |
| 522 | .ptr_elem_val, | |
| 523 | .ptr_elem_ptr, | |
| 524 | .array_to_slice, | |
| 525 | => {}, | |
| 526 | .reduce, | |
| 527 | .reduce_optimized, | |
| 528 | => if (l.features.contains(.reduce_one_elem_to_bitcast)) done: { | |
| 529 | const reduce = l.air_instructions.items(.data)[@intFromEnum(inst)].reduce; | |
| 530 | const vector_ty = l.typeOf(reduce.operand); | |
| 531 | switch (vector_ty.vectorLen(zcu)) { | |
| 532 | 0 => unreachable, | |
| 533 | 1 => continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{ | |
| 534 | .ty = Air.internedToRef(vector_ty.childType(zcu).toIntern()), | |
| 535 | .operand = reduce.operand, | |
| 78 | 536 | } }), |
| 537 | else => break :done, | |
| 79 | 538 | } |
| 539 | }, | |
| 540 | .splat, | |
| 541 | => {}, | |
| 542 | .shuffle_one => if (l.features.contains(.scalarize_shuffle_one)) continue :inst try l.scalarize(inst, .shuffle_one), | |
| 543 | .shuffle_two => if (l.features.contains(.scalarize_shuffle_two)) continue :inst try l.scalarize(inst, .shuffle_two), | |
| 544 | .select => if (l.features.contains(.scalarize_select)) continue :inst try l.scalarize(inst, .select), | |
| 545 | .memset, | |
| 546 | .memset_safe, | |
| 547 | .memcpy, | |
| 548 | .memmove, | |
| 549 | .cmpxchg_weak, | |
| 550 | .cmpxchg_strong, | |
| 551 | .atomic_load, | |
| 552 | .atomic_store_unordered, | |
| 553 | .atomic_store_monotonic, | |
| 554 | .atomic_store_release, | |
| 555 | .atomic_store_seq_cst, | |
| 556 | .atomic_rmw, | |
| 557 | .is_named_enum_value, | |
| 558 | .tag_name, | |
| 559 | .error_name, | |
| 560 | .error_set_has_value, | |
| 561 | .aggregate_init, | |
| 562 | .union_init, | |
| 563 | .prefetch, | |
| 564 | => {}, | |
| 565 | inline .mul_add, | |
| 566 | => |air_tag| if (l.features.contains(comptime .scalarize(air_tag))) { | |
| 567 | const pl_op = l.air_instructions.items(.data)[@intFromEnum(inst)].pl_op; | |
| 568 | if (l.typeOf(pl_op.operand).isVector(zcu)) continue :inst try l.scalarize(inst, .pl_op_bin); | |
| 569 | }, | |
| 570 | .field_parent_ptr, | |
| 571 | .wasm_memory_size, | |
| 572 | .wasm_memory_grow, | |
| 573 | .cmp_lt_errors_len, | |
| 574 | .err_return_trace, | |
| 575 | .set_err_return_trace, | |
| 576 | .addrspace_cast, | |
| 577 | .save_err_return_trace_index, | |
| 578 | .vector_store_elem, | |
| 579 | .tlv_dllimport_ptr, | |
| 580 | .c_va_arg, | |
| 581 | .c_va_copy, | |
| 582 | .c_va_end, | |
| 583 | .c_va_start, | |
| 584 | .work_item_id, | |
| 585 | .work_group_size, | |
| 586 | .work_group_id, | |
| 587 | => {}, | |
| 588 | } | |
| 589 | } | |
| 590 | } | |
| 591 | ||
| 592 | const ScalarizeForm = enum { un_op, ty_op, bin_op, ty_pl_vector_cmp, pl_op_bin, shuffle_one, shuffle_two, select }; | |
| 593 | inline fn scalarize(l: *Legalize, orig_inst: Air.Inst.Index, comptime form: ScalarizeForm) Error!Air.Inst.Tag { | |
| 594 | return l.replaceInst(orig_inst, .block, try l.scalarizeBlockPayload(orig_inst, form)); | |
| 595 | } | |
| 596 | fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime form: ScalarizeForm) Error!Air.Inst.Data { | |
| 597 | const pt = l.pt; | |
| 598 | const zcu = pt.zcu; | |
| 599 | ||
| 600 | const orig = l.air_instructions.get(@intFromEnum(orig_inst)); | |
| 601 | const res_ty = l.typeOfIndex(orig_inst); | |
| 602 | const res_len = res_ty.vectorLen(zcu); | |
| 603 | ||
| 604 | const extra_insts = switch (form) { | |
| 605 | .un_op, .ty_op => 1, | |
| 606 | .bin_op, .ty_pl_vector_cmp => 2, | |
| 607 | .pl_op_bin => 3, | |
| 608 | .shuffle_one, .shuffle_two => 13, | |
| 609 | .select => 6, | |
| 610 | }; | |
| 611 | var inst_buf: [5 + extra_insts + 9]Air.Inst.Index = undefined; | |
| 612 | try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len); | |
| 613 | ||
| 614 | var res_block: Block = .init(&inst_buf); | |
| 615 | { | |
| 616 | const res_alloc_inst = res_block.add(l, .{ | |
| 617 | .tag = .alloc, | |
| 618 | .data = .{ .ty = try pt.singleMutPtrType(res_ty) }, | |
| 619 | }); | |
| 620 | const index_alloc_inst = res_block.add(l, .{ | |
| 621 | .tag = .alloc, | |
| 622 | .data = .{ .ty = .ptr_usize }, | |
| 623 | }); | |
| 624 | _ = res_block.add(l, .{ | |
| 625 | .tag = .store, | |
| 626 | .data = .{ .bin_op = .{ | |
| 627 | .lhs = index_alloc_inst.toRef(), | |
| 628 | .rhs = .zero_usize, | |
| 629 | } }, | |
| 630 | }); | |
| 631 | ||
| 632 | var loop: Loop = .init(l, &res_block); | |
| 633 | loop.block = .init(res_block.stealRemainingCapacity()); | |
| 634 | { | |
| 635 | const cur_index_inst = loop.block.add(l, .{ | |
| 636 | .tag = .load, | |
| 637 | .data = .{ .ty_op = .{ | |
| 638 | .ty = .usize_type, | |
| 639 | .operand = index_alloc_inst.toRef(), | |
| 640 | } }, | |
| 641 | }); | |
| 642 | _ = loop.block.add(l, .{ | |
| 643 | .tag = .vector_store_elem, | |
| 644 | .data = .{ .vector_store_elem = .{ | |
| 645 | .vector_ptr = res_alloc_inst.toRef(), | |
| 646 | .payload = try l.addExtra(Air.Bin, .{ | |
| 647 | .lhs = cur_index_inst.toRef(), | |
| 648 | .rhs = res_elem: switch (form) { | |
| 649 | .un_op => loop.block.add(l, .{ | |
| 650 | .tag = orig.tag, | |
| 651 | .data = .{ .un_op = loop.block.add(l, .{ | |
| 652 | .tag = .array_elem_val, | |
| 653 | .data = .{ .bin_op = .{ | |
| 654 | .lhs = orig.data.un_op, | |
| 655 | .rhs = cur_index_inst.toRef(), | |
| 656 | } }, | |
| 657 | }).toRef() }, | |
| 658 | }).toRef(), | |
| 659 | .ty_op => loop.block.add(l, .{ | |
| 660 | .tag = orig.tag, | |
| 661 | .data = .{ .ty_op = .{ | |
| 662 | .ty = Air.internedToRef(res_ty.childType(zcu).toIntern()), | |
| 663 | .operand = loop.block.add(l, .{ | |
| 664 | .tag = .array_elem_val, | |
| 665 | .data = .{ .bin_op = .{ | |
| 666 | .lhs = orig.data.ty_op.operand, | |
| 667 | .rhs = cur_index_inst.toRef(), | |
| 668 | } }, | |
| 669 | }).toRef(), | |
| 670 | } }, | |
| 671 | }).toRef(), | |
| 672 | .bin_op => loop.block.add(l, .{ | |
| 673 | .tag = orig.tag, | |
| 674 | .data = .{ .bin_op = .{ | |
| 675 | .lhs = loop.block.add(l, .{ | |
| 676 | .tag = .array_elem_val, | |
| 677 | .data = .{ .bin_op = .{ | |
| 678 | .lhs = orig.data.bin_op.lhs, | |
| 679 | .rhs = cur_index_inst.toRef(), | |
| 680 | } }, | |
| 681 | }).toRef(), | |
| 682 | .rhs = loop.block.add(l, .{ | |
| 683 | .tag = .array_elem_val, | |
| 684 | .data = .{ .bin_op = .{ | |
| 685 | .lhs = orig.data.bin_op.rhs, | |
| 686 | .rhs = cur_index_inst.toRef(), | |
| 687 | } }, | |
| 688 | }).toRef(), | |
| 689 | } }, | |
| 690 | }).toRef(), | |
| 691 | .ty_pl_vector_cmp => { | |
| 692 | const extra = l.extraData(Air.VectorCmp, orig.data.ty_pl.payload).data; | |
| 693 | break :res_elem (try loop.block.addCmp( | |
| 694 | l, | |
| 695 | extra.compareOperator(), | |
| 696 | loop.block.add(l, .{ | |
| 697 | .tag = .array_elem_val, | |
| 698 | .data = .{ .bin_op = .{ | |
| 699 | .lhs = extra.lhs, | |
| 700 | .rhs = cur_index_inst.toRef(), | |
| 701 | } }, | |
| 702 | }).toRef(), | |
| 703 | loop.block.add(l, .{ | |
| 704 | .tag = .array_elem_val, | |
| 705 | .data = .{ .bin_op = .{ | |
| 706 | .lhs = extra.rhs, | |
| 707 | .rhs = cur_index_inst.toRef(), | |
| 708 | } }, | |
| 709 | }).toRef(), | |
| 710 | .{ .optimized = switch (orig.tag) { | |
| 711 | else => unreachable, | |
| 712 | .cmp_vector => false, | |
| 713 | .cmp_vector_optimized => true, | |
| 714 | } }, | |
| 715 | )).toRef(); | |
| 716 | }, | |
| 717 | .pl_op_bin => { | |
| 718 | const extra = l.extraData(Air.Bin, orig.data.pl_op.payload).data; | |
| 719 | break :res_elem loop.block.add(l, .{ | |
| 720 | .tag = orig.tag, | |
| 721 | .data = .{ .pl_op = .{ | |
| 722 | .payload = try l.addExtra(Air.Bin, .{ | |
| 723 | .lhs = loop.block.add(l, .{ | |
| 724 | .tag = .array_elem_val, | |
| 725 | .data = .{ .bin_op = .{ | |
| 726 | .lhs = extra.lhs, | |
| 727 | .rhs = cur_index_inst.toRef(), | |
| 728 | } }, | |
| 729 | }).toRef(), | |
| 730 | .rhs = loop.block.add(l, .{ | |
| 731 | .tag = .array_elem_val, | |
| 732 | .data = .{ .bin_op = .{ | |
| 733 | .lhs = extra.rhs, | |
| 734 | .rhs = cur_index_inst.toRef(), | |
| 735 | } }, | |
| 736 | }).toRef(), | |
| 737 | }), | |
| 738 | .operand = loop.block.add(l, .{ | |
| 739 | .tag = .array_elem_val, | |
| 740 | .data = .{ .bin_op = .{ | |
| 741 | .lhs = orig.data.pl_op.operand, | |
| 742 | .rhs = cur_index_inst.toRef(), | |
| 743 | } }, | |
| 744 | }).toRef(), | |
| 745 | } }, | |
| 746 | }).toRef(); | |
| 747 | }, | |
| 748 | .shuffle_one, .shuffle_two => { | |
| 749 | const ip = &zcu.intern_pool; | |
| 750 | const unwrapped = switch (form) { | |
| 751 | else => comptime unreachable, | |
| 752 | .shuffle_one => l.getTmpAir().unwrapShuffleOne(zcu, orig_inst), | |
| 753 | .shuffle_two => l.getTmpAir().unwrapShuffleTwo(zcu, orig_inst), | |
| 754 | }; | |
| 755 | const operand_a = switch (form) { | |
| 756 | else => comptime unreachable, | |
| 757 | .shuffle_one => unwrapped.operand, | |
| 758 | .shuffle_two => unwrapped.operand_a, | |
| 759 | }; | |
| 760 | const operand_a_len = l.typeOf(operand_a).vectorLen(zcu); | |
| 761 | const elem_ty = res_ty.childType(zcu); | |
| 762 | var res_elem: Result = .init(l, elem_ty, &loop.block); | |
| 763 | res_elem.block = .init(loop.block.stealCapacity(extra_insts)); | |
| 764 | { | |
| 765 | const ExpectedContents = extern struct { | |
| 766 | mask_elems: [128]InternPool.Index, | |
| 767 | ct_elems: switch (form) { | |
| 768 | else => unreachable, | |
| 769 | .shuffle_one => extern struct { | |
| 770 | keys: [152]InternPool.Index, | |
| 771 | header: u8 align(@alignOf(u32)), | |
| 772 | index: [256][2]u8, | |
| 773 | }, | |
| 774 | .shuffle_two => void, | |
| 775 | }, | |
| 776 | }; | |
| 777 | var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) = | |
| 778 | std.heap.stackFallback(@sizeOf(ExpectedContents), zcu.gpa); | |
| 779 | const gpa = stack.get(); | |
| 780 | ||
| 781 | const mask_elems = try gpa.alloc(InternPool.Index, res_len); | |
| 782 | defer gpa.free(mask_elems); | |
| 783 | ||
| 784 | var ct_elems: switch (form) { | |
| 785 | else => unreachable, | |
| 786 | .shuffle_one => std.AutoArrayHashMapUnmanaged(InternPool.Index, void), | |
| 787 | .shuffle_two => struct { | |
| 788 | const empty: @This() = .{}; | |
| 789 | inline fn deinit(_: @This(), _: std.mem.Allocator) void {} | |
| 790 | inline fn ensureTotalCapacity(_: @This(), _: std.mem.Allocator, _: usize) error{}!void {} | |
| 791 | }, | |
| 792 | } = .empty; | |
| 793 | defer ct_elems.deinit(gpa); | |
| 794 | try ct_elems.ensureTotalCapacity(gpa, res_len); | |
| 795 | ||
| 796 | const mask_elem_ty = try pt.intType(.signed, 1 + Type.smallestUnsignedBits(@max(operand_a_len, switch (form) { | |
| 797 | else => comptime unreachable, | |
| 798 | .shuffle_one => res_len, | |
| 799 | .shuffle_two => l.typeOf(unwrapped.operand_b).vectorLen(zcu), | |
| 800 | }))); | |
| 801 | for (mask_elems, unwrapped.mask) |*mask_elem_val, mask_elem| mask_elem_val.* = (try pt.intValue(mask_elem_ty, switch (form) { | |
| 802 | else => comptime unreachable, | |
| 803 | .shuffle_one => switch (mask_elem.unwrap()) { | |
| 804 | .elem => |index| index, | |
| 805 | .value => |elem_val| if (ip.isUndef(elem_val)) | |
| 806 | operand_a_len | |
| 807 | else | |
| 808 | ~@as(i33, @intCast((ct_elems.getOrPutAssumeCapacity(elem_val)).index)), | |
| 809 | }, | |
| 810 | .shuffle_two => switch (mask_elem.unwrap()) { | |
| 811 | .a_elem => |a_index| a_index, | |
| 812 | .b_elem => |b_index| ~@as(i33, b_index), | |
| 813 | .undef => operand_a_len, | |
| 814 | }, | |
| 815 | })).toIntern(); | |
| 816 | const mask_ty = try pt.arrayType(.{ | |
| 817 | .len = res_len, | |
| 818 | .child = mask_elem_ty.toIntern(), | |
| 819 | }); | |
| 820 | const mask_elem_inst = res_elem.block.add(l, .{ | |
| 821 | .tag = .ptr_elem_val, | |
| 822 | .data = .{ .bin_op = .{ | |
| 823 | .lhs = Air.internedToRef(try pt.intern(.{ .ptr = .{ | |
| 824 | .ty = (try pt.manyConstPtrType(mask_elem_ty)).toIntern(), | |
| 825 | .base_addr = .{ .uav = .{ | |
| 826 | .val = try pt.intern(.{ .aggregate = .{ | |
| 827 | .ty = mask_ty.toIntern(), | |
| 828 | .storage = .{ .elems = mask_elems }, | |
| 829 | } }), | |
| 830 | .orig_ty = (try pt.singleConstPtrType(mask_ty)).toIntern(), | |
| 831 | } }, | |
| 832 | .byte_offset = 0, | |
| 833 | } })), | |
| 834 | .rhs = cur_index_inst.toRef(), | |
| 835 | } }, | |
| 836 | }); | |
| 837 | var def_cond_br: CondBr = .init(l, (try res_elem.block.addCmp( | |
| 838 | l, | |
| 839 | .lt, | |
| 840 | mask_elem_inst.toRef(), | |
| 841 | try pt.intRef(mask_elem_ty, operand_a_len), | |
| 842 | .{}, | |
| 843 | )).toRef(), &res_elem.block, .{}); | |
| 844 | def_cond_br.then_block = .init(res_elem.block.stealRemainingCapacity()); | |
| 845 | { | |
| 846 | const operand_b_used = switch (form) { | |
| 847 | else => comptime unreachable, | |
| 848 | .shuffle_one => ct_elems.count() > 0, | |
| 849 | .shuffle_two => true, | |
| 850 | }; | |
| 851 | var operand_cond_br: CondBr = undefined; | |
| 852 | operand_cond_br.then_block = if (operand_b_used) then_block: { | |
| 853 | operand_cond_br = .init(l, (try def_cond_br.then_block.addCmp( | |
| 854 | l, | |
| 855 | .gte, | |
| 856 | mask_elem_inst.toRef(), | |
| 857 | try pt.intRef(mask_elem_ty, 0), | |
| 858 | .{}, | |
| 859 | )).toRef(), &def_cond_br.then_block, .{}); | |
| 860 | break :then_block .init(def_cond_br.then_block.stealRemainingCapacity()); | |
| 861 | } else def_cond_br.then_block; | |
| 862 | _ = operand_cond_br.then_block.add(l, .{ | |
| 863 | .tag = .br, | |
| 864 | .data = .{ .br = .{ | |
| 865 | .block_inst = res_elem.inst, | |
| 866 | .operand = operand_cond_br.then_block.add(l, .{ | |
| 867 | .tag = .array_elem_val, | |
| 868 | .data = .{ .bin_op = .{ | |
| 869 | .lhs = operand_a, | |
| 870 | .rhs = operand_cond_br.then_block.add(l, .{ | |
| 871 | .tag = .intcast, | |
| 872 | .data = .{ .ty_op = .{ | |
| 873 | .ty = .usize_type, | |
| 874 | .operand = mask_elem_inst.toRef(), | |
| 875 | } }, | |
| 876 | }).toRef(), | |
| 877 | } }, | |
| 878 | }).toRef(), | |
| 879 | } }, | |
| 880 | }); | |
| 881 | if (operand_b_used) { | |
| 882 | operand_cond_br.else_block = .init(operand_cond_br.then_block.stealRemainingCapacity()); | |
| 883 | _ = operand_cond_br.else_block.add(l, .{ | |
| 884 | .tag = .br, | |
| 885 | .data = .{ .br = .{ | |
| 886 | .block_inst = res_elem.inst, | |
| 887 | .operand = if (switch (form) { | |
| 888 | else => comptime unreachable, | |
| 889 | .shuffle_one => ct_elems.count() > 1, | |
| 890 | .shuffle_two => true, | |
| 891 | }) operand_cond_br.else_block.add(l, .{ | |
| 892 | .tag = switch (form) { | |
| 893 | else => comptime unreachable, | |
| 894 | .shuffle_one => .ptr_elem_val, | |
| 895 | .shuffle_two => .array_elem_val, | |
| 896 | }, | |
| 897 | .data = .{ .bin_op = .{ | |
| 898 | .lhs = operand_b: switch (form) { | |
| 899 | else => comptime unreachable, | |
| 900 | .shuffle_one => { | |
| 901 | const ct_elems_ty = try pt.arrayType(.{ | |
| 902 | .len = ct_elems.count(), | |
| 903 | .child = elem_ty.toIntern(), | |
| 904 | }); | |
| 905 | break :operand_b Air.internedToRef(try pt.intern(.{ .ptr = .{ | |
| 906 | .ty = (try pt.manyConstPtrType(elem_ty)).toIntern(), | |
| 907 | .base_addr = .{ .uav = .{ | |
| 908 | .val = try pt.intern(.{ .aggregate = .{ | |
| 909 | .ty = ct_elems_ty.toIntern(), | |
| 910 | .storage = .{ .elems = ct_elems.keys() }, | |
| 911 | } }), | |
| 912 | .orig_ty = (try pt.singleConstPtrType(ct_elems_ty)).toIntern(), | |
| 913 | } }, | |
| 914 | .byte_offset = 0, | |
| 915 | } })); | |
| 916 | }, | |
| 917 | .shuffle_two => unwrapped.operand_b, | |
| 918 | }, | |
| 919 | .rhs = operand_cond_br.else_block.add(l, .{ | |
| 920 | .tag = .intcast, | |
| 921 | .data = .{ .ty_op = .{ | |
| 922 | .ty = .usize_type, | |
| 923 | .operand = operand_cond_br.else_block.add(l, .{ | |
| 924 | .tag = .not, | |
| 925 | .data = .{ .ty_op = .{ | |
| 926 | .ty = Air.internedToRef(mask_elem_ty.toIntern()), | |
| 927 | .operand = mask_elem_inst.toRef(), | |
| 928 | } }, | |
| 929 | }).toRef(), | |
| 930 | } }, | |
| 931 | }).toRef(), | |
| 932 | } }, | |
| 933 | }).toRef() else res_elem_br: { | |
| 934 | _ = operand_cond_br.else_block.stealCapacity(3); | |
| 935 | break :res_elem_br Air.internedToRef(ct_elems.keys()[0]); | |
| 936 | }, | |
| 937 | } }, | |
| 938 | }); | |
| 939 | def_cond_br.else_block = .init(operand_cond_br.else_block.stealRemainingCapacity()); | |
| 940 | try operand_cond_br.finish(l); | |
| 941 | } else { | |
| 942 | def_cond_br.then_block = operand_cond_br.then_block; | |
| 943 | _ = def_cond_br.then_block.stealCapacity(6); | |
| 944 | def_cond_br.else_block = .init(def_cond_br.then_block.stealRemainingCapacity()); | |
| 945 | } | |
| 946 | } | |
| 947 | _ = def_cond_br.else_block.add(l, .{ | |
| 948 | .tag = .br, | |
| 949 | .data = .{ .br = .{ | |
| 950 | .block_inst = res_elem.inst, | |
| 951 | .operand = try pt.undefRef(elem_ty), | |
| 952 | } }, | |
| 953 | }); | |
| 954 | try def_cond_br.finish(l); | |
| 955 | } | |
| 956 | try res_elem.finish(l); | |
| 957 | break :res_elem res_elem.inst.toRef(); | |
| 958 | }, | |
| 959 | .select => { | |
| 960 | const extra = l.extraData(Air.Bin, orig.data.pl_op.payload).data; | |
| 961 | var res_elem: Result = .init(l, l.typeOf(extra.lhs).childType(zcu), &loop.block); | |
| 962 | res_elem.block = .init(loop.block.stealCapacity(extra_insts)); | |
| 963 | { | |
| 964 | var select_cond_br: CondBr = .init(l, res_elem.block.add(l, .{ | |
| 965 | .tag = .array_elem_val, | |
| 966 | .data = .{ .bin_op = .{ | |
| 967 | .lhs = orig.data.pl_op.operand, | |
| 968 | .rhs = cur_index_inst.toRef(), | |
| 969 | } }, | |
| 970 | }).toRef(), &res_elem.block, .{}); | |
| 971 | select_cond_br.then_block = .init(res_elem.block.stealRemainingCapacity()); | |
| 972 | _ = select_cond_br.then_block.add(l, .{ | |
| 973 | .tag = .br, | |
| 974 | .data = .{ .br = .{ | |
| 975 | .block_inst = res_elem.inst, | |
| 976 | .operand = select_cond_br.then_block.add(l, .{ | |
| 977 | .tag = .array_elem_val, | |
| 978 | .data = .{ .bin_op = .{ | |
| 979 | .lhs = extra.lhs, | |
| 980 | .rhs = cur_index_inst.toRef(), | |
| 981 | } }, | |
| 982 | }).toRef(), | |
| 983 | } }, | |
| 984 | }); | |
| 985 | select_cond_br.else_block = .init(select_cond_br.then_block.stealRemainingCapacity()); | |
| 986 | _ = select_cond_br.else_block.add(l, .{ | |
| 987 | .tag = .br, | |
| 988 | .data = .{ .br = .{ | |
| 989 | .block_inst = res_elem.inst, | |
| 990 | .operand = select_cond_br.else_block.add(l, .{ | |
| 991 | .tag = .array_elem_val, | |
| 992 | .data = .{ .bin_op = .{ | |
| 993 | .lhs = extra.rhs, | |
| 994 | .rhs = cur_index_inst.toRef(), | |
| 995 | } }, | |
| 996 | }).toRef(), | |
| 997 | } }, | |
| 998 | }); | |
| 999 | try select_cond_br.finish(l); | |
| 1000 | } | |
| 1001 | try res_elem.finish(l); | |
| 1002 | break :res_elem res_elem.inst.toRef(); | |
| 1003 | }, | |
| 1004 | }, | |
| 1005 | }), | |
| 1006 | } }, | |
| 1007 | }); | |
| 1008 | ||
| 1009 | var loop_cond_br: CondBr = .init(l, (try loop.block.addCmp( | |
| 1010 | l, | |
| 1011 | .lt, | |
| 1012 | cur_index_inst.toRef(), | |
| 1013 | try pt.intRef(.usize, res_len - 1), | |
| 1014 | .{}, | |
| 1015 | )).toRef(), &loop.block, .{}); | |
| 1016 | loop_cond_br.then_block = .init(loop.block.stealRemainingCapacity()); | |
| 1017 | { | |
| 1018 | _ = loop_cond_br.then_block.add(l, .{ | |
| 1019 | .tag = .store, | |
| 1020 | .data = .{ .bin_op = .{ | |
| 1021 | .lhs = index_alloc_inst.toRef(), | |
| 1022 | .rhs = loop_cond_br.then_block.add(l, .{ | |
| 1023 | .tag = .add, | |
| 1024 | .data = .{ .bin_op = .{ | |
| 1025 | .lhs = cur_index_inst.toRef(), | |
| 1026 | .rhs = .one_usize, | |
| 1027 | } }, | |
| 1028 | }).toRef(), | |
| 1029 | } }, | |
| 1030 | }); | |
| 1031 | _ = loop_cond_br.then_block.add(l, .{ | |
| 1032 | .tag = .repeat, | |
| 1033 | .data = .{ .repeat = .{ .loop_inst = loop.inst } }, | |
| 1034 | }); | |
| 80 | 1035 | } |
| 81 | }, | |
| 82 | ||
| 83 | .reduce, | |
| 84 | .reduce_optimized, | |
| 85 | => if (l.features.contains(.reduce_one_elem_to_bitcast)) done: { | |
| 86 | const reduce = data[@intFromEnum(inst)].reduce; | |
| 87 | const vector_ty = l.air.typeOf(reduce.operand, ip); | |
| 88 | switch (vector_ty.vectorLen(zcu)) { | |
| 89 | 0 => unreachable, | |
| 90 | 1 => continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{ | |
| 91 | .ty = Air.internedToRef(vector_ty.scalarType(zcu).toIntern()), | |
| 92 | .operand = reduce.operand, | |
| 93 | } }), | |
| 94 | else => break :done, | |
| 1036 | loop_cond_br.else_block = .init(loop_cond_br.then_block.stealRemainingCapacity()); | |
| 1037 | _ = loop_cond_br.else_block.add(l, .{ | |
| 1038 | .tag = .br, | |
| 1039 | .data = .{ .br = .{ | |
| 1040 | .block_inst = orig_inst, | |
| 1041 | .operand = loop_cond_br.else_block.add(l, .{ | |
| 1042 | .tag = .load, | |
| 1043 | .data = .{ .ty_op = .{ | |
| 1044 | .ty = Air.internedToRef(res_ty.toIntern()), | |
| 1045 | .operand = res_alloc_inst.toRef(), | |
| 1046 | } }, | |
| 1047 | }).toRef(), | |
| 1048 | } }, | |
| 1049 | }); | |
| 1050 | try loop_cond_br.finish(l); | |
| 1051 | } | |
| 1052 | try loop.finish(l); | |
| 1053 | } | |
| 1054 | return .{ .ty_pl = .{ | |
| 1055 | .ty = Air.internedToRef(res_ty.toIntern()), | |
| 1056 | .payload = try l.addBlockBody(res_block.body()), | |
| 1057 | } }; | |
| 1058 | } | |
| 1059 | fn scalarizeOverflowBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.Inst.Data { | |
| 1060 | const pt = l.pt; | |
| 1061 | const zcu = pt.zcu; | |
| 1062 | ||
| 1063 | const orig = l.air_instructions.get(@intFromEnum(orig_inst)); | |
| 1064 | const res_ty = l.typeOfIndex(orig_inst); | |
| 1065 | const wrapped_res_ty = res_ty.fieldType(0, zcu); | |
| 1066 | const wrapped_res_scalar_ty = wrapped_res_ty.childType(zcu); | |
| 1067 | const res_len = wrapped_res_ty.vectorLen(zcu); | |
| 1068 | ||
| 1069 | var inst_buf: [21]Air.Inst.Index = undefined; | |
| 1070 | try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len); | |
| 1071 | ||
| 1072 | var res_block: Block = .init(&inst_buf); | |
| 1073 | { | |
| 1074 | const res_alloc_inst = res_block.add(l, .{ | |
| 1075 | .tag = .alloc, | |
| 1076 | .data = .{ .ty = try pt.singleMutPtrType(res_ty) }, | |
| 1077 | }); | |
| 1078 | const ptr_wrapped_res_inst = res_block.add(l, .{ | |
| 1079 | .tag = .struct_field_ptr_index_0, | |
| 1080 | .data = .{ .ty_op = .{ | |
| 1081 | .ty = Air.internedToRef((try pt.singleMutPtrType(wrapped_res_ty)).toIntern()), | |
| 1082 | .operand = res_alloc_inst.toRef(), | |
| 1083 | } }, | |
| 1084 | }); | |
| 1085 | const ptr_overflow_res_inst = res_block.add(l, .{ | |
| 1086 | .tag = .struct_field_ptr_index_1, | |
| 1087 | .data = .{ .ty_op = .{ | |
| 1088 | .ty = Air.internedToRef((try pt.singleMutPtrType(res_ty.fieldType(1, zcu))).toIntern()), | |
| 1089 | .operand = res_alloc_inst.toRef(), | |
| 1090 | } }, | |
| 1091 | }); | |
| 1092 | const index_alloc_inst = res_block.add(l, .{ | |
| 1093 | .tag = .alloc, | |
| 1094 | .data = .{ .ty = .ptr_usize }, | |
| 1095 | }); | |
| 1096 | _ = res_block.add(l, .{ | |
| 1097 | .tag = .store, | |
| 1098 | .data = .{ .bin_op = .{ | |
| 1099 | .lhs = index_alloc_inst.toRef(), | |
| 1100 | .rhs = .zero_usize, | |
| 1101 | } }, | |
| 1102 | }); | |
| 1103 | ||
| 1104 | var loop: Loop = .init(l, &res_block); | |
| 1105 | loop.block = .init(res_block.stealRemainingCapacity()); | |
| 1106 | { | |
| 1107 | const cur_index_inst = loop.block.add(l, .{ | |
| 1108 | .tag = .load, | |
| 1109 | .data = .{ .ty_op = .{ | |
| 1110 | .ty = .usize_type, | |
| 1111 | .operand = index_alloc_inst.toRef(), | |
| 1112 | } }, | |
| 1113 | }); | |
| 1114 | const extra = l.extraData(Air.Bin, orig.data.ty_pl.payload).data; | |
| 1115 | const res_elem = loop.block.add(l, .{ | |
| 1116 | .tag = orig.tag, | |
| 1117 | .data = .{ .ty_pl = .{ | |
| 1118 | .ty = Air.internedToRef(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{ | |
| 1119 | .types = &.{ wrapped_res_scalar_ty.toIntern(), .u1_type }, | |
| 1120 | .values = &(.{.none} ** 2), | |
| 1121 | })), | |
| 1122 | .payload = try l.addExtra(Air.Bin, .{ | |
| 1123 | .lhs = loop.block.add(l, .{ | |
| 1124 | .tag = .array_elem_val, | |
| 1125 | .data = .{ .bin_op = .{ | |
| 1126 | .lhs = extra.lhs, | |
| 1127 | .rhs = cur_index_inst.toRef(), | |
| 1128 | } }, | |
| 1129 | }).toRef(), | |
| 1130 | .rhs = loop.block.add(l, .{ | |
| 1131 | .tag = .array_elem_val, | |
| 1132 | .data = .{ .bin_op = .{ | |
| 1133 | .lhs = extra.rhs, | |
| 1134 | .rhs = cur_index_inst.toRef(), | |
| 1135 | } }, | |
| 1136 | }).toRef(), | |
| 1137 | }), | |
| 1138 | } }, | |
| 1139 | }); | |
| 1140 | _ = loop.block.add(l, .{ | |
| 1141 | .tag = .vector_store_elem, | |
| 1142 | .data = .{ .vector_store_elem = .{ | |
| 1143 | .vector_ptr = ptr_overflow_res_inst.toRef(), | |
| 1144 | .payload = try l.addExtra(Air.Bin, .{ | |
| 1145 | .lhs = cur_index_inst.toRef(), | |
| 1146 | .rhs = loop.block.add(l, .{ | |
| 1147 | .tag = .struct_field_val, | |
| 1148 | .data = .{ .ty_pl = .{ | |
| 1149 | .ty = .u1_type, | |
| 1150 | .payload = try l.addExtra(Air.StructField, .{ | |
| 1151 | .struct_operand = res_elem.toRef(), | |
| 1152 | .field_index = 1, | |
| 1153 | }), | |
| 1154 | } }, | |
| 1155 | }).toRef(), | |
| 1156 | }), | |
| 1157 | } }, | |
| 1158 | }); | |
| 1159 | _ = loop.block.add(l, .{ | |
| 1160 | .tag = .vector_store_elem, | |
| 1161 | .data = .{ .vector_store_elem = .{ | |
| 1162 | .vector_ptr = ptr_wrapped_res_inst.toRef(), | |
| 1163 | .payload = try l.addExtra(Air.Bin, .{ | |
| 1164 | .lhs = cur_index_inst.toRef(), | |
| 1165 | .rhs = loop.block.add(l, .{ | |
| 1166 | .tag = .struct_field_val, | |
| 1167 | .data = .{ .ty_pl = .{ | |
| 1168 | .ty = Air.internedToRef(wrapped_res_scalar_ty.toIntern()), | |
| 1169 | .payload = try l.addExtra(Air.StructField, .{ | |
| 1170 | .struct_operand = res_elem.toRef(), | |
| 1171 | .field_index = 0, | |
| 1172 | }), | |
| 1173 | } }, | |
| 1174 | }).toRef(), | |
| 1175 | }), | |
| 1176 | } }, | |
| 1177 | }); | |
| 1178 | ||
| 1179 | var loop_cond_br: CondBr = .init(l, (try loop.block.addCmp( | |
| 1180 | l, | |
| 1181 | .lt, | |
| 1182 | cur_index_inst.toRef(), | |
| 1183 | try pt.intRef(.usize, res_len - 1), | |
| 1184 | .{}, | |
| 1185 | )).toRef(), &loop.block, .{}); | |
| 1186 | loop_cond_br.then_block = .init(loop.block.stealRemainingCapacity()); | |
| 1187 | { | |
| 1188 | _ = loop_cond_br.then_block.add(l, .{ | |
| 1189 | .tag = .store, | |
| 1190 | .data = .{ .bin_op = .{ | |
| 1191 | .lhs = index_alloc_inst.toRef(), | |
| 1192 | .rhs = loop_cond_br.then_block.add(l, .{ | |
| 1193 | .tag = .add, | |
| 1194 | .data = .{ .bin_op = .{ | |
| 1195 | .lhs = cur_index_inst.toRef(), | |
| 1196 | .rhs = .one_usize, | |
| 1197 | } }, | |
| 1198 | }).toRef(), | |
| 1199 | } }, | |
| 1200 | }); | |
| 1201 | _ = loop_cond_br.then_block.add(l, .{ | |
| 1202 | .tag = .repeat, | |
| 1203 | .data = .{ .repeat = .{ .loop_inst = loop.inst } }, | |
| 1204 | }); | |
| 95 | 1205 | } |
| 96 | }, | |
| 97 | ||
| 98 | .@"try", .try_cold => { | |
| 99 | const pl_op = data[@intFromEnum(inst)].pl_op; | |
| 100 | const extra = l.air.extraData(Air.Try, pl_op.payload); | |
| 101 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.body_len])); | |
| 102 | }, | |
| 103 | .try_ptr, .try_ptr_cold => { | |
| 104 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | |
| 105 | const extra = l.air.extraData(Air.TryPtr, ty_pl.payload); | |
| 106 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.body_len])); | |
| 107 | }, | |
| 108 | .block, .loop => { | |
| 109 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | |
| 110 | const extra = l.air.extraData(Air.Block, ty_pl.payload); | |
| 111 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.body_len])); | |
| 112 | }, | |
| 113 | .dbg_inline_block => { | |
| 114 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | |
| 115 | const extra = l.air.extraData(Air.DbgInlineBlock, ty_pl.payload); | |
| 116 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.body_len])); | |
| 117 | }, | |
| 118 | .cond_br => { | |
| 119 | const pl_op = data[@intFromEnum(inst)].pl_op; | |
| 120 | const extra = l.air.extraData(Air.CondBr, pl_op.payload); | |
| 121 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end..][0..extra.data.then_body_len])); | |
| 122 | try l.legalizeBody(@ptrCast(l.air.extra.items[extra.end + extra.data.then_body_len ..][0..extra.data.else_body_len])); | |
| 123 | }, | |
| 124 | .switch_br, .loop_switch_br => { | |
| 125 | const switch_br = l.air.unwrapSwitch(inst); | |
| 126 | var it = switch_br.iterateCases(); | |
| 127 | while (it.next()) |case| try l.legalizeBody(case.body); | |
| 128 | try l.legalizeBody(it.elseBody()); | |
| 129 | }, | |
| 1206 | loop_cond_br.else_block = .init(loop_cond_br.then_block.stealRemainingCapacity()); | |
| 1207 | _ = loop_cond_br.else_block.add(l, .{ | |
| 1208 | .tag = .br, | |
| 1209 | .data = .{ .br = .{ | |
| 1210 | .block_inst = orig_inst, | |
| 1211 | .operand = loop_cond_br.else_block.add(l, .{ | |
| 1212 | .tag = .load, | |
| 1213 | .data = .{ .ty_op = .{ | |
| 1214 | .ty = Air.internedToRef(res_ty.toIntern()), | |
| 1215 | .operand = res_alloc_inst.toRef(), | |
| 1216 | } }, | |
| 1217 | }).toRef(), | |
| 1218 | } }, | |
| 1219 | }); | |
| 1220 | try loop_cond_br.finish(l); | |
| 1221 | } | |
| 1222 | try loop.finish(l); | |
| 1223 | } | |
| 1224 | return .{ .ty_pl = .{ | |
| 1225 | .ty = Air.internedToRef(res_ty.toIntern()), | |
| 1226 | .payload = try l.addBlockBody(res_block.body()), | |
| 1227 | } }; | |
| 1228 | } | |
| 1229 | ||
| 1230 | fn safeIntcastBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Error!Air.Inst.Data { | |
| 1231 | const pt = l.pt; | |
| 1232 | const zcu = pt.zcu; | |
| 1233 | const ty_op = l.air_instructions.items(.data)[@intFromEnum(orig_inst)].ty_op; | |
| 1234 | ||
| 1235 | const operand_ref = ty_op.operand; | |
| 1236 | const operand_ty = l.typeOf(operand_ref); | |
| 1237 | const dest_ty = ty_op.ty.toType(); | |
| 1238 | ||
| 1239 | const is_vector = operand_ty.zigTypeTag(zcu) == .vector; | |
| 1240 | const operand_scalar_ty = operand_ty.scalarType(zcu); | |
| 1241 | const dest_scalar_ty = dest_ty.scalarType(zcu); | |
| 1242 | ||
| 1243 | assert(operand_scalar_ty.zigTypeTag(zcu) == .int); | |
| 1244 | const dest_is_enum = switch (dest_scalar_ty.zigTypeTag(zcu)) { | |
| 1245 | .int => false, | |
| 1246 | .@"enum" => true, | |
| 1247 | else => unreachable, | |
| 1248 | }; | |
| 1249 | ||
| 1250 | const operand_info = operand_scalar_ty.intInfo(zcu); | |
| 1251 | const dest_info = dest_scalar_ty.intInfo(zcu); | |
| 1252 | ||
| 1253 | const have_min_check, const have_max_check = c: { | |
| 1254 | const dest_pos_bits = dest_info.bits - @intFromBool(dest_info.signedness == .signed); | |
| 1255 | const operand_pos_bits = operand_info.bits - @intFromBool(operand_info.signedness == .signed); | |
| 1256 | const dest_allows_neg = dest_info.signedness == .signed and dest_info.bits > 0; | |
| 1257 | const operand_allows_neg = operand_info.signedness == .signed and operand_info.bits > 0; | |
| 1258 | break :c .{ | |
| 1259 | operand_allows_neg and (!dest_allows_neg or dest_info.bits < operand_info.bits), | |
| 1260 | dest_pos_bits < operand_pos_bits, | |
| 1261 | }; | |
| 130 | 1262 | }; |
| 1263 | ||
| 1264 | // The worst-case scenario in terms of total instructions and total condbrs is the case where | |
| 1265 | // the result type is an exhaustive enum whose tag type is smaller than the operand type: | |
| 1266 | // | |
| 1267 | // %x = block({ | |
| 1268 | // %1 = cmp_lt(%y, @min_allowed_int) | |
| 1269 | // %2 = cmp_gt(%y, @max_allowed_int) | |
| 1270 | // %3 = bool_or(%1, %2) | |
| 1271 | // %4 = cond_br(%3, { | |
| 1272 | // %5 = call(@panic.invalidEnumValue, []) | |
| 1273 | // %6 = unreach() | |
| 1274 | // }, { | |
| 1275 | // %7 = intcast(@res_ty, %y) | |
| 1276 | // %8 = is_named_enum_value(%7) | |
| 1277 | // %9 = cond_br(%8, { | |
| 1278 | // %10 = br(%x, %7) | |
| 1279 | // }, { | |
| 1280 | // %11 = call(@panic.invalidEnumValue, []) | |
| 1281 | // %12 = unreach() | |
| 1282 | // }) | |
| 1283 | // }) | |
| 1284 | // }) | |
| 1285 | // | |
| 1286 | // Note that vectors of enums don't exist -- the worst case for vectors is this: | |
| 1287 | // | |
| 1288 | // %x = block({ | |
| 1289 | // %1 = cmp_lt(%y, @min_allowed_int) | |
| 1290 | // %2 = cmp_gt(%y, @max_allowed_int) | |
| 1291 | // %3 = bool_or(%1, %2) | |
| 1292 | // %4 = reduce(%3, .@"or") | |
| 1293 | // %5 = cond_br(%4, { | |
| 1294 | // %6 = call(@panic.invalidEnumValue, []) | |
| 1295 | // %7 = unreach() | |
| 1296 | // }, { | |
| 1297 | // %8 = intcast(@res_ty, %y) | |
| 1298 | // %9 = br(%x, %8) | |
| 1299 | // }) | |
| 1300 | // }) | |
| 1301 | ||
| 1302 | var inst_buf: [12]Air.Inst.Index = undefined; | |
| 1303 | try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len); | |
| 1304 | var condbr_buf: [2]CondBr = undefined; | |
| 1305 | var condbr_idx: usize = 0; | |
| 1306 | ||
| 1307 | var main_block: Block = .init(&inst_buf); | |
| 1308 | var cur_block: *Block = &main_block; | |
| 1309 | ||
| 1310 | const panic_id: Zcu.SimplePanicId = if (dest_is_enum) .invalid_enum_value else .integer_out_of_bounds; | |
| 1311 | ||
| 1312 | if (have_min_check or have_max_check) { | |
| 1313 | const dest_int_ty = if (dest_is_enum) dest_ty.intTagType(zcu) else dest_ty; | |
| 1314 | const condbr = &condbr_buf[condbr_idx]; | |
| 1315 | condbr_idx += 1; | |
| 1316 | const below_min_inst: Air.Inst.Index = if (have_min_check) inst: { | |
| 1317 | const min_val_ref = Air.internedToRef((try dest_int_ty.minInt(pt, operand_ty)).toIntern()); | |
| 1318 | break :inst try cur_block.addCmp(l, .lt, operand_ref, min_val_ref, .{ .vector = is_vector }); | |
| 1319 | } else undefined; | |
| 1320 | const above_max_inst: Air.Inst.Index = if (have_max_check) inst: { | |
| 1321 | const max_val_ref = Air.internedToRef((try dest_int_ty.maxInt(pt, operand_ty)).toIntern()); | |
| 1322 | break :inst try cur_block.addCmp(l, .gt, operand_ref, max_val_ref, .{ .vector = is_vector }); | |
| 1323 | } else undefined; | |
| 1324 | const out_of_range_inst: Air.Inst.Index = inst: { | |
| 1325 | if (have_min_check and have_max_check) break :inst cur_block.add(l, .{ | |
| 1326 | .tag = .bool_or, | |
| 1327 | .data = .{ .bin_op = .{ | |
| 1328 | .lhs = below_min_inst.toRef(), | |
| 1329 | .rhs = above_max_inst.toRef(), | |
| 1330 | } }, | |
| 1331 | }); | |
| 1332 | if (have_min_check) break :inst below_min_inst; | |
| 1333 | if (have_max_check) break :inst above_max_inst; | |
| 1334 | unreachable; | |
| 1335 | }; | |
| 1336 | const scalar_out_of_range_inst: Air.Inst.Index = if (is_vector) cur_block.add(l, .{ | |
| 1337 | .tag = .reduce, | |
| 1338 | .data = .{ .reduce = .{ | |
| 1339 | .operand = out_of_range_inst.toRef(), | |
| 1340 | .operation = .Or, | |
| 1341 | } }, | |
| 1342 | }) else out_of_range_inst; | |
| 1343 | condbr.* = .init(l, scalar_out_of_range_inst.toRef(), cur_block, .{ .true = .cold }); | |
| 1344 | condbr.then_block = .init(cur_block.stealRemainingCapacity()); | |
| 1345 | try condbr.then_block.addPanic(l, panic_id); | |
| 1346 | condbr.else_block = .init(condbr.then_block.stealRemainingCapacity()); | |
| 1347 | cur_block = &condbr.else_block; | |
| 1348 | } | |
| 1349 | ||
| 1350 | // Now we know we're in-range, we can intcast: | |
| 1351 | const cast_inst = cur_block.add(l, .{ | |
| 1352 | .tag = .intcast, | |
| 1353 | .data = .{ .ty_op = .{ | |
| 1354 | .ty = Air.internedToRef(dest_ty.toIntern()), | |
| 1355 | .operand = operand_ref, | |
| 1356 | } }, | |
| 1357 | }); | |
| 1358 | // For ints we're already done, but for exhaustive enums we must check this is a valid tag. | |
| 1359 | if (dest_is_enum and !dest_ty.isNonexhaustiveEnum(zcu) and zcu.backendSupportsFeature(.is_named_enum_value)) { | |
| 1360 | assert(!is_vector); // vectors of enums don't exist | |
| 1361 | // We are building this: | |
| 1362 | // %1 = is_named_enum_value(%cast_inst) | |
| 1363 | // %2 = cond_br(%1, { | |
| 1364 | // <new cursor> | |
| 1365 | // }, { | |
| 1366 | // <panic> | |
| 1367 | // }) | |
| 1368 | const is_named_inst = cur_block.add(l, .{ | |
| 1369 | .tag = .is_named_enum_value, | |
| 1370 | .data = .{ .un_op = cast_inst.toRef() }, | |
| 1371 | }); | |
| 1372 | const condbr = &condbr_buf[condbr_idx]; | |
| 1373 | condbr_idx += 1; | |
| 1374 | condbr.* = .init(l, is_named_inst.toRef(), cur_block, .{ .false = .cold }); | |
| 1375 | condbr.else_block = .init(cur_block.stealRemainingCapacity()); | |
| 1376 | try condbr.else_block.addPanic(l, panic_id); | |
| 1377 | condbr.then_block = .init(condbr.else_block.stealRemainingCapacity()); | |
| 1378 | cur_block = &condbr.then_block; | |
| 1379 | } | |
| 1380 | // Finally, just `br` to our outer `block`. | |
| 1381 | _ = cur_block.add(l, .{ | |
| 1382 | .tag = .br, | |
| 1383 | .data = .{ .br = .{ | |
| 1384 | .block_inst = orig_inst, | |
| 1385 | .operand = cast_inst.toRef(), | |
| 1386 | } }, | |
| 1387 | }); | |
| 1388 | // We might not have used all of the instructions; that's intentional. | |
| 1389 | _ = cur_block.stealRemainingCapacity(); | |
| 1390 | ||
| 1391 | for (condbr_buf[0..condbr_idx]) |*condbr| try condbr.finish(l); | |
| 1392 | return .{ .ty_pl = .{ | |
| 1393 | .ty = Air.internedToRef(dest_ty.toIntern()), | |
| 1394 | .payload = try l.addBlockBody(main_block.body()), | |
| 1395 | } }; | |
| 1396 | } | |
| 1397 | fn safeArithmeticBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, overflow_op_tag: Air.Inst.Tag) Error!Air.Inst.Data { | |
| 1398 | const pt = l.pt; | |
| 1399 | const zcu = pt.zcu; | |
| 1400 | const bin_op = l.air_instructions.items(.data)[@intFromEnum(orig_inst)].bin_op; | |
| 1401 | ||
| 1402 | const operand_ty = l.typeOf(bin_op.lhs); | |
| 1403 | assert(l.typeOf(bin_op.rhs).toIntern() == operand_ty.toIntern()); | |
| 1404 | const is_vector = operand_ty.zigTypeTag(zcu) == .vector; | |
| 1405 | ||
| 1406 | const overflow_tuple_ty = try pt.overflowArithmeticTupleType(operand_ty); | |
| 1407 | const overflow_bits_ty = overflow_tuple_ty.fieldType(1, zcu); | |
| 1408 | ||
| 1409 | // The worst-case scenario is a vector operand: | |
| 1410 | // | |
| 1411 | // %1 = add_with_overflow(%x, %y) | |
| 1412 | // %2 = struct_field_val(%1, .@"1") | |
| 1413 | // %3 = reduce(%2, .@"or") | |
| 1414 | // %4 = bitcast(%3, @bool_type) | |
| 1415 | // %5 = cond_br(%4, { | |
| 1416 | // %6 = call(@panic.integerOverflow, []) | |
| 1417 | // %7 = unreach() | |
| 1418 | // }, { | |
| 1419 | // %8 = struct_field_val(%1, .@"0") | |
| 1420 | // %9 = br(%z, %8) | |
| 1421 | // }) | |
| 1422 | var inst_buf: [9]Air.Inst.Index = undefined; | |
| 1423 | try l.air_instructions.ensureUnusedCapacity(zcu.gpa, inst_buf.len); | |
| 1424 | ||
| 1425 | var main_block: Block = .init(&inst_buf); | |
| 1426 | ||
| 1427 | const overflow_op_inst = main_block.add(l, .{ | |
| 1428 | .tag = overflow_op_tag, | |
| 1429 | .data = .{ .ty_pl = .{ | |
| 1430 | .ty = Air.internedToRef(overflow_tuple_ty.toIntern()), | |
| 1431 | .payload = try l.addExtra(Air.Bin, .{ | |
| 1432 | .lhs = bin_op.lhs, | |
| 1433 | .rhs = bin_op.rhs, | |
| 1434 | }), | |
| 1435 | } }, | |
| 1436 | }); | |
| 1437 | const overflow_bits_inst = main_block.add(l, .{ | |
| 1438 | .tag = .struct_field_val, | |
| 1439 | .data = .{ .ty_pl = .{ | |
| 1440 | .ty = Air.internedToRef(overflow_bits_ty.toIntern()), | |
| 1441 | .payload = try l.addExtra(Air.StructField, .{ | |
| 1442 | .struct_operand = overflow_op_inst.toRef(), | |
| 1443 | .field_index = 1, | |
| 1444 | }), | |
| 1445 | } }, | |
| 1446 | }); | |
| 1447 | const any_overflow_bit_inst = if (is_vector) main_block.add(l, .{ | |
| 1448 | .tag = .reduce, | |
| 1449 | .data = .{ .reduce = .{ | |
| 1450 | .operand = overflow_bits_inst.toRef(), | |
| 1451 | .operation = .Or, | |
| 1452 | } }, | |
| 1453 | }) else overflow_bits_inst; | |
| 1454 | const any_overflow_inst = try main_block.addCmp(l, .eq, any_overflow_bit_inst.toRef(), .one_u1, .{}); | |
| 1455 | ||
| 1456 | var condbr: CondBr = .init(l, any_overflow_inst.toRef(), &main_block, .{ .true = .cold }); | |
| 1457 | condbr.then_block = .init(main_block.stealRemainingCapacity()); | |
| 1458 | try condbr.then_block.addPanic(l, .integer_overflow); | |
| 1459 | condbr.else_block = .init(condbr.then_block.stealRemainingCapacity()); | |
| 1460 | ||
| 1461 | const result_inst = condbr.else_block.add(l, .{ | |
| 1462 | .tag = .struct_field_val, | |
| 1463 | .data = .{ .ty_pl = .{ | |
| 1464 | .ty = Air.internedToRef(operand_ty.toIntern()), | |
| 1465 | .payload = try l.addExtra(Air.StructField, .{ | |
| 1466 | .struct_operand = overflow_op_inst.toRef(), | |
| 1467 | .field_index = 0, | |
| 1468 | }), | |
| 1469 | } }, | |
| 1470 | }); | |
| 1471 | _ = condbr.else_block.add(l, .{ | |
| 1472 | .tag = .br, | |
| 1473 | .data = .{ .br = .{ | |
| 1474 | .block_inst = orig_inst, | |
| 1475 | .operand = result_inst.toRef(), | |
| 1476 | } }, | |
| 1477 | }); | |
| 1478 | // We might not have used all of the instructions; that's intentional. | |
| 1479 | _ = condbr.else_block.stealRemainingCapacity(); | |
| 1480 | ||
| 1481 | try condbr.finish(l); | |
| 1482 | return .{ .ty_pl = .{ | |
| 1483 | .ty = Air.internedToRef(operand_ty.toIntern()), | |
| 1484 | .payload = try l.addBlockBody(main_block.body()), | |
| 1485 | } }; | |
| 1486 | } | |
| 1487 | ||
| 1488 | const Block = struct { | |
| 1489 | instructions: []Air.Inst.Index, | |
| 1490 | len: usize, | |
| 1491 | ||
| 1492 | /// There are two common usages of the API: | |
| 1493 | /// * `buf.len` is exactly the number of instructions which will be in this block | |
| 1494 | /// * `buf.len` is no smaller than necessary, and `b.stealRemainingCapacity` will be used | |
| 1495 | fn init(buf: []Air.Inst.Index) Block { | |
| 1496 | return .{ | |
| 1497 | .instructions = buf, | |
| 1498 | .len = 0, | |
| 1499 | }; | |
| 1500 | } | |
| 1501 | ||
| 1502 | /// Like `Legalize.addInstAssumeCapacity`, but also appends the instruction to `b`. | |
| 1503 | fn add(b: *Block, l: *Legalize, inst_data: Air.Inst) Air.Inst.Index { | |
| 1504 | const inst = l.addInstAssumeCapacity(inst_data); | |
| 1505 | b.instructions[b.len] = inst; | |
| 1506 | b.len += 1; | |
| 1507 | return inst; | |
| 1508 | } | |
| 1509 | ||
| 1510 | /// Adds the code to call the panic handler `panic_id`. This is usually `.call` then `.unreach`, | |
| 1511 | /// but if `Zcu.Feature.panic_fn` is unsupported, we lower to `.trap` instead. | |
| 1512 | fn addPanic(b: *Block, l: *Legalize, panic_id: Zcu.SimplePanicId) Error!void { | |
| 1513 | const zcu = l.pt.zcu; | |
| 1514 | if (!zcu.backendSupportsFeature(.panic_fn)) { | |
| 1515 | _ = b.add(l, .{ | |
| 1516 | .tag = .trap, | |
| 1517 | .data = .{ .no_op = {} }, | |
| 1518 | }); | |
| 1519 | return; | |
| 1520 | } | |
| 1521 | const panic_fn_val = zcu.builtin_decl_values.get(panic_id.toBuiltin()); | |
| 1522 | _ = b.add(l, .{ | |
| 1523 | .tag = .call, | |
| 1524 | .data = .{ .pl_op = .{ | |
| 1525 | .operand = Air.internedToRef(panic_fn_val), | |
| 1526 | .payload = try l.addExtra(Air.Call, .{ .args_len = 0 }), | |
| 1527 | } }, | |
| 1528 | }); | |
| 1529 | _ = b.add(l, .{ | |
| 1530 | .tag = .unreach, | |
| 1531 | .data = .{ .no_op = {} }, | |
| 1532 | }); | |
| 1533 | } | |
| 1534 | ||
| 1535 | /// Adds a `cmp_*` instruction (including maybe `cmp_vector`) to `b`. This is a fairly thin wrapper | |
| 1536 | /// around `add`, although it does compute the result type if `is_vector` (`@Vector(n, bool)`). | |
| 1537 | fn addCmp( | |
| 1538 | b: *Block, | |
| 1539 | l: *Legalize, | |
| 1540 | op: std.math.CompareOperator, | |
| 1541 | lhs: Air.Inst.Ref, | |
| 1542 | rhs: Air.Inst.Ref, | |
| 1543 | opts: struct { optimized: bool = false, vector: bool = false }, | |
| 1544 | ) Error!Air.Inst.Index { | |
| 1545 | const pt = l.pt; | |
| 1546 | if (opts.vector) { | |
| 1547 | const bool_vec_ty = try pt.vectorType(.{ | |
| 1548 | .child = .bool_type, | |
| 1549 | .len = l.typeOf(lhs).vectorLen(pt.zcu), | |
| 1550 | }); | |
| 1551 | return b.add(l, .{ | |
| 1552 | .tag = if (opts.optimized) .cmp_vector_optimized else .cmp_vector, | |
| 1553 | .data = .{ .ty_pl = .{ | |
| 1554 | .ty = Air.internedToRef(bool_vec_ty.toIntern()), | |
| 1555 | .payload = try l.addExtra(Air.VectorCmp, .{ | |
| 1556 | .lhs = lhs, | |
| 1557 | .rhs = rhs, | |
| 1558 | .op = Air.VectorCmp.encodeOp(op), | |
| 1559 | }), | |
| 1560 | } }, | |
| 1561 | }); | |
| 1562 | } | |
| 1563 | return b.add(l, .{ | |
| 1564 | .tag = switch (op) { | |
| 1565 | .lt => if (opts.optimized) .cmp_lt_optimized else .cmp_lt, | |
| 1566 | .lte => if (opts.optimized) .cmp_lte_optimized else .cmp_lte, | |
| 1567 | .eq => if (opts.optimized) .cmp_eq_optimized else .cmp_eq, | |
| 1568 | .gte => if (opts.optimized) .cmp_gte_optimized else .cmp_gte, | |
| 1569 | .gt => if (opts.optimized) .cmp_gt_optimized else .cmp_gt, | |
| 1570 | .neq => if (opts.optimized) .cmp_neq_optimized else .cmp_neq, | |
| 1571 | }, | |
| 1572 | .data = .{ .bin_op = .{ | |
| 1573 | .lhs = lhs, | |
| 1574 | .rhs = rhs, | |
| 1575 | } }, | |
| 1576 | }); | |
| 1577 | } | |
| 1578 | ||
| 1579 | /// Returns the unused capacity of `b.instructions`, and shrinks `b.instructions` down to `b.len`. | |
| 1580 | /// This is useful when you've provided a buffer big enough for all your instructions, but you are | |
| 1581 | /// now starting a new block and some of them need to live there instead. | |
| 1582 | fn stealRemainingCapacity(b: *Block) []Air.Inst.Index { | |
| 1583 | return b.stealFrom(b.len); | |
| 1584 | } | |
| 1585 | ||
| 1586 | /// Returns `len` elements taken from the unused capacity of `b.instructions`, and shrinks | |
| 1587 | /// `b.instructions` down to not include them anymore. | |
| 1588 | /// This is useful when you've provided a buffer big enough for all your instructions, but you are | |
| 1589 | /// now starting a new block and some of them need to live there instead. | |
| 1590 | fn stealCapacity(b: *Block, len: usize) []Air.Inst.Index { | |
| 1591 | return b.stealFrom(b.instructions.len - len); | |
| 1592 | } | |
| 1593 | ||
| 1594 | fn stealFrom(b: *Block, start: usize) []Air.Inst.Index { | |
| 1595 | assert(start >= b.len); | |
| 1596 | defer b.instructions.len = start; | |
| 1597 | return b.instructions[start..]; | |
| 1598 | } | |
| 1599 | ||
| 1600 | fn body(b: *const Block) []const Air.Inst.Index { | |
| 1601 | assert(b.len == b.instructions.len); | |
| 1602 | return b.instructions; | |
| 1603 | } | |
| 1604 | }; | |
| 1605 | ||
| 1606 | const Result = struct { | |
| 1607 | inst: Air.Inst.Index, | |
| 1608 | block: Block, | |
| 1609 | ||
| 1610 | /// The return value has `block` initialized to `undefined`; it is the caller's reponsibility | |
| 1611 | /// to initialize it. | |
| 1612 | fn init(l: *Legalize, ty: Type, parent_block: *Block) Result { | |
| 1613 | return .{ | |
| 1614 | .inst = parent_block.add(l, .{ | |
| 1615 | .tag = .block, | |
| 1616 | .data = .{ .ty_pl = .{ | |
| 1617 | .ty = Air.internedToRef(ty.toIntern()), | |
| 1618 | .payload = undefined, | |
| 1619 | } }, | |
| 1620 | }), | |
| 1621 | .block = undefined, | |
| 1622 | }; | |
| 1623 | } | |
| 1624 | ||
| 1625 | fn finish(res: Result, l: *Legalize) Error!void { | |
| 1626 | const data = &l.air_instructions.items(.data)[@intFromEnum(res.inst)]; | |
| 1627 | data.ty_pl.payload = try l.addBlockBody(res.block.body()); | |
| 1628 | } | |
| 1629 | }; | |
| 1630 | ||
| 1631 | const Loop = struct { | |
| 1632 | inst: Air.Inst.Index, | |
| 1633 | block: Block, | |
| 1634 | ||
| 1635 | /// The return value has `block` initialized to `undefined`; it is the caller's reponsibility | |
| 1636 | /// to initialize it. | |
| 1637 | fn init(l: *Legalize, parent_block: *Block) Loop { | |
| 1638 | return .{ | |
| 1639 | .inst = parent_block.add(l, .{ | |
| 1640 | .tag = .loop, | |
| 1641 | .data = .{ .ty_pl = .{ | |
| 1642 | .ty = .noreturn_type, | |
| 1643 | .payload = undefined, | |
| 1644 | } }, | |
| 1645 | }), | |
| 1646 | .block = undefined, | |
| 1647 | }; | |
| 1648 | } | |
| 1649 | ||
| 1650 | fn finish(loop: Loop, l: *Legalize) Error!void { | |
| 1651 | const data = &l.air_instructions.items(.data)[@intFromEnum(loop.inst)]; | |
| 1652 | data.ty_pl.payload = try l.addBlockBody(loop.block.body()); | |
| 1653 | } | |
| 1654 | }; | |
| 1655 | ||
| 1656 | const CondBr = struct { | |
| 1657 | inst: Air.Inst.Index, | |
| 1658 | hints: Air.CondBr.BranchHints, | |
| 1659 | then_block: Block, | |
| 1660 | else_block: Block, | |
| 1661 | ||
| 1662 | /// The return value has `then_block` and `else_block` initialized to `undefined`; it is the | |
| 1663 | /// caller's reponsibility to initialize them. | |
| 1664 | fn init(l: *Legalize, operand: Air.Inst.Ref, parent_block: *Block, hints: Air.CondBr.BranchHints) CondBr { | |
| 1665 | return .{ | |
| 1666 | .inst = parent_block.add(l, .{ | |
| 1667 | .tag = .cond_br, | |
| 1668 | .data = .{ .pl_op = .{ | |
| 1669 | .operand = operand, | |
| 1670 | .payload = undefined, | |
| 1671 | } }, | |
| 1672 | }), | |
| 1673 | .hints = hints, | |
| 1674 | .then_block = undefined, | |
| 1675 | .else_block = undefined, | |
| 1676 | }; | |
| 1677 | } | |
| 1678 | ||
| 1679 | fn finish(cond_br: CondBr, l: *Legalize) Error!void { | |
| 1680 | const then_body = cond_br.then_block.body(); | |
| 1681 | const else_body = cond_br.else_block.body(); | |
| 1682 | try l.air_extra.ensureUnusedCapacity(l.pt.zcu.gpa, 3 + then_body.len + else_body.len); | |
| 1683 | ||
| 1684 | const data = &l.air_instructions.items(.data)[@intFromEnum(cond_br.inst)]; | |
| 1685 | data.pl_op.payload = @intCast(l.air_extra.items.len); | |
| 1686 | l.air_extra.appendSliceAssumeCapacity(&.{ | |
| 1687 | @intCast(then_body.len), | |
| 1688 | @intCast(else_body.len), | |
| 1689 | @bitCast(cond_br.hints), | |
| 1690 | }); | |
| 1691 | l.air_extra.appendSliceAssumeCapacity(@ptrCast(then_body)); | |
| 1692 | l.air_extra.appendSliceAssumeCapacity(@ptrCast(else_body)); | |
| 1693 | } | |
| 1694 | }; | |
| 1695 | ||
| 1696 | fn addInstAssumeCapacity(l: *Legalize, inst: Air.Inst) Air.Inst.Index { | |
| 1697 | defer l.air_instructions.appendAssumeCapacity(inst); | |
| 1698 | return @enumFromInt(l.air_instructions.len); | |
| 1699 | } | |
| 1700 | ||
| 1701 | fn addExtra(l: *Legalize, comptime Extra: type, extra: Extra) Error!u32 { | |
| 1702 | const extra_fields = @typeInfo(Extra).@"struct".fields; | |
| 1703 | try l.air_extra.ensureUnusedCapacity(l.pt.zcu.gpa, extra_fields.len); | |
| 1704 | defer inline for (extra_fields) |field| l.air_extra.appendAssumeCapacity(switch (field.type) { | |
| 1705 | u32 => @field(extra, field.name), | |
| 1706 | Air.Inst.Ref => @intFromEnum(@field(extra, field.name)), | |
| 1707 | else => @compileError(@typeName(field.type)), | |
| 1708 | }); | |
| 1709 | return @intCast(l.air_extra.items.len); | |
| 1710 | } | |
| 1711 | ||
| 1712 | fn addBlockBody(l: *Legalize, body: []const Air.Inst.Index) Error!u32 { | |
| 1713 | try l.air_extra.ensureUnusedCapacity(l.pt.zcu.gpa, 1 + body.len); | |
| 1714 | defer { | |
| 1715 | l.air_extra.appendAssumeCapacity(@intCast(body.len)); | |
| 1716 | l.air_extra.appendSliceAssumeCapacity(@ptrCast(body)); | |
| 1717 | } | |
| 1718 | return @intCast(l.air_extra.items.len); | |
| 131 | 1719 | } |
| 132 | 1720 | |
| 133 | // inline to propagate comptime `tag`s | |
| 134 | inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag { | |
| 135 | const ip = &l.zcu.intern_pool; | |
| 136 | const orig_ty = if (std.debug.runtime_safety) l.air.typeOfIndex(inst, ip) else {}; | |
| 137 | l.air.instructions.items(.tag)[@intFromEnum(inst)] = tag; | |
| 138 | l.air.instructions.items(.data)[@intFromEnum(inst)] = data; | |
| 139 | if (std.debug.runtime_safety) std.debug.assert(l.air.typeOfIndex(inst, ip).toIntern() == orig_ty.toIntern()); | |
| 1721 | /// Returns `tag` to remind the caller to `continue :inst` the result. | |
| 1722 | /// This is inline to propagate the comptime-known `tag`. | |
| 1723 | inline fn replaceInst(l: *Legalize, inst: Air.Inst.Index, comptime tag: Air.Inst.Tag, data: Air.Inst.Data) Air.Inst.Tag { | |
| 1724 | const orig_ty = if (std.debug.runtime_safety) l.typeOfIndex(inst) else {}; | |
| 1725 | l.air_instructions.set(@intFromEnum(inst), .{ .tag = tag, .data = data }); | |
| 1726 | if (std.debug.runtime_safety) assert(l.typeOfIndex(inst).toIntern() == orig_ty.toIntern()); | |
| 140 | 1727 | return tag; |
| 141 | 1728 | } |
| 142 | 1729 | |
| 143 | 1730 | const Air = @import("../Air.zig"); |
| 144 | const codegen = @import("../codegen.zig"); | |
| 1731 | const assert = std.debug.assert; | |
| 1732 | const dev = @import("../dev.zig"); | |
| 1733 | const InternPool = @import("../InternPool.zig"); | |
| 145 | 1734 | const Legalize = @This(); |
| 146 | 1735 | const std = @import("std"); |
| 1736 | const Type = @import("../Type.zig"); | |
| 147 | 1737 | const Zcu = @import("../Zcu.zig"); |
src/Air/Liveness.zig+24-9| ... | ... | @@ -15,6 +15,7 @@ const Liveness = @This(); |
| 15 | 15 | const trace = @import("../tracy.zig").trace; |
| 16 | 16 | const Air = @import("../Air.zig"); |
| 17 | 17 | const InternPool = @import("../InternPool.zig"); |
| 18 | const Zcu = @import("../Zcu.zig"); | |
| 18 | 19 | |
| 19 | 20 | pub const Verify = @import("Liveness/Verify.zig"); |
| 20 | 21 | |
| ... | ... | @@ -136,12 +137,15 @@ fn LivenessPassData(comptime pass: LivenessPass) type { |
| 136 | 137 | }; |
| 137 | 138 | } |
| 138 | 139 | |
| 139 | pub fn analyze(gpa: Allocator, air: Air, intern_pool: *InternPool) Allocator.Error!Liveness { | |
| 140 | pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Liveness { | |
| 140 | 141 | const tracy = trace(@src()); |
| 141 | 142 | defer tracy.end(); |
| 142 | 143 | |
| 144 | const gpa = zcu.gpa; | |
| 145 | ||
| 143 | 146 | var a: Analysis = .{ |
| 144 | 147 | .gpa = gpa, |
| 148 | .zcu = zcu, | |
| 145 | 149 | .air = air, |
| 146 | 150 | .tomb_bits = try gpa.alloc( |
| 147 | 151 | usize, |
| ... | ... | @@ -220,6 +224,7 @@ const OperandCategory = enum { |
| 220 | 224 | pub fn categorizeOperand( |
| 221 | 225 | l: Liveness, |
| 222 | 226 | air: Air, |
| 227 | zcu: *Zcu, | |
| 223 | 228 | inst: Air.Inst.Index, |
| 224 | 229 | operand: Air.Inst.Index, |
| 225 | 230 | ip: *const InternPool, |
| ... | ... | @@ -511,10 +516,15 @@ pub fn categorizeOperand( |
| 511 | 516 | if (extra.rhs == operand_ref) return matchOperandSmallIndex(l, inst, 2, .none); |
| 512 | 517 | return .none; |
| 513 | 518 | }, |
| 514 | .shuffle => { | |
| 515 | const extra = air.extraData(Air.Shuffle, air_datas[@intFromEnum(inst)].ty_pl.payload).data; | |
| 516 | if (extra.a == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); | |
| 517 | if (extra.b == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none); | |
| 519 | .shuffle_one => { | |
| 520 | const unwrapped = air.unwrapShuffleOne(zcu, inst); | |
| 521 | if (unwrapped.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); | |
| 522 | return .none; | |
| 523 | }, | |
| 524 | .shuffle_two => { | |
| 525 | const unwrapped = air.unwrapShuffleTwo(zcu, inst); | |
| 526 | if (unwrapped.operand_a == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); | |
| 527 | if (unwrapped.operand_b == operand_ref) return matchOperandSmallIndex(l, inst, 1, .none); | |
| 518 | 528 | return .none; |
| 519 | 529 | }, |
| 520 | 530 | .reduce, .reduce_optimized => { |
| ... | ... | @@ -639,7 +649,7 @@ pub fn categorizeOperand( |
| 639 | 649 | |
| 640 | 650 | var operand_live: bool = true; |
| 641 | 651 | for (&[_]Air.Inst.Index{ then_body[0], else_body[0] }) |cond_inst| { |
| 642 | if (l.categorizeOperand(air, cond_inst, operand, ip) == .tomb) | |
| 652 | if (l.categorizeOperand(air, zcu, cond_inst, operand, ip) == .tomb) | |
| 643 | 653 | operand_live = false; |
| 644 | 654 | |
| 645 | 655 | switch (air_tags[@intFromEnum(cond_inst)]) { |
| ... | ... | @@ -824,6 +834,7 @@ pub const BigTomb = struct { |
| 824 | 834 | /// In-progress data; on successful analysis converted into `Liveness`. |
| 825 | 835 | const Analysis = struct { |
| 826 | 836 | gpa: Allocator, |
| 837 | zcu: *Zcu, | |
| 827 | 838 | air: Air, |
| 828 | 839 | intern_pool: *InternPool, |
| 829 | 840 | tomb_bits: []usize, |
| ... | ... | @@ -1119,9 +1130,13 @@ fn analyzeInst( |
| 1119 | 1130 | const extra = a.air.extraData(Air.Bin, pl_op.payload).data; |
| 1120 | 1131 | return analyzeOperands(a, pass, data, inst, .{ pl_op.operand, extra.lhs, extra.rhs }); |
| 1121 | 1132 | }, |
| 1122 | .shuffle => { | |
| 1123 | const extra = a.air.extraData(Air.Shuffle, inst_datas[@intFromEnum(inst)].ty_pl.payload).data; | |
| 1124 | return analyzeOperands(a, pass, data, inst, .{ extra.a, extra.b, .none }); | |
| 1133 | .shuffle_one => { | |
| 1134 | const unwrapped = a.air.unwrapShuffleOne(a.zcu, inst); | |
| 1135 | return analyzeOperands(a, pass, data, inst, .{ unwrapped.operand, .none, .none }); | |
| 1136 | }, | |
| 1137 | .shuffle_two => { | |
| 1138 | const unwrapped = a.air.unwrapShuffleTwo(a.zcu, inst); | |
| 1139 | return analyzeOperands(a, pass, data, inst, .{ unwrapped.operand_a, unwrapped.operand_b, .none }); | |
| 1125 | 1140 | }, |
| 1126 | 1141 | .reduce, .reduce_optimized => { |
| 1127 | 1142 | const reduce = inst_datas[@intFromEnum(inst)].reduce; |
src/Air/Liveness/Verify.zig+9-4| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | //! Verifies that Liveness information is valid. |
| 2 | 2 | |
| 3 | 3 | gpa: std.mem.Allocator, |
| 4 | zcu: *Zcu, | |
| 4 | 5 | air: Air, |
| 5 | 6 | liveness: Liveness, |
| 6 | 7 | live: LiveMap = .{}, |
| ... | ... | @@ -287,10 +288,13 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { |
| 287 | 288 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 288 | 289 | try self.verifyInstOperands(inst, .{ extra.lhs, extra.rhs, .none }); |
| 289 | 290 | }, |
| 290 | .shuffle => { | |
| 291 | const ty_pl = data[@intFromEnum(inst)].ty_pl; | |
| 292 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; | |
| 293 | try self.verifyInstOperands(inst, .{ extra.a, extra.b, .none }); | |
| 291 | .shuffle_one => { | |
| 292 | const unwrapped = self.air.unwrapShuffleOne(self.zcu, inst); | |
| 293 | try self.verifyInstOperands(inst, .{ unwrapped.operand, .none, .none }); | |
| 294 | }, | |
| 295 | .shuffle_two => { | |
| 296 | const unwrapped = self.air.unwrapShuffleTwo(self.zcu, inst); | |
| 297 | try self.verifyInstOperands(inst, .{ unwrapped.operand_a, unwrapped.operand_b, .none }); | |
| 294 | 298 | }, |
| 295 | 299 | .cmp_vector, |
| 296 | 300 | .cmp_vector_optimized, |
| ... | ... | @@ -639,4 +643,5 @@ const log = std.log.scoped(.liveness_verify); |
| 639 | 643 | const Air = @import("../../Air.zig"); |
| 640 | 644 | const Liveness = @import("../Liveness.zig"); |
| 641 | 645 | const InternPool = @import("../../InternPool.zig"); |
| 646 | const Zcu = @import("../../Zcu.zig"); | |
| 642 | 647 | const Verify = @This(); |
src/Air/types_resolved.zig+16-6| ... | ... | @@ -249,12 +249,22 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool { |
| 249 | 249 | if (!checkRef(extra.struct_operand, zcu)) return false; |
| 250 | 250 | }, |
| 251 | 251 | |
| 252 | .shuffle => { | |
| 253 | const extra = air.extraData(Air.Shuffle, data.ty_pl.payload).data; | |
| 254 | if (!checkType(data.ty_pl.ty.toType(), zcu)) return false; | |
| 255 | if (!checkRef(extra.a, zcu)) return false; | |
| 256 | if (!checkRef(extra.b, zcu)) return false; | |
| 257 | if (!checkVal(Value.fromInterned(extra.mask), zcu)) return false; | |
| 252 | .shuffle_one => { | |
| 253 | const unwrapped = air.unwrapShuffleOne(zcu, inst); | |
| 254 | if (!checkType(unwrapped.result_ty, zcu)) return false; | |
| 255 | if (!checkRef(unwrapped.operand, zcu)) return false; | |
| 256 | for (unwrapped.mask) |m| switch (m.unwrap()) { | |
| 257 | .elem => {}, | |
| 258 | .value => |val| if (!checkVal(.fromInterned(val), zcu)) return false, | |
| 259 | }; | |
| 260 | }, | |
| 261 | ||
| 262 | .shuffle_two => { | |
| 263 | const unwrapped = air.unwrapShuffleTwo(zcu, inst); | |
| 264 | if (!checkType(unwrapped.result_ty, zcu)) return false; | |
| 265 | if (!checkRef(unwrapped.operand_a, zcu)) return false; | |
| 266 | if (!checkRef(unwrapped.operand_b, zcu)) return false; | |
| 267 | // No values to check because there are no comptime-known values other than undef | |
| 258 | 268 | }, |
| 259 | 269 | |
| 260 | 270 | .cmpxchg_weak, |
src/Compilation.zig+1-1| ... | ... | @@ -2529,6 +2529,7 @@ pub fn destroy(comp: *Compilation) void { |
| 2529 | 2529 | |
| 2530 | 2530 | pub fn clearMiscFailures(comp: *Compilation) void { |
| 2531 | 2531 | comp.alloc_failure_occurred = false; |
| 2532 | comp.link_diags.flags = .{}; | |
| 2532 | 2533 | for (comp.misc_failures.values()) |*value| { |
| 2533 | 2534 | value.deinit(comp.gpa); |
| 2534 | 2535 | } |
| ... | ... | @@ -2795,7 +2796,6 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void { |
| 2795 | 2796 | |
| 2796 | 2797 | if (anyErrors(comp)) { |
| 2797 | 2798 | // Skip flushing and keep source files loaded for error reporting. |
| 2798 | comp.link_diags.flags = .{}; | |
| 2799 | 2799 | return; |
| 2800 | 2800 | } |
| 2801 | 2801 |
src/InternPool.zig+60-24| ... | ... | @@ -4579,10 +4579,11 @@ pub const Index = enum(u32) { |
| 4579 | 4579 | undefined_type, |
| 4580 | 4580 | enum_literal_type, |
| 4581 | 4581 | |
| 4582 | ptr_usize_type, | |
| 4583 | ptr_const_comptime_int_type, | |
| 4582 | 4584 | manyptr_u8_type, |
| 4583 | 4585 | manyptr_const_u8_type, |
| 4584 | 4586 | manyptr_const_u8_sentinel_0_type, |
| 4585 | single_const_pointer_to_comptime_int_type, | |
| 4586 | 4587 | slice_const_u8_type, |
| 4587 | 4588 | slice_const_u8_sentinel_0_type, |
| 4588 | 4589 | |
| ... | ... | @@ -4649,19 +4650,29 @@ pub const Index = enum(u32) { |
| 4649 | 4650 | |
| 4650 | 4651 | /// `undefined` (untyped) |
| 4651 | 4652 | undef, |
| 4653 | /// `@as(bool, undefined)` | |
| 4654 | undef_bool, | |
| 4655 | /// `@as(usize, undefined)` | |
| 4656 | undef_usize, | |
| 4657 | /// `@as(u1, undefined)` | |
| 4658 | undef_u1, | |
| 4652 | 4659 | /// `0` (comptime_int) |
| 4653 | 4660 | zero, |
| 4654 | /// `0` (usize) | |
| 4661 | /// `@as(usize, 0)` | |
| 4655 | 4662 | zero_usize, |
| 4656 | /// `0` (u8) | |
| 4663 | /// `@as(u1, 0)` | |
| 4664 | zero_u1, | |
| 4665 | /// `@as(u8, 0)` | |
| 4657 | 4666 | zero_u8, |
| 4658 | 4667 | /// `1` (comptime_int) |
| 4659 | 4668 | one, |
| 4660 | /// `1` (usize) | |
| 4669 | /// `@as(usize, 1)` | |
| 4661 | 4670 | one_usize, |
| 4662 | /// `1` (u8) | |
| 4671 | /// `@as(u1, 1)` | |
| 4672 | one_u1, | |
| 4673 | /// `@as(u8, 1)` | |
| 4663 | 4674 | one_u8, |
| 4664 | /// `4` (u8) | |
| 4675 | /// `@as(u8, 4)` | |
| 4665 | 4676 | four_u8, |
| 4666 | 4677 | /// `-1` (comptime_int) |
| 4667 | 4678 | negative_one, |
| ... | ... | @@ -5074,6 +5085,20 @@ pub const static_keys: [static_len]Key = .{ |
| 5074 | 5085 | .{ .simple_type = .undefined }, |
| 5075 | 5086 | .{ .simple_type = .enum_literal }, |
| 5076 | 5087 | |
| 5088 | // *usize | |
| 5089 | .{ .ptr_type = .{ | |
| 5090 | .child = .usize_type, | |
| 5091 | .flags = .{}, | |
| 5092 | } }, | |
| 5093 | ||
| 5094 | // *const comptime_int | |
| 5095 | .{ .ptr_type = .{ | |
| 5096 | .child = .comptime_int_type, | |
| 5097 | .flags = .{ | |
| 5098 | .is_const = true, | |
| 5099 | }, | |
| 5100 | } }, | |
| 5101 | ||
| 5077 | 5102 | // [*]u8 |
| 5078 | 5103 | .{ .ptr_type = .{ |
| 5079 | 5104 | .child = .u8_type, |
| ... | ... | @@ -5101,15 +5126,6 @@ pub const static_keys: [static_len]Key = .{ |
| 5101 | 5126 | }, |
| 5102 | 5127 | } }, |
| 5103 | 5128 | |
| 5104 | // *const comptime_int | |
| 5105 | .{ .ptr_type = .{ | |
| 5106 | .child = .comptime_int_type, | |
| 5107 | .flags = .{ | |
| 5108 | .size = .one, | |
| 5109 | .is_const = true, | |
| 5110 | }, | |
| 5111 | } }, | |
| 5112 | ||
| 5113 | 5129 | // []const u8 |
| 5114 | 5130 | .{ .ptr_type = .{ |
| 5115 | 5131 | .child = .u8_type, |
| ... | ... | @@ -5245,6 +5261,9 @@ pub const static_keys: [static_len]Key = .{ |
| 5245 | 5261 | } }, |
| 5246 | 5262 | |
| 5247 | 5263 | .{ .simple_value = .undefined }, |
| 5264 | .{ .undef = .bool_type }, | |
| 5265 | .{ .undef = .usize_type }, | |
| 5266 | .{ .undef = .u1_type }, | |
| 5248 | 5267 | |
| 5249 | 5268 | .{ .int = .{ |
| 5250 | 5269 | .ty = .comptime_int_type, |
| ... | ... | @@ -5256,6 +5275,11 @@ pub const static_keys: [static_len]Key = .{ |
| 5256 | 5275 | .storage = .{ .u64 = 0 }, |
| 5257 | 5276 | } }, |
| 5258 | 5277 | |
| 5278 | .{ .int = .{ | |
| 5279 | .ty = .u1_type, | |
| 5280 | .storage = .{ .u64 = 0 }, | |
| 5281 | } }, | |
| 5282 | ||
| 5259 | 5283 | .{ .int = .{ |
| 5260 | 5284 | .ty = .u8_type, |
| 5261 | 5285 | .storage = .{ .u64 = 0 }, |
| ... | ... | @@ -5271,17 +5295,21 @@ pub const static_keys: [static_len]Key = .{ |
| 5271 | 5295 | .storage = .{ .u64 = 1 }, |
| 5272 | 5296 | } }, |
| 5273 | 5297 | |
| 5274 | // one_u8 | |
| 5298 | .{ .int = .{ | |
| 5299 | .ty = .u1_type, | |
| 5300 | .storage = .{ .u64 = 1 }, | |
| 5301 | } }, | |
| 5302 | ||
| 5275 | 5303 | .{ .int = .{ |
| 5276 | 5304 | .ty = .u8_type, |
| 5277 | 5305 | .storage = .{ .u64 = 1 }, |
| 5278 | 5306 | } }, |
| 5279 | // four_u8 | |
| 5307 | ||
| 5280 | 5308 | .{ .int = .{ |
| 5281 | 5309 | .ty = .u8_type, |
| 5282 | 5310 | .storage = .{ .u64 = 4 }, |
| 5283 | 5311 | } }, |
| 5284 | // negative_one | |
| 5312 | ||
| 5285 | 5313 | .{ .int = .{ |
| 5286 | 5314 | .ty = .comptime_int_type, |
| 5287 | 5315 | .storage = .{ .i64 = -1 }, |
| ... | ... | @@ -10482,7 +10510,7 @@ pub fn getCoerced( |
| 10482 | 10510 | .base_addr = .int, |
| 10483 | 10511 | .byte_offset = 0, |
| 10484 | 10512 | } }), |
| 10485 | .len = try ip.get(gpa, tid, .{ .undef = .usize_type }), | |
| 10513 | .len = .undef_usize, | |
| 10486 | 10514 | } }), |
| 10487 | 10515 | }; |
| 10488 | 10516 | }, |
| ... | ... | @@ -10601,7 +10629,7 @@ pub fn getCoerced( |
| 10601 | 10629 | .base_addr = .int, |
| 10602 | 10630 | .byte_offset = 0, |
| 10603 | 10631 | } }), |
| 10604 | .len = try ip.get(gpa, tid, .{ .undef = .usize_type }), | |
| 10632 | .len = .undef_usize, | |
| 10605 | 10633 | } }), |
| 10606 | 10634 | }, |
| 10607 | 10635 | else => |payload| try ip.getCoerced(gpa, tid, payload, new_ty), |
| ... | ... | @@ -11847,10 +11875,11 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 11847 | 11875 | .null_type, |
| 11848 | 11876 | .undefined_type, |
| 11849 | 11877 | .enum_literal_type, |
| 11878 | .ptr_usize_type, | |
| 11879 | .ptr_const_comptime_int_type, | |
| 11850 | 11880 | .manyptr_u8_type, |
| 11851 | 11881 | .manyptr_const_u8_type, |
| 11852 | 11882 | .manyptr_const_u8_sentinel_0_type, |
| 11853 | .single_const_pointer_to_comptime_int_type, | |
| 11854 | 11883 | .slice_const_u8_type, |
| 11855 | 11884 | .slice_const_u8_sentinel_0_type, |
| 11856 | 11885 | .vector_8_i8_type, |
| ... | ... | @@ -11909,12 +11938,13 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index { |
| 11909 | 11938 | |
| 11910 | 11939 | .undef => .undefined_type, |
| 11911 | 11940 | .zero, .one, .negative_one => .comptime_int_type, |
| 11912 | .zero_usize, .one_usize => .usize_type, | |
| 11941 | .undef_usize, .zero_usize, .one_usize => .usize_type, | |
| 11942 | .undef_u1, .zero_u1, .one_u1 => .u1_type, | |
| 11913 | 11943 | .zero_u8, .one_u8, .four_u8 => .u8_type, |
| 11914 | 11944 | .void_value => .void_type, |
| 11915 | 11945 | .unreachable_value => .noreturn_type, |
| 11916 | 11946 | .null_value => .null_type, |
| 11917 | .bool_true, .bool_false => .bool_type, | |
| 11947 | .undef_bool, .bool_true, .bool_false => .bool_type, | |
| 11918 | 11948 | .empty_tuple => .empty_tuple_type, |
| 11919 | 11949 | |
| 11920 | 11950 | // This optimization on tags is needed so that indexToKey can call |
| ... | ... | @@ -12186,10 +12216,11 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { |
| 12186 | 12216 | .undefined_type => .undefined, |
| 12187 | 12217 | .enum_literal_type => .enum_literal, |
| 12188 | 12218 | |
| 12219 | .ptr_usize_type, | |
| 12220 | .ptr_const_comptime_int_type, | |
| 12189 | 12221 | .manyptr_u8_type, |
| 12190 | 12222 | .manyptr_const_u8_type, |
| 12191 | 12223 | .manyptr_const_u8_sentinel_0_type, |
| 12192 | .single_const_pointer_to_comptime_int_type, | |
| 12193 | 12224 | .slice_const_u8_type, |
| 12194 | 12225 | .slice_const_u8_sentinel_0_type, |
| 12195 | 12226 | => .pointer, |
| ... | ... | @@ -12251,11 +12282,16 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId { |
| 12251 | 12282 | |
| 12252 | 12283 | // values, not types |
| 12253 | 12284 | .undef => unreachable, |
| 12285 | .undef_bool => unreachable, | |
| 12286 | .undef_usize => unreachable, | |
| 12287 | .undef_u1 => unreachable, | |
| 12254 | 12288 | .zero => unreachable, |
| 12255 | 12289 | .zero_usize => unreachable, |
| 12290 | .zero_u1 => unreachable, | |
| 12256 | 12291 | .zero_u8 => unreachable, |
| 12257 | 12292 | .one => unreachable, |
| 12258 | 12293 | .one_usize => unreachable, |
| 12294 | .one_u1 => unreachable, | |
| 12259 | 12295 | .one_u8 => unreachable, |
| 12260 | 12296 | .four_u8 => unreachable, |
| 12261 | 12297 | .negative_one => unreachable, |
src/Sema.zig+553-795| ... | ... | @@ -1881,7 +1881,7 @@ fn analyzeBodyInner( |
| 1881 | 1881 | extra.data.else_body_len, |
| 1882 | 1882 | ); |
| 1883 | 1883 | const uncasted_cond = try sema.resolveInst(extra.data.condition); |
| 1884 | const cond = try sema.coerce(block, Type.bool, uncasted_cond, cond_src); | |
| 1884 | const cond = try sema.coerce(block, .bool, uncasted_cond, cond_src); | |
| 1885 | 1885 | const cond_val = try sema.resolveConstDefinedValue( |
| 1886 | 1886 | block, |
| 1887 | 1887 | cond_src, |
| ... | ... | @@ -2012,7 +2012,7 @@ fn resolveConstBool( |
| 2012 | 2012 | reason: ComptimeReason, |
| 2013 | 2013 | ) !bool { |
| 2014 | 2014 | const air_inst = try sema.resolveInst(zir_ref); |
| 2015 | const wanted_type = Type.bool; | |
| 2015 | const wanted_type: Type = .bool; | |
| 2016 | 2016 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); |
| 2017 | 2017 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); |
| 2018 | 2018 | return val.toBool(); |
| ... | ... | @@ -2037,7 +2037,7 @@ pub fn toConstString( |
| 2037 | 2037 | reason: ComptimeReason, |
| 2038 | 2038 | ) ![]u8 { |
| 2039 | 2039 | const pt = sema.pt; |
| 2040 | const coerced_inst = try sema.coerce(block, Type.slice_const_u8, air_inst, src); | |
| 2040 | const coerced_inst = try sema.coerce(block, .slice_const_u8, air_inst, src); | |
| 2041 | 2041 | const slice_val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); |
| 2042 | 2042 | const arr_val = try sema.derefSliceAsArray(block, src, slice_val, reason); |
| 2043 | 2043 | return arr_val.toAllocatedBytes(arr_val.typeOf(pt.zcu), sema.arena, pt); |
| ... | ... | @@ -2051,7 +2051,7 @@ pub fn resolveConstStringIntern( |
| 2051 | 2051 | reason: ComptimeReason, |
| 2052 | 2052 | ) !InternPool.NullTerminatedString { |
| 2053 | 2053 | const air_inst = try sema.resolveInst(zir_ref); |
| 2054 | const wanted_type = Type.slice_const_u8; | |
| 2054 | const wanted_type: Type = .slice_const_u8; | |
| 2055 | 2055 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); |
| 2056 | 2056 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); |
| 2057 | 2057 | return sema.sliceToIpString(block, src, val, reason); |
| ... | ... | @@ -2180,7 +2180,7 @@ fn analyzeAsType( |
| 2180 | 2180 | src: LazySrcLoc, |
| 2181 | 2181 | air_inst: Air.Inst.Ref, |
| 2182 | 2182 | ) !Type { |
| 2183 | const wanted_type = Type.type; | |
| 2183 | const wanted_type: Type = .type; | |
| 2184 | 2184 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); |
| 2185 | 2185 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, .{ .simple = .type }); |
| 2186 | 2186 | return val.toType(); |
| ... | ... | @@ -2641,7 +2641,7 @@ fn reparentOwnedErrorMsg( |
| 2641 | 2641 | msg.msg = msg_str; |
| 2642 | 2642 | } |
| 2643 | 2643 | |
| 2644 | const align_ty = Type.u29; | |
| 2644 | const align_ty: Type = .u29; | |
| 2645 | 2645 | |
| 2646 | 2646 | pub fn analyzeAsAlign( |
| 2647 | 2647 | sema: *Sema, |
| ... | ... | @@ -2819,7 +2819,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us |
| 2819 | 2819 | const pt = sema.pt; |
| 2820 | 2820 | const zcu = pt.zcu; |
| 2821 | 2821 | const ip = &zcu.intern_pool; |
| 2822 | const parent_ty = Type.fromInterned(zcu.namespacePtr(block.namespace).owner_type); | |
| 2822 | const parent_ty: Type = .fromInterned(zcu.namespacePtr(block.namespace).owner_type); | |
| 2823 | 2823 | const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu); |
| 2824 | 2824 | |
| 2825 | 2825 | const captures = try sema.arena.alloc(InternPool.CaptureValue, captures_len); |
| ... | ... | @@ -3777,7 +3777,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3777 | 3777 | const alloc = try sema.resolveInst(inst_data.operand); |
| 3778 | 3778 | const alloc_ty = sema.typeOf(alloc); |
| 3779 | 3779 | const ptr_info = alloc_ty.ptrInfo(zcu); |
| 3780 | const elem_ty = Type.fromInterned(ptr_info.child); | |
| 3780 | const elem_ty: Type = .fromInterned(ptr_info.child); | |
| 3781 | 3781 | |
| 3782 | 3782 | // If the alloc was created in a comptime scope, we already created a comptime alloc for it. |
| 3783 | 3783 | // However, if the final constructed value does not reference comptime-mutable memory, we wish |
| ... | ... | @@ -3848,7 +3848,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 3848 | 3848 | |
| 3849 | 3849 | const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc); |
| 3850 | 3850 | const ptr_info = alloc_ty.ptrInfo(zcu); |
| 3851 | const elem_ty = Type.fromInterned(ptr_info.child); | |
| 3851 | const elem_ty: Type = .fromInterned(ptr_info.child); | |
| 3852 | 3852 | |
| 3853 | 3853 | const alloc_inst = alloc.toIndex() orelse return null; |
| 3854 | 3854 | const comptime_info = sema.maybe_comptime_allocs.fetchRemove(alloc_inst) orelse return null; |
| ... | ... | @@ -4024,9 +4024,9 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 4024 | 4024 | // As this is a union field, we must store to the pointer now to set the tag. |
| 4025 | 4025 | // If the payload is OPV, there will not be a payload store, so we store that value. |
| 4026 | 4026 | // Otherwise, there will be a payload store to process later, so undef will suffice. |
| 4027 | const payload_ty = Type.fromInterned(union_obj.field_types.get(&zcu.intern_pool)[idx]); | |
| 4027 | const payload_ty: Type = .fromInterned(union_obj.field_types.get(&zcu.intern_pool)[idx]); | |
| 4028 | 4028 | const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty); |
| 4029 | const tag_val = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), idx); | |
| 4029 | const tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), idx); | |
| 4030 | 4030 | const store_val = try pt.unionValue(maybe_union_ty, tag_val, payload_val); |
| 4031 | 4031 | try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), store_val, maybe_union_ty); |
| 4032 | 4032 | } |
| ... | ... | @@ -4050,7 +4050,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, |
| 4050 | 4050 | const air_ptr_inst = store_inst.data.bin_op.lhs.toIndex().?; |
| 4051 | 4051 | const store_val = (try sema.resolveValue(store_inst.data.bin_op.rhs)).?; |
| 4052 | 4052 | const new_ptr = ptr_mapping.get(air_ptr_inst).?; |
| 4053 | try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(new_ptr), store_val, Type.fromInterned(zcu.intern_pool.typeOf(store_val.toIntern()))); | |
| 4053 | try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(new_ptr), store_val, .fromInterned(zcu.intern_pool.typeOf(store_val.toIntern()))); | |
| 4054 | 4054 | }, |
| 4055 | 4055 | else => unreachable, |
| 4056 | 4056 | } |
| ... | ... | @@ -4284,7 +4284,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4284 | 4284 | else => unreachable, |
| 4285 | 4285 | }; |
| 4286 | 4286 | if (zcu.intern_pool.isFuncBody(val)) { |
| 4287 | const ty = Type.fromInterned(zcu.intern_pool.typeOf(val)); | |
| 4287 | const ty: Type = .fromInterned(zcu.intern_pool.typeOf(val)); | |
| 4288 | 4288 | if (try ty.fnHasRuntimeBitsSema(pt)) { |
| 4289 | 4289 | try sema.addReferenceEntry(block, src, AnalUnit.wrap(.{ .func = val })); |
| 4290 | 4290 | try zcu.ensureFuncBodyAnalysisQueued(val); |
| ... | ... | @@ -4447,14 +4447,14 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 4447 | 4447 | const range_end = try sema.resolveInst(zir_arg_pair[1]); |
| 4448 | 4448 | break :l try sema.analyzeArithmetic(block, .sub, range_end, range_start, arg_src, arg_src, arg_src, true); |
| 4449 | 4449 | }; |
| 4450 | const arg_len = try sema.coerce(block, Type.usize, arg_len_uncoerced, arg_src); | |
| 4450 | const arg_len = try sema.coerce(block, .usize, arg_len_uncoerced, arg_src); | |
| 4451 | 4451 | if (len == .none) { |
| 4452 | 4452 | len = arg_len; |
| 4453 | 4453 | len_idx = i; |
| 4454 | 4454 | } |
| 4455 | 4455 | if (try sema.resolveDefinedValue(block, src, arg_len)) |arg_val| { |
| 4456 | 4456 | if (len_val) |v| { |
| 4457 | if (!(try sema.valuesEqual(arg_val, v, Type.usize))) { | |
| 4457 | if (!(try sema.valuesEqual(arg_val, v, .usize))) { | |
| 4458 | 4458 | const msg = msg: { |
| 4459 | 4459 | const msg = try sema.errMsg(src, "non-matching for loop lengths", .{}); |
| 4460 | 4460 | errdefer msg.destroy(gpa); |
| ... | ... | @@ -5343,7 +5343,7 @@ fn zirValidatePtrArrayInit( |
| 5343 | 5343 | // sentinel-terminated array, the sentinel will not have been populated by |
| 5344 | 5344 | // any ZIR instructions at comptime; we need to do that here. |
| 5345 | 5345 | if (array_ty.sentinel(zcu)) |sentinel_val| { |
| 5346 | const array_len_ref = try pt.intRef(Type.usize, array_len); | |
| 5346 | const array_len_ref = try pt.intRef(.usize, array_len); | |
| 5347 | 5347 | const sentinel_ptr = try sema.elemPtrArray(block, init_src, init_src, array_ptr, init_src, array_len_ref, true, true); |
| 5348 | 5348 | const sentinel = Air.internedToRef(sentinel_val.toIntern()); |
| 5349 | 5349 | try sema.storePtr2(block, init_src, sentinel_ptr, init_src, sentinel, init_src, .store); |
| ... | ... | @@ -5828,7 +5828,7 @@ fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 5828 | 5828 | defer tracy.end(); |
| 5829 | 5829 | |
| 5830 | 5830 | const int = sema.code.instructions.items(.data)[@intFromEnum(inst)].int; |
| 5831 | return sema.pt.intRef(Type.comptime_int, int); | |
| 5831 | return sema.pt.intRef(.comptime_int, int); | |
| 5832 | 5832 | } |
| 5833 | 5833 | |
| 5834 | 5834 | fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -5846,7 +5846,7 @@ fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 5846 | 5846 | const limbs = try sema.arena.alloc(std.math.big.Limb, int.len); |
| 5847 | 5847 | @memcpy(mem.sliceAsBytes(limbs), limb_bytes); |
| 5848 | 5848 | |
| 5849 | return Air.internedToRef((try sema.pt.intValue_big(Type.comptime_int, .{ | |
| 5849 | return Air.internedToRef((try sema.pt.intValue_big(.comptime_int, .{ | |
| 5850 | 5850 | .limbs = limbs, |
| 5851 | 5851 | .positive = true, |
| 5852 | 5852 | })).toIntern()); |
| ... | ... | @@ -5856,7 +5856,7 @@ fn zirFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 5856 | 5856 | _ = block; |
| 5857 | 5857 | const number = sema.code.instructions.items(.data)[@intFromEnum(inst)].float; |
| 5858 | 5858 | return Air.internedToRef((try sema.pt.floatValue( |
| 5859 | Type.comptime_float, | |
| 5859 | .comptime_float, | |
| 5860 | 5860 | number, |
| 5861 | 5861 | )).toIntern()); |
| 5862 | 5862 | } |
| ... | ... | @@ -5866,7 +5866,7 @@ fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 5866 | 5866 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; |
| 5867 | 5867 | const extra = sema.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data; |
| 5868 | 5868 | const number = extra.get(); |
| 5869 | return Air.internedToRef((try sema.pt.floatValue(Type.comptime_float, number)).toIntern()); | |
| 5869 | return Air.internedToRef((try sema.pt.floatValue(.comptime_float, number)).toIntern()); | |
| 5870 | 5870 | } |
| 5871 | 5871 | |
| 5872 | 5872 | fn zirCompileError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | ... | @@ -6641,7 +6641,7 @@ pub fn analyzeExport( |
| 6641 | 6641 | }; |
| 6642 | 6642 | |
| 6643 | 6643 | const exported_nav = ip.getNav(exported_nav_index); |
| 6644 | const export_ty = Type.fromInterned(exported_nav.typeOf(ip)); | |
| 6644 | const export_ty: Type = .fromInterned(exported_nav.typeOf(ip)); | |
| 6645 | 6645 | |
| 6646 | 6646 | if (!try sema.validateExternType(export_ty, .other)) { |
| 6647 | 6647 | return sema.failWithOwnedErrorMsg(block, msg: { |
| ... | ... | @@ -7005,7 +7005,7 @@ fn lookupInNamespace( |
| 7005 | 7005 | |
| 7006 | 7006 | for (usingnamespaces.items) |sub_ns_nav| { |
| 7007 | 7007 | try sema.ensureNavResolved(block, src, sub_ns_nav, .fully); |
| 7008 | const sub_ns_ty = Type.fromInterned(ip.getNav(sub_ns_nav).status.fully_resolved.val); | |
| 7008 | const sub_ns_ty: Type = .fromInterned(ip.getNav(sub_ns_nav).status.fully_resolved.val); | |
| 7009 | 7009 | const sub_ns = zcu.namespacePtr(sub_ns_ty.getNamespaceIndex(zcu)); |
| 7010 | 7010 | try checked_namespaces.put(gpa, sub_ns, {}); |
| 7011 | 7011 | } |
| ... | ... | @@ -7081,7 +7081,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref |
| 7081 | 7081 | const gpa = sema.gpa; |
| 7082 | 7082 | |
| 7083 | 7083 | if (block.isComptime() or block.is_typeof) { |
| 7084 | const index_val = try pt.intValue_u64(Type.usize, sema.comptime_err_ret_trace.items.len); | |
| 7084 | const index_val = try pt.intValue_u64(.usize, sema.comptime_err_ret_trace.items.len); | |
| 7085 | 7085 | return Air.internedToRef(index_val.toIntern()); |
| 7086 | 7086 | } |
| 7087 | 7087 | |
| ... | ... | @@ -7326,13 +7326,13 @@ fn checkCallArgumentCount( |
| 7326 | 7326 | ) !Type { |
| 7327 | 7327 | const pt = sema.pt; |
| 7328 | 7328 | const zcu = pt.zcu; |
| 7329 | const func_ty = func_ty: { | |
| 7329 | const func_ty: Type = func_ty: { | |
| 7330 | 7330 | switch (callee_ty.zigTypeTag(zcu)) { |
| 7331 | 7331 | .@"fn" => break :func_ty callee_ty, |
| 7332 | 7332 | .pointer => { |
| 7333 | 7333 | const ptr_info = callee_ty.ptrInfo(zcu); |
| 7334 | 7334 | if (ptr_info.flags.size == .one and Type.fromInterned(ptr_info.child).zigTypeTag(zcu) == .@"fn") { |
| 7335 | break :func_ty Type.fromInterned(ptr_info.child); | |
| 7335 | break :func_ty .fromInterned(ptr_info.child); | |
| 7336 | 7336 | } |
| 7337 | 7337 | }, |
| 7338 | 7338 | .optional => { |
| ... | ... | @@ -7405,13 +7405,13 @@ fn callBuiltin( |
| 7405 | 7405 | const pt = sema.pt; |
| 7406 | 7406 | const zcu = pt.zcu; |
| 7407 | 7407 | const callee_ty = sema.typeOf(builtin_fn); |
| 7408 | const func_ty = func_ty: { | |
| 7408 | const func_ty: Type = func_ty: { | |
| 7409 | 7409 | switch (callee_ty.zigTypeTag(zcu)) { |
| 7410 | 7410 | .@"fn" => break :func_ty callee_ty, |
| 7411 | 7411 | .pointer => { |
| 7412 | 7412 | const ptr_info = callee_ty.ptrInfo(zcu); |
| 7413 | 7413 | if (ptr_info.flags.size == .one and Type.fromInterned(ptr_info.child).zigTypeTag(zcu) == .@"fn") { |
| 7414 | break :func_ty Type.fromInterned(ptr_info.child); | |
| 7414 | break :func_ty .fromInterned(ptr_info.child); | |
| 7415 | 7415 | } |
| 7416 | 7416 | }, |
| 7417 | 7417 | else => {}, |
| ... | ... | @@ -7568,7 +7568,7 @@ const CallArgsInfo = union(enum) { |
| 7568 | 7568 | } |
| 7569 | 7569 | } |
| 7570 | 7570 | // Give the arg its result type |
| 7571 | const provide_param_ty = if (maybe_param_ty) |t| t else Type.generic_poison; | |
| 7571 | const provide_param_ty: Type = maybe_param_ty orelse .generic_poison; | |
| 7572 | 7572 | sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(provide_param_ty.toIntern())); |
| 7573 | 7573 | // Resolve the arg! |
| 7574 | 7574 | const uncoerced_arg = try sema.resolveInlineBody(block, arg_body, zir_call.call_inst); |
| ... | ... | @@ -8353,7 +8353,7 @@ fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Typ |
| 8353 | 8353 | @tagName(backend), @tagName(target.cpu.arch), |
| 8354 | 8354 | }); |
| 8355 | 8355 | } |
| 8356 | const owner_func_ty = Type.fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty); | |
| 8356 | const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty); | |
| 8357 | 8357 | if (owner_func_ty.toIntern() != func_ty.toIntern()) { |
| 8358 | 8358 | return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{ |
| 8359 | 8359 | func_ty.fmt(pt), owner_func_ty.fmt(pt), |
| ... | ... | @@ -8452,7 +8452,7 @@ fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 8452 | 8452 | const len_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 8453 | 8453 | const elem_type_src = block.builtinCallArgSrc(inst_data.src_node, 1); |
| 8454 | 8454 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 8455 | const len: u32 = @intCast(try sema.resolveInt(block, len_src, extra.lhs, Type.u32, .{ .simple = .vector_length })); | |
| 8455 | const len: u32 = @intCast(try sema.resolveInt(block, len_src, extra.lhs, .u32, .{ .simple = .vector_length })); | |
| 8456 | 8456 | const elem_type = try sema.resolveType(block, elem_type_src, extra.rhs); |
| 8457 | 8457 | try sema.checkVectorElemType(block, elem_type_src, elem_type); |
| 8458 | 8458 | const vector_type = try sema.pt.vectorType(.{ |
| ... | ... | @@ -8470,7 +8470,7 @@ fn zirArrayType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 8470 | 8470 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 8471 | 8471 | const len_src = block.src(.{ .node_offset_array_type_len = inst_data.src_node }); |
| 8472 | 8472 | const elem_src = block.src(.{ .node_offset_array_type_elem = inst_data.src_node }); |
| 8473 | const len = try sema.resolveInt(block, len_src, extra.lhs, Type.usize, .{ .simple = .array_length }); | |
| 8473 | const len = try sema.resolveInt(block, len_src, extra.lhs, .usize, .{ .simple = .array_length }); | |
| 8474 | 8474 | const elem_type = try sema.resolveType(block, elem_src, extra.rhs); |
| 8475 | 8475 | try sema.validateArrayElemType(block, elem_type, elem_src); |
| 8476 | 8476 | const array_ty = try sema.pt.arrayType(.{ |
| ... | ... | @@ -8490,7 +8490,7 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil |
| 8490 | 8490 | const len_src = block.src(.{ .node_offset_array_type_len = inst_data.src_node }); |
| 8491 | 8491 | const sentinel_src = block.src(.{ .node_offset_array_type_sentinel = inst_data.src_node }); |
| 8492 | 8492 | const elem_src = block.src(.{ .node_offset_array_type_elem = inst_data.src_node }); |
| 8493 | const len = try sema.resolveInt(block, len_src, extra.len, Type.usize, .{ .simple = .array_length }); | |
| 8493 | const len = try sema.resolveInt(block, len_src, extra.len, .usize, .{ .simple = .array_length }); | |
| 8494 | 8494 | const elem_type = try sema.resolveType(block, elem_src, extra.elem_type); |
| 8495 | 8495 | try sema.validateArrayElemType(block, elem_type, elem_src); |
| 8496 | 8496 | const uncasted_sentinel = try sema.resolveInst(extra.sentinel); |
| ... | ... | @@ -8599,7 +8599,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 8599 | 8599 | const src = block.nodeOffset(extra.node); |
| 8600 | 8600 | const operand_src = block.builtinCallArgSrc(extra.node, 0); |
| 8601 | 8601 | const uncasted_operand = try sema.resolveInst(extra.operand); |
| 8602 | const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src); | |
| 8602 | const operand = try sema.coerce(block, .anyerror, uncasted_operand, operand_src); | |
| 8603 | 8603 | const err_int_ty = try pt.errorIntType(); |
| 8604 | 8604 | |
| 8605 | 8605 | if (try sema.resolveValue(operand)) |val| { |
| ... | ... | @@ -8912,21 +8912,10 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8912 | 8912 | |
| 8913 | 8913 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 8914 | 8914 | if (block.wantSafety()) { |
| 8915 | if (zcu.backendSupportsFeature(.safety_checked_instructions)) { | |
| 8915 | if (zcu.backendSupportsFeature(.panic_fn)) { | |
| 8916 | 8916 | _ = try sema.preparePanicId(src, .invalid_enum_value); |
| 8917 | return block.addTyOp(.intcast_safe, dest_ty, operand); | |
| 8918 | } else { | |
| 8919 | // Slightly silly fallback case... | |
| 8920 | const int_tag_ty = dest_ty.intTagType(zcu); | |
| 8921 | // Use `intCast`, since it'll set up the Sema-emitted safety checks for us! | |
| 8922 | const int_val = try sema.intCast(block, src, int_tag_ty, src, operand, src, true, true); | |
| 8923 | const result = try block.addBitCast(dest_ty, int_val); | |
| 8924 | if (!dest_ty.isNonexhaustiveEnum(zcu) and zcu.backendSupportsFeature(.is_named_enum_value)) { | |
| 8925 | const ok = try block.addUnOp(.is_named_enum_value, result); | |
| 8926 | try sema.addSafetyCheck(block, src, ok, .invalid_enum_value); | |
| 8927 | } | |
| 8928 | return result; | |
| 8929 | 8917 | } |
| 8918 | return block.addTyOp(.intcast_safe, dest_ty, operand); | |
| 8930 | 8919 | } |
| 8931 | 8920 | return block.addTyOp(.intcast, dest_ty, operand); |
| 8932 | 8921 | } |
| ... | ... | @@ -9309,7 +9298,7 @@ fn zirFunc( |
| 9309 | 9298 | const ret_ty: Type = if (extra.data.ret_ty.is_generic) |
| 9310 | 9299 | .generic_poison |
| 9311 | 9300 | else switch (extra.data.ret_ty.body_len) { |
| 9312 | 0 => Type.void, | |
| 9301 | 0 => .void, | |
| 9313 | 9302 | 1 => blk: { |
| 9314 | 9303 | const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); |
| 9315 | 9304 | extra_index += 1; |
| ... | ... | @@ -9319,7 +9308,7 @@ fn zirFunc( |
| 9319 | 9308 | const ret_ty_body = sema.code.bodySlice(extra_index, extra.data.ret_ty.body_len); |
| 9320 | 9309 | extra_index += ret_ty_body.len; |
| 9321 | 9310 | |
| 9322 | const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, Type.type, .{ .simple = .function_ret_ty }); | |
| 9311 | const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, .type, .{ .simple = .function_ret_ty }); | |
| 9323 | 9312 | break :blk ret_ty_val.toType(); |
| 9324 | 9313 | }, |
| 9325 | 9314 | }; |
| ... | ... | @@ -9649,7 +9638,7 @@ fn funcCommon( |
| 9649 | 9638 | |
| 9650 | 9639 | var comptime_bits: u32 = 0; |
| 9651 | 9640 | for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| { |
| 9652 | const param_ty = Type.fromInterned(param_ty_ip); | |
| 9641 | const param_ty: Type = .fromInterned(param_ty_ip); | |
| 9653 | 9642 | const is_noalias = blk: { |
| 9654 | 9643 | const index = std.math.cast(u5, i) orelse break :blk false; |
| 9655 | 9644 | break :blk @as(u1, @truncate(noalias_bits >> index)) != 0; |
| ... | ... | @@ -9870,7 +9859,7 @@ fn finishFunc( |
| 9870 | 9859 | const return_type: Type = if (opt_func_index == .none or ret_poison) |
| 9871 | 9860 | bare_return_type |
| 9872 | 9861 | else |
| 9873 | Type.fromInterned(ip.funcTypeReturnType(ip.typeOf(opt_func_index))); | |
| 9862 | .fromInterned(ip.funcTypeReturnType(ip.typeOf(opt_func_index))); | |
| 9874 | 9863 | |
| 9875 | 9864 | if (!return_type.isValidReturnType(zcu)) { |
| 9876 | 9865 | const opaque_str = if (return_type.zigTypeTag(zcu) == .@"opaque") "opaque " else ""; |
| ... | ... | @@ -10130,14 +10119,14 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10130 | 10119 | if (try sema.resolveValue(operand)) |operand_val| ct: { |
| 10131 | 10120 | if (!is_vector) { |
| 10132 | 10121 | if (operand_val.isUndef(zcu)) { |
| 10133 | return Air.internedToRef((try pt.undefValue(Type.usize)).toIntern()); | |
| 10122 | return .undef_usize; | |
| 10134 | 10123 | } |
| 10135 | 10124 | const addr = try operand_val.getUnsignedIntSema(pt) orelse { |
| 10136 | 10125 | // Wasn't an integer pointer. This is a runtime operation. |
| 10137 | 10126 | break :ct; |
| 10138 | 10127 | }; |
| 10139 | 10128 | return Air.internedToRef((try pt.intValue( |
| 10140 | Type.usize, | |
| 10129 | .usize, | |
| 10141 | 10130 | addr, |
| 10142 | 10131 | )).toIntern()); |
| 10143 | 10132 | } |
| ... | ... | @@ -10145,7 +10134,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10145 | 10134 | for (new_elems, 0..) |*new_elem, i| { |
| 10146 | 10135 | const ptr_val = try operand_val.elemValue(pt, i); |
| 10147 | 10136 | if (ptr_val.isUndef(zcu)) { |
| 10148 | new_elem.* = (try pt.undefValue(Type.usize)).toIntern(); | |
| 10137 | new_elem.* = .undef_usize; | |
| 10149 | 10138 | continue; |
| 10150 | 10139 | } |
| 10151 | 10140 | const addr = try ptr_val.getUnsignedIntSema(pt) orelse { |
| ... | ... | @@ -10153,7 +10142,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10153 | 10142 | break :ct; |
| 10154 | 10143 | }; |
| 10155 | 10144 | new_elem.* = (try pt.intValue( |
| 10156 | Type.usize, | |
| 10145 | .usize, | |
| 10157 | 10146 | addr, |
| 10158 | 10147 | )).toIntern(); |
| 10159 | 10148 | } |
| ... | ... | @@ -10165,16 +10154,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10165 | 10154 | try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src); |
| 10166 | 10155 | try sema.validateRuntimeValue(block, ptr_src, operand); |
| 10167 | 10156 | try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty); |
| 10168 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 10169 | return block.addBitCast(dest_ty, operand); | |
| 10170 | } | |
| 10171 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 10172 | for (new_elems, 0..) |*new_elem, i| { | |
| 10173 | const idx_ref = try pt.intRef(Type.usize, i); | |
| 10174 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 10175 | new_elem.* = try block.addBitCast(.usize, old_elem); | |
| 10176 | } | |
| 10177 | return block.addAggregateInit(dest_ty, new_elems); | |
| 10157 | return block.addBitCast(dest_ty, operand); | |
| 10178 | 10158 | } |
| 10179 | 10159 | |
| 10180 | 10160 | fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -10283,7 +10263,7 @@ fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 10283 | 10263 | const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast"); |
| 10284 | 10264 | const operand = try sema.resolveInst(extra.rhs); |
| 10285 | 10265 | |
| 10286 | return sema.intCast(block, block.nodeOffset(inst_data.src_node), dest_ty, src, operand, operand_src, true, false); | |
| 10266 | return sema.intCast(block, block.nodeOffset(inst_data.src_node), dest_ty, src, operand, operand_src); | |
| 10287 | 10267 | } |
| 10288 | 10268 | |
| 10289 | 10269 | fn intCast( |
| ... | ... | @@ -10294,8 +10274,6 @@ fn intCast( |
| 10294 | 10274 | dest_ty_src: LazySrcLoc, |
| 10295 | 10275 | operand: Air.Inst.Ref, |
| 10296 | 10276 | operand_src: LazySrcLoc, |
| 10297 | runtime_safety: bool, | |
| 10298 | safety_panics_are_enum: bool, | |
| 10299 | 10277 | ) CompileError!Air.Inst.Ref { |
| 10300 | 10278 | const pt = sema.pt; |
| 10301 | 10279 | const zcu = pt.zcu; |
| ... | ... | @@ -10314,7 +10292,7 @@ fn intCast( |
| 10314 | 10292 | |
| 10315 | 10293 | if ((try sema.typeHasOnePossibleValue(dest_ty))) |opv| { |
| 10316 | 10294 | // requirement: intCast(u0, input) iff input == 0 |
| 10317 | if (runtime_safety and block.wantSafety()) { | |
| 10295 | if (block.wantSafety()) { | |
| 10318 | 10296 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 10319 | 10297 | const wanted_info = dest_scalar_ty.intInfo(zcu); |
| 10320 | 10298 | const wanted_bits = wanted_info.bits; |
| ... | ... | @@ -10331,7 +10309,7 @@ fn intCast( |
| 10331 | 10309 | const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst); |
| 10332 | 10310 | break :ok is_in_range; |
| 10333 | 10311 | }; |
| 10334 | try sema.addSafetyCheck(block, src, ok, if (safety_panics_are_enum) .invalid_enum_value else .cast_truncated_data); | |
| 10312 | try sema.addSafetyCheck(block, src, ok, .integer_out_of_bounds); | |
| 10335 | 10313 | } |
| 10336 | 10314 | } |
| 10337 | 10315 | |
| ... | ... | @@ -10339,91 +10317,11 @@ fn intCast( |
| 10339 | 10317 | } |
| 10340 | 10318 | |
| 10341 | 10319 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 10342 | if (runtime_safety and block.wantSafety()) { | |
| 10343 | if (zcu.backendSupportsFeature(.safety_checked_instructions)) { | |
| 10344 | _ = try sema.preparePanicId(src, .negative_to_unsigned); | |
| 10345 | _ = try sema.preparePanicId(src, .cast_truncated_data); | |
| 10346 | return block.addTyOp(.intcast_safe, dest_ty, operand); | |
| 10347 | } | |
| 10348 | const actual_info = operand_scalar_ty.intInfo(zcu); | |
| 10349 | const wanted_info = dest_scalar_ty.intInfo(zcu); | |
| 10350 | const actual_bits = actual_info.bits; | |
| 10351 | const wanted_bits = wanted_info.bits; | |
| 10352 | const actual_value_bits = actual_bits - @intFromBool(actual_info.signedness == .signed); | |
| 10353 | const wanted_value_bits = wanted_bits - @intFromBool(wanted_info.signedness == .signed); | |
| 10354 | ||
| 10355 | // range shrinkage | |
| 10356 | // requirement: int value fits into target type | |
| 10357 | if (wanted_value_bits < actual_value_bits) { | |
| 10358 | const dest_max_val_scalar = try dest_scalar_ty.maxIntScalar(pt, operand_scalar_ty); | |
| 10359 | const dest_max_val = try sema.splat(operand_ty, dest_max_val_scalar); | |
| 10360 | const dest_max = Air.internedToRef(dest_max_val.toIntern()); | |
| 10361 | ||
| 10362 | if (actual_info.signedness == .signed) { | |
| 10363 | const diff = try block.addBinOp(.sub_wrap, dest_max, operand); | |
| 10364 | ||
| 10365 | // Reinterpret the sign-bit as part of the value. This will make | |
| 10366 | // negative differences (`operand` > `dest_max`) appear too big. | |
| 10367 | const unsigned_scalar_operand_ty = try pt.intType(.unsigned, actual_bits); | |
| 10368 | const unsigned_operand_ty = if (is_vector) try pt.vectorType(.{ | |
| 10369 | .len = dest_ty.vectorLen(zcu), | |
| 10370 | .child = unsigned_scalar_operand_ty.toIntern(), | |
| 10371 | }) else unsigned_scalar_operand_ty; | |
| 10372 | const diff_unsigned = try block.addBitCast(unsigned_operand_ty, diff); | |
| 10373 | ||
| 10374 | // If the destination type is signed, then we need to double its | |
| 10375 | // range to account for negative values. | |
| 10376 | const dest_range_val = if (wanted_info.signedness == .signed) range_val: { | |
| 10377 | const one_scalar = try pt.intValue(unsigned_scalar_operand_ty, 1); | |
| 10378 | const one = if (is_vector) Value.fromInterned(try pt.intern(.{ .aggregate = .{ | |
| 10379 | .ty = unsigned_operand_ty.toIntern(), | |
| 10380 | .storage = .{ .repeated_elem = one_scalar.toIntern() }, | |
| 10381 | } })) else one_scalar; | |
| 10382 | const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, pt); | |
| 10383 | const result = try arith.addWithOverflow(sema, unsigned_operand_ty, range_minus_one, one); | |
| 10384 | assert(result.overflow_bit.compareAllWithZero(.eq, zcu)); | |
| 10385 | break :range_val result.wrapped_result; | |
| 10386 | } else try pt.getCoerced(dest_max_val, unsigned_operand_ty); | |
| 10387 | const dest_range = Air.internedToRef(dest_range_val.toIntern()); | |
| 10388 | ||
| 10389 | const ok = if (is_vector) ok: { | |
| 10390 | const is_in_range = try block.addCmpVector(diff_unsigned, dest_range, .lte); | |
| 10391 | const all_in_range = try block.addReduce(is_in_range, .And); | |
| 10392 | break :ok all_in_range; | |
| 10393 | } else ok: { | |
| 10394 | const is_in_range = try block.addBinOp(.cmp_lte, diff_unsigned, dest_range); | |
| 10395 | break :ok is_in_range; | |
| 10396 | }; | |
| 10397 | // TODO negative_to_unsigned? | |
| 10398 | try sema.addSafetyCheck(block, src, ok, if (safety_panics_are_enum) .invalid_enum_value else .cast_truncated_data); | |
| 10399 | } else { | |
| 10400 | const ok = if (is_vector) ok: { | |
| 10401 | const is_in_range = try block.addCmpVector(operand, dest_max, .lte); | |
| 10402 | const all_in_range = try block.addReduce(is_in_range, .And); | |
| 10403 | break :ok all_in_range; | |
| 10404 | } else ok: { | |
| 10405 | const is_in_range = try block.addBinOp(.cmp_lte, operand, dest_max); | |
| 10406 | break :ok is_in_range; | |
| 10407 | }; | |
| 10408 | try sema.addSafetyCheck(block, src, ok, if (safety_panics_are_enum) .invalid_enum_value else .cast_truncated_data); | |
| 10409 | } | |
| 10410 | } else if (actual_info.signedness == .signed and wanted_info.signedness == .unsigned) { | |
| 10411 | // no shrinkage, yes sign loss | |
| 10412 | // requirement: signed to unsigned >= 0 | |
| 10413 | const ok = if (is_vector) ok: { | |
| 10414 | const scalar_zero = try pt.intValue(operand_scalar_ty, 0); | |
| 10415 | const zero_val = try sema.splat(operand_ty, scalar_zero); | |
| 10416 | const zero_inst = Air.internedToRef(zero_val.toIntern()); | |
| 10417 | const is_in_range = try block.addCmpVector(operand, zero_inst, .gte); | |
| 10418 | const all_in_range = try block.addReduce(is_in_range, .And); | |
| 10419 | break :ok all_in_range; | |
| 10420 | } else ok: { | |
| 10421 | const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern()); | |
| 10422 | const is_in_range = try block.addBinOp(.cmp_gte, operand, zero_inst); | |
| 10423 | break :ok is_in_range; | |
| 10424 | }; | |
| 10425 | try sema.addSafetyCheck(block, src, ok, if (safety_panics_are_enum) .invalid_enum_value else .negative_to_unsigned); | |
| 10320 | if (block.wantSafety()) { | |
| 10321 | if (zcu.backendSupportsFeature(.panic_fn)) { | |
| 10322 | _ = try sema.preparePanicId(src, .integer_out_of_bounds); | |
| 10426 | 10323 | } |
| 10324 | return block.addTyOp(.intcast_safe, dest_ty, operand); | |
| 10427 | 10325 | } |
| 10428 | 10326 | return block.addTyOp(.intcast, dest_ty, operand); |
| 10429 | 10327 | } |
| ... | ... | @@ -10640,17 +10538,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 10640 | 10538 | if (dst_bits >= src_bits) { |
| 10641 | 10539 | return sema.coerce(block, dest_ty, operand, operand_src); |
| 10642 | 10540 | } |
| 10643 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 10644 | return block.addTyOp(.fptrunc, dest_ty, operand); | |
| 10645 | } | |
| 10646 | const vec_len = operand_ty.vectorLen(zcu); | |
| 10647 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, vec_len); | |
| 10648 | for (new_elems, 0..) |*new_elem, i| { | |
| 10649 | const idx_ref = try pt.intRef(Type.usize, i); | |
| 10650 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 10651 | new_elem.* = try block.addTyOp(.fptrunc, dest_scalar_ty, old_elem); | |
| 10652 | } | |
| 10653 | return block.addAggregateInit(dest_ty, new_elems); | |
| 10541 | return block.addTyOp(.fptrunc, dest_ty, operand); | |
| 10654 | 10542 | } |
| 10655 | 10543 | |
| 10656 | 10544 | fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -10675,7 +10563,7 @@ fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10675 | 10563 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10676 | 10564 | const array = try sema.resolveInst(extra.lhs); |
| 10677 | 10565 | const uncoerced_elem_index = try sema.resolveInst(extra.rhs); |
| 10678 | const elem_index = try sema.coerce(block, Type.usize, uncoerced_elem_index, elem_index_src); | |
| 10566 | const elem_index = try sema.coerce(block, .usize, uncoerced_elem_index, elem_index_src); | |
| 10679 | 10567 | return sema.elemVal(block, src, array, elem_index, elem_index_src, true); |
| 10680 | 10568 | } |
| 10681 | 10569 | |
| ... | ... | @@ -10685,7 +10573,7 @@ fn zirElemValImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10685 | 10573 | |
| 10686 | 10574 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm; |
| 10687 | 10575 | const array = try sema.resolveInst(inst_data.operand); |
| 10688 | const elem_index = try sema.pt.intRef(Type.usize, inst_data.idx); | |
| 10576 | const elem_index = try sema.pt.intRef(.usize, inst_data.idx); | |
| 10689 | 10577 | return sema.elemVal(block, LazySrcLoc.unneeded, array, elem_index, LazySrcLoc.unneeded, false); |
| 10690 | 10578 | } |
| 10691 | 10579 | |
| ... | ... | @@ -10728,7 +10616,7 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10728 | 10616 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 10729 | 10617 | const array_ptr = try sema.resolveInst(extra.lhs); |
| 10730 | 10618 | const uncoerced_elem_index = try sema.resolveInst(extra.rhs); |
| 10731 | const elem_index = try sema.coerce(block, Type.usize, uncoerced_elem_index, elem_index_src); | |
| 10619 | const elem_index = try sema.coerce(block, .usize, uncoerced_elem_index, elem_index_src); | |
| 10732 | 10620 | return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, true); |
| 10733 | 10621 | } |
| 10734 | 10622 | |
| ... | ... | @@ -10742,7 +10630,7 @@ fn zirArrayInitElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile |
| 10742 | 10630 | const src = block.nodeOffset(inst_data.src_node); |
| 10743 | 10631 | const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data; |
| 10744 | 10632 | const array_ptr = try sema.resolveInst(extra.ptr); |
| 10745 | const elem_index = try pt.intRef(Type.usize, extra.index); | |
| 10633 | const elem_index = try pt.intRef(.usize, extra.index); | |
| 10746 | 10634 | const array_ty = sema.typeOf(array_ptr).childType(zcu); |
| 10747 | 10635 | switch (array_ty.zigTypeTag(zcu)) { |
| 10748 | 10636 | .array, .vector => {}, |
| ... | ... | @@ -11104,7 +10992,7 @@ const SwitchProngAnalysis = struct { |
| 11104 | 10992 | if (operand_ty.zigTypeTag(zcu) == .@"union") { |
| 11105 | 10993 | const field_index: u32 = @intCast(operand_ty.unionTagFieldIndex(item_val, zcu).?); |
| 11106 | 10994 | const union_obj = zcu.typeToUnion(operand_ty).?; |
| 11107 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 10995 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 11108 | 10996 | if (capture_byref) { |
| 11109 | 10997 | const ptr_field_ty = try pt.ptrTypeSema(.{ |
| 11110 | 10998 | .child = field_ty.toIntern(), |
| ... | ... | @@ -11154,7 +11042,7 @@ const SwitchProngAnalysis = struct { |
| 11154 | 11042 | const first_item_val = sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, case_vals[0], undefined) catch unreachable; |
| 11155 | 11043 | |
| 11156 | 11044 | const first_field_index: u32 = zcu.unionTagFieldIndex(union_obj, first_item_val).?; |
| 11157 | const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[first_field_index]); | |
| 11045 | const first_field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[first_field_index]); | |
| 11158 | 11046 | |
| 11159 | 11047 | const field_indices = try sema.arena.alloc(u32, case_vals.len); |
| 11160 | 11048 | for (case_vals, field_indices) |item, *field_idx| { |
| ... | ... | @@ -11165,7 +11053,7 @@ const SwitchProngAnalysis = struct { |
| 11165 | 11053 | // Fast path: if all the operands are the same type already, we don't need to hit |
| 11166 | 11054 | // PTR! This will also allow us to emit simpler code. |
| 11167 | 11055 | const same_types = for (field_indices[1..]) |field_idx| { |
| 11168 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11056 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11169 | 11057 | if (!field_ty.eql(first_field_ty, zcu)) break false; |
| 11170 | 11058 | } else true; |
| 11171 | 11059 | |
| ... | ... | @@ -11173,7 +11061,7 @@ const SwitchProngAnalysis = struct { |
| 11173 | 11061 | // We need values to run PTR on, so make a bunch of undef constants. |
| 11174 | 11062 | const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, case_vals.len); |
| 11175 | 11063 | for (dummy_captures, field_indices) |*dummy, field_idx| { |
| 11176 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11064 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11177 | 11065 | dummy.* = try pt.undefRef(field_ty); |
| 11178 | 11066 | } |
| 11179 | 11067 | |
| ... | ... | @@ -11208,7 +11096,7 @@ const SwitchProngAnalysis = struct { |
| 11208 | 11096 | // We need values to run PTR on, so make a bunch of undef constants. |
| 11209 | 11097 | const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, case_vals.len); |
| 11210 | 11098 | for (field_indices, dummy_captures) |field_idx, *dummy| { |
| 11211 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11099 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11212 | 11100 | const field_ptr_ty = try pt.ptrTypeSema(.{ |
| 11213 | 11101 | .child = field_ty.toIntern(), |
| 11214 | 11102 | .flags = .{ |
| ... | ... | @@ -11271,7 +11159,7 @@ const SwitchProngAnalysis = struct { |
| 11271 | 11159 | // If we can, try to avoid that using in-memory coercions. |
| 11272 | 11160 | const first_non_imc = in_mem: { |
| 11273 | 11161 | for (field_indices, 0..) |field_idx, i| { |
| 11274 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11162 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11275 | 11163 | if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), LazySrcLoc.unneeded, LazySrcLoc.unneeded, null)) { |
| 11276 | 11164 | break :in_mem i; |
| 11277 | 11165 | } |
| ... | ... | @@ -11294,7 +11182,7 @@ const SwitchProngAnalysis = struct { |
| 11294 | 11182 | { |
| 11295 | 11183 | const next = first_non_imc + 1; |
| 11296 | 11184 | for (field_indices[next..], next..) |field_idx, i| { |
| 11297 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11185 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11298 | 11186 | if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), LazySrcLoc.unneeded, LazySrcLoc.unneeded, null)) { |
| 11299 | 11187 | in_mem_coercible.unset(i); |
| 11300 | 11188 | } |
| ... | ... | @@ -11341,7 +11229,7 @@ const SwitchProngAnalysis = struct { |
| 11341 | 11229 | }; |
| 11342 | 11230 | |
| 11343 | 11231 | const field_idx = field_indices[idx]; |
| 11344 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11232 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]); | |
| 11345 | 11233 | const uncoerced = try coerce_block.addStructFieldVal(operand_val, field_idx, field_ty); |
| 11346 | 11234 | const coerced = try sema.coerce(&coerce_block, capture_ty, uncoerced, case_src); |
| 11347 | 11235 | _ = try coerce_block.addBr(capture_block_inst, coerced); |
| ... | ... | @@ -11365,7 +11253,7 @@ const SwitchProngAnalysis = struct { |
| 11365 | 11253 | |
| 11366 | 11254 | const first_imc_item_idx = in_mem_coercible.findFirstSet().?; |
| 11367 | 11255 | const first_imc_field_idx = field_indices[first_imc_item_idx]; |
| 11368 | const first_imc_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[first_imc_field_idx]); | |
| 11256 | const first_imc_field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[first_imc_field_idx]); | |
| 11369 | 11257 | const uncoerced = try coerce_block.addStructFieldVal(operand_val, first_imc_field_idx, first_imc_field_ty); |
| 11370 | 11258 | const coerced = try coerce_block.addBitCast(capture_ty, uncoerced); |
| 11371 | 11259 | _ = try coerce_block.addBr(capture_block_inst, coerced); |
| ... | ... | @@ -13165,7 +13053,7 @@ fn analyzeSwitchRuntimeBlock( |
| 13165 | 13053 | for (seen_enum_fields, 0..) |seen_field, index| { |
| 13166 | 13054 | if (seen_field != null) continue; |
| 13167 | 13055 | const union_obj = zcu.typeToUnion(maybe_union_ty).?; |
| 13168 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[index]); | |
| 13056 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[index]); | |
| 13169 | 13057 | if (field_ty.zigTypeTag(zcu) != .noreturn) break true; |
| 13170 | 13058 | } else false |
| 13171 | 13059 | else |
| ... | ... | @@ -13490,7 +13378,7 @@ const RangeSetUnhandledIterator = struct { |
| 13490 | 13378 | inline .u64, .i64 => |val_int| { |
| 13491 | 13379 | const next_int = @addWithOverflow(val_int, 1); |
| 13492 | 13380 | if (next_int[1] == 0) |
| 13493 | return (try it.pt.intValue(Type.fromInterned(int.ty), next_int[0])).toIntern(); | |
| 13381 | return (try it.pt.intValue(.fromInterned(int.ty), next_int[0])).toIntern(); | |
| 13494 | 13382 | }, |
| 13495 | 13383 | .big_int => {}, |
| 13496 | 13384 | .lazy_align, .lazy_size => unreachable, |
| ... | ... | @@ -13506,7 +13394,7 @@ const RangeSetUnhandledIterator = struct { |
| 13506 | 13394 | ); |
| 13507 | 13395 | |
| 13508 | 13396 | result_bigint.addScalar(val_bigint, 1); |
| 13509 | return (try it.pt.intValue_big(Type.fromInterned(int.ty), result_bigint.toConst())).toIntern(); | |
| 13397 | return (try it.pt.intValue_big(.fromInterned(int.ty), result_bigint.toConst())).toIntern(); | |
| 13510 | 13398 | } |
| 13511 | 13399 | |
| 13512 | 13400 | fn next(it: *RangeSetUnhandledIterator) !?InternPool.Index { |
| ... | ... | @@ -13636,7 +13524,7 @@ fn validateErrSetSwitch( |
| 13636 | 13524 | .{}, |
| 13637 | 13525 | ); |
| 13638 | 13526 | } |
| 13639 | return Type.anyerror; | |
| 13527 | return .anyerror; | |
| 13640 | 13528 | }, |
| 13641 | 13529 | else => |err_set_ty_index| else_validation: { |
| 13642 | 13530 | const error_names = ip.indexToKey(err_set_ty_index).error_set_type.names; |
| ... | ... | @@ -13839,7 +13727,7 @@ fn validateSwitchItemBool( |
| 13839 | 13727 | item_ref: Zir.Inst.Ref, |
| 13840 | 13728 | item_src: LazySrcLoc, |
| 13841 | 13729 | ) CompileError!Air.Inst.Ref { |
| 13842 | const item = try sema.resolveSwitchItemVal(block, item_ref, Type.bool, item_src); | |
| 13730 | const item = try sema.resolveSwitchItemVal(block, item_ref, .bool, item_src); | |
| 13843 | 13731 | if (Value.fromInterned(item.val).toBool()) { |
| 13844 | 13732 | true_count.* += 1; |
| 13845 | 13733 | } else { |
| ... | ... | @@ -14224,7 +14112,7 @@ fn zirShl( |
| 14224 | 14112 | return lhs; |
| 14225 | 14113 | } |
| 14226 | 14114 | if (air_tag != .shl_sat and scalar_ty.zigTypeTag(zcu) != .comptime_int) { |
| 14227 | const bit_value = try pt.intValue(Type.comptime_int, scalar_ty.intInfo(zcu).bits); | |
| 14115 | const bit_value = try pt.intValue(.comptime_int, scalar_ty.intInfo(zcu).bits); | |
| 14228 | 14116 | if (rhs_ty.zigTypeTag(zcu) == .vector) { |
| 14229 | 14117 | var i: usize = 0; |
| 14230 | 14118 | while (i < rhs_ty.vectorLen(zcu)) : (i += 1) { |
| ... | ... | @@ -14335,7 +14223,7 @@ fn zirShl( |
| 14335 | 14223 | } |
| 14336 | 14224 | |
| 14337 | 14225 | if (air_tag == .shl_exact) { |
| 14338 | const op_ov_tuple_ty = try sema.overflowArithmeticTupleType(lhs_ty); | |
| 14226 | const op_ov_tuple_ty = try pt.overflowArithmeticTupleType(lhs_ty); | |
| 14339 | 14227 | const op_ov = try block.addInst(.{ |
| 14340 | 14228 | .tag = .shl_with_overflow, |
| 14341 | 14229 | .data = .{ .ty_pl = .{ |
| ... | ... | @@ -14351,8 +14239,7 @@ fn zirShl( |
| 14351 | 14239 | try block.addReduce(ov_bit, .Or) |
| 14352 | 14240 | else |
| 14353 | 14241 | ov_bit; |
| 14354 | const zero_ov = Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern()); | |
| 14355 | const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov); | |
| 14242 | const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, .zero_u1); | |
| 14356 | 14243 | |
| 14357 | 14244 | try sema.addSafetyCheck(block, src, no_ov, .shl_overflow); |
| 14358 | 14245 | return sema.tupleFieldValByIndex(block, op_ov, 0, op_ov_tuple_ty); |
| ... | ... | @@ -14406,7 +14293,7 @@ fn zirShr( |
| 14406 | 14293 | return lhs; |
| 14407 | 14294 | } |
| 14408 | 14295 | if (scalar_ty.zigTypeTag(zcu) != .comptime_int) { |
| 14409 | const bit_value = try pt.intValue(Type.comptime_int, scalar_ty.intInfo(zcu).bits); | |
| 14296 | const bit_value = try pt.intValue(.comptime_int, scalar_ty.intInfo(zcu).bits); | |
| 14410 | 14297 | if (rhs_ty.zigTypeTag(zcu) == .vector) { |
| 14411 | 14298 | var i: usize = 0; |
| 14412 | 14299 | while (i < rhs_ty.vectorLen(zcu)) : (i += 1) { |
| ... | ... | @@ -14689,7 +14576,7 @@ fn analyzeTupleCat( |
| 14689 | 14576 | try sema.tupleFieldValByIndex(block, rhs, i, rhs_ty); |
| 14690 | 14577 | } |
| 14691 | 14578 | |
| 14692 | return block.addAggregateInit(Type.fromInterned(tuple_ty), element_refs); | |
| 14579 | return block.addAggregateInit(.fromInterned(tuple_ty), element_refs); | |
| 14693 | 14580 | } |
| 14694 | 14581 | |
| 14695 | 14582 | fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -14716,7 +14603,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14716 | 14603 | const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| 14717 | 14604 | |
| 14718 | 14605 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: { |
| 14719 | if (lhs_is_tuple) break :lhs_info @as(Type.ArrayInfo, undefined); | |
| 14606 | if (lhs_is_tuple) break :lhs_info undefined; | |
| 14720 | 14607 | return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(pt)}); |
| 14721 | 14608 | }; |
| 14722 | 14609 | const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse { |
| ... | ... | @@ -14892,7 +14779,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14892 | 14779 | |
| 14893 | 14780 | // lhs_dest_slice = dest[0..lhs.len] |
| 14894 | 14781 | const slice_ty_ref = Air.internedToRef(slice_ty.toIntern()); |
| 14895 | const lhs_len_ref = try pt.intRef(Type.usize, lhs_len); | |
| 14782 | const lhs_len_ref = try pt.intRef(.usize, lhs_len); | |
| 14896 | 14783 | const lhs_dest_slice = try block.addInst(.{ |
| 14897 | 14784 | .tag = .slice, |
| 14898 | 14785 | .data = .{ .ty_pl = .{ |
| ... | ... | @@ -14907,7 +14794,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14907 | 14794 | _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs); |
| 14908 | 14795 | |
| 14909 | 14796 | // rhs_dest_slice = dest[lhs.len..][0..rhs.len] |
| 14910 | const rhs_len_ref = try pt.intRef(Type.usize, rhs_len); | |
| 14797 | const rhs_len_ref = try pt.intRef(.usize, rhs_len); | |
| 14911 | 14798 | const rhs_dest_offset = try block.addInst(.{ |
| 14912 | 14799 | .tag = .ptr_add, |
| 14913 | 14800 | .data = .{ .ty_pl = .{ |
| ... | ... | @@ -14932,7 +14819,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14932 | 14819 | _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs); |
| 14933 | 14820 | |
| 14934 | 14821 | if (res_sent_val) |sent_val| { |
| 14935 | const elem_index = try pt.intRef(Type.usize, result_len); | |
| 14822 | const elem_index = try pt.intRef(.usize, result_len); | |
| 14936 | 14823 | const elem_ptr = try block.addPtrElemPtr(mutable_alloc, elem_index, elem_ptr_ty); |
| 14937 | 14824 | const init = Air.internedToRef((try pt.getCoerced(sent_val, lhs_info.elem_type)).toIntern()); |
| 14938 | 14825 | try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store); |
| ... | ... | @@ -14943,7 +14830,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14943 | 14830 | |
| 14944 | 14831 | var elem_i: u32 = 0; |
| 14945 | 14832 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 14946 | const elem_index = try pt.intRef(Type.usize, elem_i); | |
| 14833 | const elem_index = try pt.intRef(.usize, elem_i); | |
| 14947 | 14834 | const elem_ptr = try block.addPtrElemPtr(mutable_alloc, elem_index, elem_ptr_ty); |
| 14948 | 14835 | const operand_src = block.src(.{ .array_cat_lhs = .{ |
| 14949 | 14836 | .array_cat_offset = inst_data.src_node, |
| ... | ... | @@ -14954,8 +14841,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14954 | 14841 | } |
| 14955 | 14842 | while (elem_i < result_len) : (elem_i += 1) { |
| 14956 | 14843 | const rhs_elem_i = elem_i - lhs_len; |
| 14957 | const elem_index = try pt.intRef(Type.usize, elem_i); | |
| 14958 | const rhs_index = try pt.intRef(Type.usize, rhs_elem_i); | |
| 14844 | const elem_index = try pt.intRef(.usize, elem_i); | |
| 14845 | const rhs_index = try pt.intRef(.usize, rhs_elem_i); | |
| 14959 | 14846 | const elem_ptr = try block.addPtrElemPtr(mutable_alloc, elem_index, elem_ptr_ty); |
| 14960 | 14847 | const operand_src = block.src(.{ .array_cat_rhs = .{ |
| 14961 | 14848 | .array_cat_offset = inst_data.src_node, |
| ... | ... | @@ -14965,7 +14852,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14965 | 14852 | try sema.storePtr2(block, src, elem_ptr, src, init, operand_src, .store); |
| 14966 | 14853 | } |
| 14967 | 14854 | if (res_sent_val) |sent_val| { |
| 14968 | const elem_index = try pt.intRef(Type.usize, result_len); | |
| 14855 | const elem_index = try pt.intRef(.usize, result_len); | |
| 14969 | 14856 | const elem_ptr = try block.addPtrElemPtr(mutable_alloc, elem_index, elem_ptr_ty); |
| 14970 | 14857 | const init = Air.internedToRef((try pt.getCoerced(sent_val, lhs_info.elem_type)).toIntern()); |
| 14971 | 14858 | try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store); |
| ... | ... | @@ -14978,7 +14865,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14978 | 14865 | { |
| 14979 | 14866 | var elem_i: u32 = 0; |
| 14980 | 14867 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 14981 | const index = try pt.intRef(Type.usize, elem_i); | |
| 14868 | const index = try pt.intRef(.usize, elem_i); | |
| 14982 | 14869 | const operand_src = block.src(.{ .array_cat_lhs = .{ |
| 14983 | 14870 | .array_cat_offset = inst_data.src_node, |
| 14984 | 14871 | .elem_index = elem_i, |
| ... | ... | @@ -14988,7 +14875,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14988 | 14875 | } |
| 14989 | 14876 | while (elem_i < result_len) : (elem_i += 1) { |
| 14990 | 14877 | const rhs_elem_i = elem_i - lhs_len; |
| 14991 | const index = try pt.intRef(Type.usize, rhs_elem_i); | |
| 14878 | const index = try pt.intRef(.usize, rhs_elem_i); | |
| 14992 | 14879 | const operand_src = block.src(.{ .array_cat_rhs = .{ |
| 14993 | 14880 | .array_cat_offset = inst_data.src_node, |
| 14994 | 14881 | .elem_index = @intCast(rhs_elem_i), |
| ... | ... | @@ -15012,8 +14899,8 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 15012 | 14899 | switch (ptr_info.flags.size) { |
| 15013 | 14900 | .slice => { |
| 15014 | 14901 | const val = try sema.resolveConstDefinedValue(block, src, operand, .{ .simple = .slice_cat_operand }); |
| 15015 | return Type.ArrayInfo{ | |
| 15016 | .elem_type = Type.fromInterned(ptr_info.child), | |
| 14902 | return .{ | |
| 14903 | .elem_type = .fromInterned(ptr_info.child), | |
| 15017 | 14904 | .sentinel = switch (ptr_info.sentinel) { |
| 15018 | 14905 | .none => null, |
| 15019 | 14906 | else => Value.fromInterned(ptr_info.sentinel), |
| ... | ... | @@ -15113,7 +15000,7 @@ fn analyzeTupleMul( |
| 15113 | 15000 | @memcpy(element_refs[tuple_len * i ..][0..tuple_len], element_refs[0..tuple_len]); |
| 15114 | 15001 | } |
| 15115 | 15002 | |
| 15116 | return block.addAggregateInit(Type.fromInterned(tuple_ty), element_refs); | |
| 15003 | return block.addAggregateInit(.fromInterned(tuple_ty), element_refs); | |
| 15117 | 15004 | } |
| 15118 | 15005 | |
| 15119 | 15006 | fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -15166,7 +15053,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15166 | 15053 | |
| 15167 | 15054 | if (lhs_ty.isTuple(zcu)) { |
| 15168 | 15055 | // In `**` rhs must be comptime-known, but lhs can be runtime-known |
| 15169 | const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, .{ .simple = .array_mul_factor }); | |
| 15056 | const factor = try sema.resolveInt(block, rhs_src, extra.rhs, .usize, .{ .simple = .array_mul_factor }); | |
| 15170 | 15057 | const factor_casted = try sema.usizeCast(block, rhs_src, factor); |
| 15171 | 15058 | return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor_casted); |
| 15172 | 15059 | } |
| ... | ... | @@ -15188,7 +15075,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15188 | 15075 | }; |
| 15189 | 15076 | |
| 15190 | 15077 | // In `**` rhs must be comptime-known, but lhs can be runtime-known |
| 15191 | const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, .{ .simple = .array_mul_factor }); | |
| 15078 | const factor = try sema.resolveInt(block, rhs_src, extra.rhs, .usize, .{ .simple = .array_mul_factor }); | |
| 15192 | 15079 | |
| 15193 | 15080 | const result_len_u64 = std.math.mul(u64, lhs_info.len, factor) catch |
| 15194 | 15081 | return sema.fail(block, rhs_src, "operation results in overflow", .{}); |
| ... | ... | @@ -15246,7 +15133,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15246 | 15133 | // to get the same elem values. |
| 15247 | 15134 | const lhs_vals = try sema.arena.alloc(Air.Inst.Ref, lhs_len); |
| 15248 | 15135 | for (lhs_vals, 0..) |*lhs_val, idx| { |
| 15249 | const idx_ref = try pt.intRef(Type.usize, idx); | |
| 15136 | const idx_ref = try pt.intRef(.usize, idx); | |
| 15250 | 15137 | lhs_val.* = try sema.elemVal(block, lhs_src, lhs, idx_ref, src, false); |
| 15251 | 15138 | } |
| 15252 | 15139 | |
| ... | ... | @@ -15267,14 +15154,14 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15267 | 15154 | var elem_i: usize = 0; |
| 15268 | 15155 | while (elem_i < result_len) { |
| 15269 | 15156 | for (lhs_vals) |lhs_val| { |
| 15270 | const elem_index = try pt.intRef(Type.usize, elem_i); | |
| 15157 | const elem_index = try pt.intRef(.usize, elem_i); | |
| 15271 | 15158 | const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); |
| 15272 | 15159 | try sema.storePtr2(block, src, elem_ptr, src, lhs_val, lhs_src, .store); |
| 15273 | 15160 | elem_i += 1; |
| 15274 | 15161 | } |
| 15275 | 15162 | } |
| 15276 | 15163 | if (lhs_info.sentinel) |sent_val| { |
| 15277 | const elem_index = try pt.intRef(Type.usize, result_len); | |
| 15164 | const elem_index = try pt.intRef(.usize, result_len); | |
| 15278 | 15165 | const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); |
| 15279 | 15166 | const init = Air.internedToRef(sent_val.toIntern()); |
| 15280 | 15167 | try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store); |
| ... | ... | @@ -16131,15 +16018,14 @@ fn zirOverflowArithmetic( |
| 16131 | 16018 | const maybe_lhs_val = try sema.resolveValue(lhs); |
| 16132 | 16019 | const maybe_rhs_val = try sema.resolveValue(rhs); |
| 16133 | 16020 | |
| 16134 | const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty); | |
| 16135 | const overflow_ty = Type.fromInterned(ip.indexToKey(tuple_ty.toIntern()).tuple_type.types.get(ip)[1]); | |
| 16021 | const tuple_ty = try pt.overflowArithmeticTupleType(dest_ty); | |
| 16022 | const overflow_ty: Type = .fromInterned(ip.indexToKey(tuple_ty.toIntern()).tuple_type.types.get(ip)[1]); | |
| 16136 | 16023 | |
| 16137 | 16024 | var result: struct { |
| 16138 | 16025 | inst: Air.Inst.Ref = .none, |
| 16139 | 16026 | wrapped: Value = Value.@"unreachable", |
| 16140 | 16027 | overflow_bit: Value, |
| 16141 | 16028 | } = result: { |
| 16142 | const zero_bit = try pt.intValue(Type.u1, 0); | |
| 16143 | 16029 | switch (zir_tag) { |
| 16144 | 16030 | .add_with_overflow => { |
| 16145 | 16031 | // If either of the arguments is zero, `false` is returned and the other is stored |
| ... | ... | @@ -16147,12 +16033,12 @@ fn zirOverflowArithmetic( |
| 16147 | 16033 | // Otherwise, if either of the argument is undefined, undefined is returned. |
| 16148 | 16034 | if (maybe_lhs_val) |lhs_val| { |
| 16149 | 16035 | if (!lhs_val.isUndef(zcu) and (try lhs_val.compareAllWithZeroSema(.eq, pt))) { |
| 16150 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs }; | |
| 16036 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs }; | |
| 16151 | 16037 | } |
| 16152 | 16038 | } |
| 16153 | 16039 | if (maybe_rhs_val) |rhs_val| { |
| 16154 | 16040 | if (!rhs_val.isUndef(zcu) and (try rhs_val.compareAllWithZeroSema(.eq, pt))) { |
| 16155 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; | |
| 16041 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; | |
| 16156 | 16042 | } |
| 16157 | 16043 | } |
| 16158 | 16044 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -16173,7 +16059,7 @@ fn zirOverflowArithmetic( |
| 16173 | 16059 | if (rhs_val.isUndef(zcu)) { |
| 16174 | 16060 | break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef }; |
| 16175 | 16061 | } else if (try rhs_val.compareAllWithZeroSema(.eq, pt)) { |
| 16176 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; | |
| 16062 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; | |
| 16177 | 16063 | } else if (maybe_lhs_val) |lhs_val| { |
| 16178 | 16064 | if (lhs_val.isUndef(zcu)) { |
| 16179 | 16065 | break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef }; |
| ... | ... | @@ -16192,9 +16078,9 @@ fn zirOverflowArithmetic( |
| 16192 | 16078 | if (maybe_lhs_val) |lhs_val| { |
| 16193 | 16079 | if (!lhs_val.isUndef(zcu)) { |
| 16194 | 16080 | if (try lhs_val.compareAllWithZeroSema(.eq, pt)) { |
| 16195 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; | |
| 16081 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; | |
| 16196 | 16082 | } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) { |
| 16197 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs }; | |
| 16083 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs }; | |
| 16198 | 16084 | } |
| 16199 | 16085 | } |
| 16200 | 16086 | } |
| ... | ... | @@ -16202,9 +16088,9 @@ fn zirOverflowArithmetic( |
| 16202 | 16088 | if (maybe_rhs_val) |rhs_val| { |
| 16203 | 16089 | if (!rhs_val.isUndef(zcu)) { |
| 16204 | 16090 | if (try rhs_val.compareAllWithZeroSema(.eq, pt)) { |
| 16205 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs }; | |
| 16091 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs }; | |
| 16206 | 16092 | } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) { |
| 16207 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; | |
| 16093 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; | |
| 16208 | 16094 | } |
| 16209 | 16095 | } |
| 16210 | 16096 | } |
| ... | ... | @@ -16226,12 +16112,12 @@ fn zirOverflowArithmetic( |
| 16226 | 16112 | // Oterhwise if either of the arguments is undefined, both results are undefined. |
| 16227 | 16113 | if (maybe_lhs_val) |lhs_val| { |
| 16228 | 16114 | if (!lhs_val.isUndef(zcu) and (try lhs_val.compareAllWithZeroSema(.eq, pt))) { |
| 16229 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; | |
| 16115 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; | |
| 16230 | 16116 | } |
| 16231 | 16117 | } |
| 16232 | 16118 | if (maybe_rhs_val) |rhs_val| { |
| 16233 | 16119 | if (!rhs_val.isUndef(zcu) and (try rhs_val.compareAllWithZeroSema(.eq, pt))) { |
| 16234 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; | |
| 16120 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs }; | |
| 16235 | 16121 | } |
| 16236 | 16122 | } |
| 16237 | 16123 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -16305,24 +16191,6 @@ fn splat(sema: *Sema, ty: Type, val: Value) !Value { |
| 16305 | 16191 | return Value.fromInterned(repeated); |
| 16306 | 16192 | } |
| 16307 | 16193 | |
| 16308 | fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type { | |
| 16309 | const pt = sema.pt; | |
| 16310 | const zcu = pt.zcu; | |
| 16311 | const ip = &zcu.intern_pool; | |
| 16312 | const ov_ty = if (ty.zigTypeTag(zcu) == .vector) try pt.vectorType(.{ | |
| 16313 | .len = ty.vectorLen(zcu), | |
| 16314 | .child = .u1_type, | |
| 16315 | }) else Type.u1; | |
| 16316 | ||
| 16317 | const types = [2]InternPool.Index{ ty.toIntern(), ov_ty.toIntern() }; | |
| 16318 | const values = [2]InternPool.Index{ .none, .none }; | |
| 16319 | const tuple_ty = try ip.getTupleType(zcu.gpa, pt.tid, .{ | |
| 16320 | .types = &types, | |
| 16321 | .values = &values, | |
| 16322 | }); | |
| 16323 | return Type.fromInterned(tuple_ty); | |
| 16324 | } | |
| 16325 | ||
| 16326 | 16194 | fn analyzeArithmetic( |
| 16327 | 16195 | sema: *Sema, |
| 16328 | 16196 | block: *Block, |
| ... | ... | @@ -16380,7 +16248,7 @@ fn analyzeArithmetic( |
| 16380 | 16248 | const address = std.math.sub(u64, lhs_ptr.byte_offset, rhs_ptr.byte_offset) catch |
| 16381 | 16249 | return sema.fail(block, src, "operation results in overflow", .{}); |
| 16382 | 16250 | const result = address / elem_size; |
| 16383 | return try pt.intRef(Type.usize, result); | |
| 16251 | return try pt.intRef(.usize, result); | |
| 16384 | 16252 | } else { |
| 16385 | 16253 | break :runtime_src lhs_src; |
| 16386 | 16254 | } |
| ... | ... | @@ -16395,7 +16263,7 @@ fn analyzeArithmetic( |
| 16395 | 16263 | const lhs_int = try block.addBitCast(.usize, lhs); |
| 16396 | 16264 | const rhs_int = try block.addBitCast(.usize, rhs); |
| 16397 | 16265 | const address = try block.addBinOp(.sub_wrap, lhs_int, rhs_int); |
| 16398 | return try block.addBinOp(.div_exact, address, try pt.intRef(Type.usize, elem_size)); | |
| 16266 | return try block.addBinOp(.div_exact, address, try pt.intRef(.usize, elem_size)); | |
| 16399 | 16267 | } |
| 16400 | 16268 | } else { |
| 16401 | 16269 | switch (lhs_ty.ptrSize(zcu)) { |
| ... | ... | @@ -16498,42 +16366,10 @@ fn analyzeArithmetic( |
| 16498 | 16366 | } |
| 16499 | 16367 | |
| 16500 | 16368 | if (block.wantSafety() and want_safety and scalar_tag == .int) { |
| 16501 | if (zcu.backendSupportsFeature(.safety_checked_instructions)) { | |
| 16502 | if (air_tag != air_tag_safe) { | |
| 16503 | _ = try sema.preparePanicId(src, .integer_overflow); | |
| 16504 | } | |
| 16505 | return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs); | |
| 16506 | } else { | |
| 16507 | const maybe_op_ov: ?Air.Inst.Tag = switch (air_tag) { | |
| 16508 | .add => .add_with_overflow, | |
| 16509 | .sub => .sub_with_overflow, | |
| 16510 | .mul => .mul_with_overflow, | |
| 16511 | else => null, | |
| 16512 | }; | |
| 16513 | if (maybe_op_ov) |op_ov_tag| { | |
| 16514 | const op_ov_tuple_ty = try sema.overflowArithmeticTupleType(resolved_type); | |
| 16515 | const op_ov = try block.addInst(.{ | |
| 16516 | .tag = op_ov_tag, | |
| 16517 | .data = .{ .ty_pl = .{ | |
| 16518 | .ty = Air.internedToRef(op_ov_tuple_ty.toIntern()), | |
| 16519 | .payload = try sema.addExtra(Air.Bin{ | |
| 16520 | .lhs = casted_lhs, | |
| 16521 | .rhs = casted_rhs, | |
| 16522 | }), | |
| 16523 | } }, | |
| 16524 | }); | |
| 16525 | const ov_bit = try sema.tupleFieldValByIndex(block, op_ov, 1, op_ov_tuple_ty); | |
| 16526 | const any_ov_bit = if (resolved_type.zigTypeTag(zcu) == .vector) | |
| 16527 | try block.addReduce(ov_bit, .Or) | |
| 16528 | else | |
| 16529 | ov_bit; | |
| 16530 | const zero_ov = Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern()); | |
| 16531 | const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov); | |
| 16532 | ||
| 16533 | try sema.addSafetyCheck(block, src, no_ov, .integer_overflow); | |
| 16534 | return sema.tupleFieldValByIndex(block, op_ov, 0, op_ov_tuple_ty); | |
| 16535 | } | |
| 16369 | if (air_tag != air_tag_safe and zcu.backendSupportsFeature(.panic_fn)) { | |
| 16370 | _ = try sema.preparePanicId(src, .integer_overflow); | |
| 16536 | 16371 | } |
| 16372 | return block.addBinOp(air_tag_safe, casted_lhs, casted_rhs); | |
| 16537 | 16373 | } |
| 16538 | 16374 | return block.addBinOp(air_tag, casted_lhs, casted_rhs); |
| 16539 | 16375 | } |
| ... | ... | @@ -16550,7 +16386,7 @@ fn analyzePtrArithmetic( |
| 16550 | 16386 | ) CompileError!Air.Inst.Ref { |
| 16551 | 16387 | // TODO if the operand is comptime-known to be negative, or is a negative int, |
| 16552 | 16388 | // coerce to isize instead of usize. |
| 16553 | const offset = try sema.coerce(block, Type.usize, uncasted_offset, offset_src); | |
| 16389 | const offset = try sema.coerce(block, .usize, uncasted_offset, offset_src); | |
| 16554 | 16390 | const pt = sema.pt; |
| 16555 | 16391 | const zcu = pt.zcu; |
| 16556 | 16392 | const opt_ptr_val = try sema.resolveValue(ptr); |
| ... | ... | @@ -16736,8 +16572,8 @@ fn zirAsm( |
| 16736 | 16572 | const uncasted_arg = try sema.resolveInst(input.data.operand); |
| 16737 | 16573 | const uncasted_arg_ty = sema.typeOf(uncasted_arg); |
| 16738 | 16574 | switch (uncasted_arg_ty.zigTypeTag(zcu)) { |
| 16739 | .comptime_int => arg.* = try sema.coerce(block, Type.usize, uncasted_arg, src), | |
| 16740 | .comptime_float => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src), | |
| 16575 | .comptime_int => arg.* = try sema.coerce(block, .usize, uncasted_arg, src), | |
| 16576 | .comptime_float => arg.* = try sema.coerce(block, .f64, uncasted_arg, src), | |
| 16741 | 16577 | else => { |
| 16742 | 16578 | arg.* = uncasted_arg; |
| 16743 | 16579 | }, |
| ... | ... | @@ -16860,9 +16696,7 @@ fn zirCmpEq( |
| 16860 | 16696 | const runtime_src: LazySrcLoc = src: { |
| 16861 | 16697 | if (try sema.resolveValue(lhs)) |lval| { |
| 16862 | 16698 | if (try sema.resolveValue(rhs)) |rval| { |
| 16863 | if (lval.isUndef(zcu) or rval.isUndef(zcu)) { | |
| 16864 | return pt.undefRef(Type.bool); | |
| 16865 | } | |
| 16699 | if (lval.isUndef(zcu) or rval.isUndef(zcu)) return .undef_bool; | |
| 16866 | 16700 | const lkey = zcu.intern_pool.indexToKey(lval.toIntern()); |
| 16867 | 16701 | const rkey = zcu.intern_pool.indexToKey(rval.toIntern()); |
| 16868 | 16702 | return if ((lkey.err.name == rkey.err.name) == (op == .eq)) |
| ... | ... | @@ -16916,7 +16750,7 @@ fn analyzeCmpUnionTag( |
| 16916 | 16750 | const coerced_union = try sema.coerce(block, union_tag_ty, un, un_src); |
| 16917 | 16751 | |
| 16918 | 16752 | if (try sema.resolveValue(coerced_tag)) |enum_val| { |
| 16919 | if (enum_val.isUndef(zcu)) return pt.undefRef(Type.bool); | |
| 16753 | if (enum_val.isUndef(zcu)) return .undef_bool; | |
| 16920 | 16754 | const field_ty = union_ty.unionFieldType(enum_val, zcu).?; |
| 16921 | 16755 | if (field_ty.zigTypeTag(zcu) == .noreturn) { |
| 16922 | 16756 | return .bool_false; |
| ... | ... | @@ -17027,8 +16861,8 @@ fn cmpSelf( |
| 17027 | 16861 | |
| 17028 | 16862 | const maybe_lhs_val = try sema.resolveValue(casted_lhs); |
| 17029 | 16863 | const maybe_rhs_val = try sema.resolveValue(casted_rhs); |
| 17030 | if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(Type.bool); | |
| 17031 | if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(Type.bool); | |
| 16864 | if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return .undef_bool; | |
| 16865 | if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return .undef_bool; | |
| 17032 | 16866 | |
| 17033 | 16867 | const runtime_src: LazySrcLoc = src: { |
| 17034 | 16868 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -17083,7 +16917,7 @@ fn runtimeBoolCmp( |
| 17083 | 16917 | ) CompileError!Air.Inst.Ref { |
| 17084 | 16918 | if ((op == .neq) == rhs) { |
| 17085 | 16919 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 17086 | return block.addTyOp(.not, Type.bool, lhs); | |
| 16920 | return block.addTyOp(.not, .bool, lhs); | |
| 17087 | 16921 | } else { |
| 17088 | 16922 | return lhs; |
| 17089 | 16923 | } |
| ... | ... | @@ -17107,7 +16941,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 17107 | 16941 | .comptime_float, |
| 17108 | 16942 | .comptime_int, |
| 17109 | 16943 | .void, |
| 17110 | => return pt.intRef(Type.comptime_int, 0), | |
| 16944 | => return .zero, | |
| 17111 | 16945 | |
| 17112 | 16946 | .bool, |
| 17113 | 16947 | .int, |
| ... | ... | @@ -17148,7 +16982,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 17148 | 16982 | .comptime_float, |
| 17149 | 16983 | .comptime_int, |
| 17150 | 16984 | .void, |
| 17151 | => return pt.intRef(Type.comptime_int, 0), | |
| 16985 | => return .zero, | |
| 17152 | 16986 | |
| 17153 | 16987 | .bool, |
| 17154 | 16988 | .int, |
| ... | ... | @@ -17167,7 +17001,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 17167 | 17001 | => {}, |
| 17168 | 17002 | } |
| 17169 | 17003 | const bit_size = try operand_ty.bitSizeSema(pt); |
| 17170 | return pt.intRef(Type.comptime_int, bit_size); | |
| 17004 | return pt.intRef(.comptime_int, bit_size); | |
| 17171 | 17005 | } |
| 17172 | 17006 | |
| 17173 | 17007 | fn zirThis( |
| ... | ... | @@ -17285,7 +17119,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17285 | 17119 | |
| 17286 | 17120 | assert(block.is_typeof); |
| 17287 | 17121 | // We need a dummy runtime instruction with the correct type. |
| 17288 | return block.addTy(.alloc, Type.fromInterned(capture_ty)); | |
| 17122 | return block.addTy(.alloc, .fromInterned(capture_ty)); | |
| 17289 | 17123 | } |
| 17290 | 17124 | |
| 17291 | 17125 | fn zirRetAddr( |
| ... | ... | @@ -17293,10 +17127,11 @@ fn zirRetAddr( |
| 17293 | 17127 | block: *Block, |
| 17294 | 17128 | extended: Zir.Inst.Extended.InstData, |
| 17295 | 17129 | ) CompileError!Air.Inst.Ref { |
| 17130 | _ = sema; | |
| 17296 | 17131 | _ = extended; |
| 17297 | 17132 | if (block.isComptime()) { |
| 17298 | 17133 | // TODO: we could give a meaningful lazy value here. #14938 |
| 17299 | return sema.pt.intRef(Type.usize, 0); | |
| 17134 | return .zero_usize; | |
| 17300 | 17135 | } else { |
| 17301 | 17136 | return block.addNoOp(.ret_addr); |
| 17302 | 17137 | } |
| ... | ... | @@ -17349,7 +17184,7 @@ fn zirBuiltinSrc( |
| 17349 | 17184 | } }, |
| 17350 | 17185 | .byte_offset = 0, |
| 17351 | 17186 | } }), |
| 17352 | .len = (try pt.intValue(Type.usize, func_name_len)).toIntern(), | |
| 17187 | .len = (try pt.intValue(.usize, func_name_len)).toIntern(), | |
| 17353 | 17188 | } }); |
| 17354 | 17189 | }; |
| 17355 | 17190 | |
| ... | ... | @@ -17375,7 +17210,7 @@ fn zirBuiltinSrc( |
| 17375 | 17210 | } }, |
| 17376 | 17211 | .byte_offset = 0, |
| 17377 | 17212 | } }), |
| 17378 | .len = (try pt.intValue(Type.usize, module_name.len)).toIntern(), | |
| 17213 | .len = (try pt.intValue(.usize, module_name.len)).toIntern(), | |
| 17379 | 17214 | } }); |
| 17380 | 17215 | }; |
| 17381 | 17216 | |
| ... | ... | @@ -17401,7 +17236,7 @@ fn zirBuiltinSrc( |
| 17401 | 17236 | } }, |
| 17402 | 17237 | .byte_offset = 0, |
| 17403 | 17238 | } }), |
| 17404 | .len = (try pt.intValue(Type.usize, file_name.len)).toIntern(), | |
| 17239 | .len = (try pt.intValue(.usize, file_name.len)).toIntern(), | |
| 17405 | 17240 | } }); |
| 17406 | 17241 | }; |
| 17407 | 17242 | |
| ... | ... | @@ -17414,9 +17249,9 @@ fn zirBuiltinSrc( |
| 17414 | 17249 | // fn_name: [:0]const u8, |
| 17415 | 17250 | func_name_val, |
| 17416 | 17251 | // line: u32, |
| 17417 | (try pt.intValue(Type.u32, extra.line + 1)).toIntern(), | |
| 17252 | (try pt.intValue(.u32, extra.line + 1)).toIntern(), | |
| 17418 | 17253 | // column: u32, |
| 17419 | (try pt.intValue(Type.u32, extra.column + 1)).toIntern(), | |
| 17254 | (try pt.intValue(.u32, extra.column + 1)).toIntern(), | |
| 17420 | 17255 | }; |
| 17421 | 17256 | return Air.internedToRef((try pt.intern(.{ .aggregate = .{ |
| 17422 | 17257 | .ty = src_loc_ty.toIntern(), |
| ... | ... | @@ -17511,7 +17346,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17511 | 17346 | } }, |
| 17512 | 17347 | .byte_offset = 0, |
| 17513 | 17348 | } }), |
| 17514 | .len = (try pt.intValue(Type.usize, param_vals.len)).toIntern(), | |
| 17349 | .len = (try pt.intValue(.usize, param_vals.len)).toIntern(), | |
| 17515 | 17350 | } }); |
| 17516 | 17351 | }; |
| 17517 | 17352 | |
| ... | ... | @@ -17564,7 +17399,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17564 | 17399 | // signedness: Signedness, |
| 17565 | 17400 | (try pt.enumValueFieldIndex(signedness_ty, @intFromEnum(info.signedness))).toIntern(), |
| 17566 | 17401 | // bits: u16, |
| 17567 | (try pt.intValue(Type.u16, info.bits)).toIntern(), | |
| 17402 | (try pt.intValue(.u16, info.bits)).toIntern(), | |
| 17568 | 17403 | }; |
| 17569 | 17404 | return Air.internedToRef((try pt.internUnion(.{ |
| 17570 | 17405 | .ty = type_info_ty.toIntern(), |
| ... | ... | @@ -17580,7 +17415,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17580 | 17415 | |
| 17581 | 17416 | const field_vals = .{ |
| 17582 | 17417 | // bits: u16, |
| 17583 | (try pt.intValue(Type.u16, ty.bitSize(zcu))).toIntern(), | |
| 17418 | (try pt.intValue(.u16, ty.bitSize(zcu))).toIntern(), | |
| 17584 | 17419 | }; |
| 17585 | 17420 | return Air.internedToRef((try pt.internUnion(.{ |
| 17586 | 17421 | .ty = type_info_ty.toIntern(), |
| ... | ... | @@ -17594,7 +17429,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17594 | 17429 | .pointer => { |
| 17595 | 17430 | const info = ty.ptrInfo(zcu); |
| 17596 | 17431 | const alignment = if (info.flags.alignment.toByteUnits()) |alignment| |
| 17597 | try pt.intValue(Type.comptime_int, alignment) | |
| 17432 | try pt.intValue(.comptime_int, alignment) | |
| 17598 | 17433 | else |
| 17599 | 17434 | try Type.fromInterned(info.child).lazyAbiAlignment(pt); |
| 17600 | 17435 | |
| ... | ... | @@ -17638,7 +17473,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17638 | 17473 | const info = ty.arrayInfo(zcu); |
| 17639 | 17474 | const field_values = .{ |
| 17640 | 17475 | // len: comptime_int, |
| 17641 | (try pt.intValue(Type.comptime_int, info.len)).toIntern(), | |
| 17476 | (try pt.intValue(.comptime_int, info.len)).toIntern(), | |
| 17642 | 17477 | // child: type, |
| 17643 | 17478 | info.elem_type.toIntern(), |
| 17644 | 17479 | // sentinel: ?*const anyopaque, |
| ... | ... | @@ -17659,7 +17494,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17659 | 17494 | const info = ty.arrayInfo(zcu); |
| 17660 | 17495 | const field_values = .{ |
| 17661 | 17496 | // len: comptime_int, |
| 17662 | (try pt.intValue(Type.comptime_int, info.len)).toIntern(), | |
| 17497 | (try pt.intValue(.comptime_int, info.len)).toIntern(), | |
| 17663 | 17498 | // child: type, |
| 17664 | 17499 | info.elem_type.toIntern(), |
| 17665 | 17500 | }; |
| ... | ... | @@ -17723,7 +17558,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17723 | 17558 | } }, |
| 17724 | 17559 | .byte_offset = 0, |
| 17725 | 17560 | } }), |
| 17726 | .len = (try pt.intValue(Type.usize, error_name_len)).toIntern(), | |
| 17561 | .len = (try pt.intValue(.usize, error_name_len)).toIntern(), | |
| 17727 | 17562 | } }); |
| 17728 | 17563 | }; |
| 17729 | 17564 | |
| ... | ... | @@ -17770,7 +17605,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17770 | 17605 | } }, |
| 17771 | 17606 | .byte_offset = 0, |
| 17772 | 17607 | } }), |
| 17773 | .len = (try pt.intValue(Type.usize, vals.len)).toIntern(), | |
| 17608 | .len = (try pt.intValue(.usize, vals.len)).toIntern(), | |
| 17774 | 17609 | } }); |
| 17775 | 17610 | } else .none; |
| 17776 | 17611 | const errors_val = try pt.intern(.{ .opt = .{ |
| ... | ... | @@ -17819,7 +17654,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17819 | 17654 | .comptime_int_type, |
| 17820 | 17655 | ) |
| 17821 | 17656 | else |
| 17822 | (try pt.intValue(Type.comptime_int, tag_index)).toIntern(); | |
| 17657 | (try pt.intValue(.comptime_int, tag_index)).toIntern(); | |
| 17823 | 17658 | |
| 17824 | 17659 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| 17825 | 17660 | const name_val = v: { |
| ... | ... | @@ -17844,7 +17679,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17844 | 17679 | } }, |
| 17845 | 17680 | .byte_offset = 0, |
| 17846 | 17681 | } }), |
| 17847 | .len = (try pt.intValue(Type.usize, tag_name_len)).toIntern(), | |
| 17682 | .len = (try pt.intValue(.usize, tag_name_len)).toIntern(), | |
| 17848 | 17683 | } }); |
| 17849 | 17684 | }; |
| 17850 | 17685 | |
| ... | ... | @@ -17887,7 +17722,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17887 | 17722 | } }, |
| 17888 | 17723 | .byte_offset = 0, |
| 17889 | 17724 | } }), |
| 17890 | .len = (try pt.intValue(Type.usize, enum_field_vals.len)).toIntern(), | |
| 17725 | .len = (try pt.intValue(.usize, enum_field_vals.len)).toIntern(), | |
| 17891 | 17726 | } }); |
| 17892 | 17727 | }; |
| 17893 | 17728 | |
| ... | ... | @@ -17949,7 +17784,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17949 | 17784 | } }, |
| 17950 | 17785 | .byte_offset = 0, |
| 17951 | 17786 | } }), |
| 17952 | .len = (try pt.intValue(Type.usize, field_name_len)).toIntern(), | |
| 17787 | .len = (try pt.intValue(.usize, field_name_len)).toIntern(), | |
| 17953 | 17788 | } }); |
| 17954 | 17789 | }; |
| 17955 | 17790 | |
| ... | ... | @@ -17965,7 +17800,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17965 | 17800 | // type: type, |
| 17966 | 17801 | field_ty, |
| 17967 | 17802 | // alignment: comptime_int, |
| 17968 | (try pt.intValue(Type.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), | |
| 17803 | (try pt.intValue(.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), | |
| 17969 | 17804 | }; |
| 17970 | 17805 | field_val.* = try pt.intern(.{ .aggregate = .{ |
| 17971 | 17806 | .ty = union_field_ty.toIntern(), |
| ... | ... | @@ -18000,7 +17835,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18000 | 17835 | } }, |
| 18001 | 17836 | .byte_offset = 0, |
| 18002 | 17837 | } }), |
| 18003 | .len = (try pt.intValue(Type.usize, union_field_vals.len)).toIntern(), | |
| 17838 | .len = (try pt.intValue(.usize, union_field_vals.len)).toIntern(), | |
| 18004 | 17839 | } }); |
| 18005 | 17840 | }; |
| 18006 | 17841 | |
| ... | ... | @@ -18070,7 +17905,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18070 | 17905 | } }, |
| 18071 | 17906 | .byte_offset = 0, |
| 18072 | 17907 | } }), |
| 18073 | .len = (try pt.intValue(Type.usize, field_name_len)).toIntern(), | |
| 17908 | .len = (try pt.intValue(.usize, field_name_len)).toIntern(), | |
| 18074 | 17909 | } }); |
| 18075 | 17910 | }; |
| 18076 | 17911 | |
| ... | ... | @@ -18089,7 +17924,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18089 | 17924 | // is_comptime: bool, |
| 18090 | 17925 | Value.makeBool(is_comptime).toIntern(), |
| 18091 | 17926 | // alignment: comptime_int, |
| 18092 | (try pt.intValue(Type.comptime_int, Type.fromInterned(field_ty).abiAlignment(zcu).toByteUnits() orelse 0)).toIntern(), | |
| 17927 | (try pt.intValue(.comptime_int, Type.fromInterned(field_ty).abiAlignment(zcu).toByteUnits() orelse 0)).toIntern(), | |
| 18093 | 17928 | }; |
| 18094 | 17929 | struct_field_val.* = try pt.intern(.{ .aggregate = .{ |
| 18095 | 17930 | .ty = struct_field_ty.toIntern(), |
| ... | ... | @@ -18111,7 +17946,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18111 | 17946 | else |
| 18112 | 17947 | try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); |
| 18113 | 17948 | const field_name_len = field_name.length(ip); |
| 18114 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 17949 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 18115 | 17950 | const field_init = struct_type.fieldInit(ip, field_index); |
| 18116 | 17951 | const field_is_comptime = struct_type.fieldIsComptime(ip, field_index); |
| 18117 | 17952 | const name_val = v: { |
| ... | ... | @@ -18134,7 +17969,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18134 | 17969 | } }, |
| 18135 | 17970 | .byte_offset = 0, |
| 18136 | 17971 | } }), |
| 18137 | .len = (try pt.intValue(Type.usize, field_name_len)).toIntern(), | |
| 17972 | .len = (try pt.intValue(.usize, field_name_len)).toIntern(), | |
| 18138 | 17973 | } }); |
| 18139 | 17974 | }; |
| 18140 | 17975 | |
| ... | ... | @@ -18159,7 +17994,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18159 | 17994 | // is_comptime: bool, |
| 18160 | 17995 | Value.makeBool(field_is_comptime).toIntern(), |
| 18161 | 17996 | // alignment: comptime_int, |
| 18162 | (try pt.intValue(Type.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), | |
| 17997 | (try pt.intValue(.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), | |
| 18163 | 17998 | }; |
| 18164 | 17999 | field_val.* = try pt.intern(.{ .aggregate = .{ |
| 18165 | 18000 | .ty = struct_field_ty.toIntern(), |
| ... | ... | @@ -18195,7 +18030,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18195 | 18030 | } }, |
| 18196 | 18031 | .byte_offset = 0, |
| 18197 | 18032 | } }), |
| 18198 | .len = (try pt.intValue(Type.usize, struct_field_vals.len)).toIntern(), | |
| 18033 | .len = (try pt.intValue(.usize, struct_field_vals.len)).toIntern(), | |
| 18199 | 18034 | } }); |
| 18200 | 18035 | }; |
| 18201 | 18036 | |
| ... | ... | @@ -18304,7 +18139,7 @@ fn typeInfoDecls( |
| 18304 | 18139 | } }, |
| 18305 | 18140 | .byte_offset = 0, |
| 18306 | 18141 | } }), |
| 18307 | .len = (try pt.intValue(Type.usize, decl_vals.items.len)).toIntern(), | |
| 18142 | .len = (try pt.intValue(.usize, decl_vals.items.len)).toIntern(), | |
| 18308 | 18143 | } }); |
| 18309 | 18144 | } |
| 18310 | 18145 | |
| ... | ... | @@ -18354,7 +18189,7 @@ fn typeInfoNamespaceDecls( |
| 18354 | 18189 | .byte_offset = 0, |
| 18355 | 18190 | }, |
| 18356 | 18191 | }), |
| 18357 | .len = (try pt.intValue(Type.usize, name_len)).toIntern(), | |
| 18192 | .len = (try pt.intValue(.usize, name_len)).toIntern(), | |
| 18358 | 18193 | }, |
| 18359 | 18194 | }); |
| 18360 | 18195 | }; |
| ... | ... | @@ -18373,7 +18208,7 @@ fn typeInfoNamespaceDecls( |
| 18373 | 18208 | continue; |
| 18374 | 18209 | } |
| 18375 | 18210 | try sema.ensureNavResolved(block, src, nav, .fully); |
| 18376 | const namespace_ty = Type.fromInterned(ip.getNav(nav).status.fully_resolved.val); | |
| 18211 | const namespace_ty: Type = .fromInterned(ip.getNav(nav).status.fully_resolved.val); | |
| 18377 | 18212 | try sema.typeInfoNamespaceDecls(block, src, namespace_ty.getNamespaceIndex(zcu).toOptional(), declaration_ty, decl_vals, seen_namespaces); |
| 18378 | 18213 | } |
| 18379 | 18214 | } |
| ... | ... | @@ -18424,7 +18259,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi |
| 18424 | 18259 | const pt = sema.pt; |
| 18425 | 18260 | const zcu = pt.zcu; |
| 18426 | 18261 | switch (operand.zigTypeTag(zcu)) { |
| 18427 | .comptime_int => return Type.comptime_int, | |
| 18262 | .comptime_int => return .comptime_int, | |
| 18428 | 18263 | .int => { |
| 18429 | 18264 | const bits = operand.bitSize(zcu); |
| 18430 | 18265 | const count = if (bits == 0) |
| ... | ... | @@ -18512,14 +18347,12 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18512 | 18347 | const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); |
| 18513 | 18348 | const uncasted_operand = try sema.resolveInst(inst_data.operand); |
| 18514 | 18349 | |
| 18515 | const operand = try sema.coerce(block, Type.bool, uncasted_operand, operand_src); | |
| 18350 | const operand = try sema.coerce(block, .bool, uncasted_operand, operand_src); | |
| 18516 | 18351 | if (try sema.resolveValue(operand)) |val| { |
| 18517 | return if (val.isUndef(zcu)) | |
| 18518 | pt.undefRef(Type.bool) | |
| 18519 | else if (val.toBool()) .bool_false else .bool_true; | |
| 18352 | return if (val.isUndef(zcu)) .undef_bool else if (val.toBool()) .bool_false else .bool_true; | |
| 18520 | 18353 | } |
| 18521 | 18354 | try sema.requireRuntimeBlock(block, src, null); |
| 18522 | return block.addTyOp(.not, Type.bool, operand); | |
| 18355 | return block.addTyOp(.not, .bool, operand); | |
| 18523 | 18356 | } |
| 18524 | 18357 | |
| 18525 | 18358 | fn zirBoolBr( |
| ... | ... | @@ -18544,7 +18377,7 @@ fn zirBoolBr( |
| 18544 | 18377 | const lhs_src = parent_block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); |
| 18545 | 18378 | const rhs_src = parent_block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); |
| 18546 | 18379 | |
| 18547 | const lhs = try sema.coerce(parent_block, Type.bool, uncoerced_lhs, lhs_src); | |
| 18380 | const lhs = try sema.coerce(parent_block, .bool, uncoerced_lhs, lhs_src); | |
| 18548 | 18381 | |
| 18549 | 18382 | if (try sema.resolveDefinedValue(parent_block, lhs_src, lhs)) |lhs_val| { |
| 18550 | 18383 | if (is_bool_or and lhs_val.toBool()) { |
| ... | ... | @@ -18559,7 +18392,7 @@ fn zirBoolBr( |
| 18559 | 18392 | if (sema.typeOf(rhs_result).isNoReturn(zcu)) { |
| 18560 | 18393 | return rhs_result; |
| 18561 | 18394 | } |
| 18562 | return sema.coerce(parent_block, Type.bool, rhs_result, rhs_src); | |
| 18395 | return sema.coerce(parent_block, .bool, rhs_result, rhs_src); | |
| 18563 | 18396 | } |
| 18564 | 18397 | |
| 18565 | 18398 | const block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len); |
| ... | ... | @@ -18596,7 +18429,7 @@ fn zirBoolBr( |
| 18596 | 18429 | const rhs_result = try sema.resolveInlineBody(rhs_block, body, inst); |
| 18597 | 18430 | const rhs_noret = sema.typeOf(rhs_result).isNoReturn(zcu); |
| 18598 | 18431 | const coerced_rhs_result = if (!rhs_noret) rhs: { |
| 18599 | const coerced_result = try sema.coerce(rhs_block, Type.bool, rhs_result, rhs_src); | |
| 18432 | const coerced_result = try sema.coerce(rhs_block, .bool, rhs_result, rhs_src); | |
| 18600 | 18433 | _ = try rhs_block.addBr(block_inst, coerced_result); |
| 18601 | 18434 | break :rhs coerced_result; |
| 18602 | 18435 | } else rhs_result; |
| ... | ... | @@ -18797,7 +18630,7 @@ fn zirCondbr( |
| 18797 | 18630 | const else_body = sema.code.bodySlice(extra.end + then_body.len, extra.data.else_body_len); |
| 18798 | 18631 | |
| 18799 | 18632 | const uncasted_cond = try sema.resolveInst(extra.data.condition); |
| 18800 | const cond = try sema.coerce(parent_block, Type.bool, uncasted_cond, cond_src); | |
| 18633 | const cond = try sema.coerce(parent_block, .bool, uncasted_cond, cond_src); | |
| 18801 | 18634 | |
| 18802 | 18635 | if (try sema.resolveDefinedValue(parent_block, cond_src, cond)) |cond_val| { |
| 18803 | 18636 | const body = if (cond_val.toBool()) then_body else else_body; |
| ... | ... | @@ -19502,7 +19335,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19502 | 19335 | const abi_align: Alignment = if (inst_data.flags.has_align) blk: { |
| 19503 | 19336 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); |
| 19504 | 19337 | extra_i += 1; |
| 19505 | const coerced = try sema.coerce(block, Type.u32, try sema.resolveInst(ref), align_src); | |
| 19338 | const coerced = try sema.coerce(block, .u32, try sema.resolveInst(ref), align_src); | |
| 19506 | 19339 | const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" }); |
| 19507 | 19340 | // Check if this happens to be the lazy alignment of our element type, in |
| 19508 | 19341 | // which case we can make this 0 without resolving it. |
| ... | ... | @@ -19526,14 +19359,14 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 19526 | 19359 | const bit_offset: u16 = if (inst_data.flags.has_bit_range) blk: { |
| 19527 | 19360 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); |
| 19528 | 19361 | extra_i += 1; |
| 19529 | const bit_offset = try sema.resolveInt(block, bitoffset_src, ref, Type.u16, .{ .simple = .type }); | |
| 19362 | const bit_offset = try sema.resolveInt(block, bitoffset_src, ref, .u16, .{ .simple = .type }); | |
| 19530 | 19363 | break :blk @intCast(bit_offset); |
| 19531 | 19364 | } else 0; |
| 19532 | 19365 | |
| 19533 | 19366 | const host_size: u16 = if (inst_data.flags.has_bit_range) blk: { |
| 19534 | 19367 | const ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_i]); |
| 19535 | 19368 | extra_i += 1; |
| 19536 | const host_size = try sema.resolveInt(block, hostsize_src, ref, Type.u16, .{ .simple = .type }); | |
| 19369 | const host_size = try sema.resolveInt(block, hostsize_src, ref, .u16, .{ .simple = .type }); | |
| 19537 | 19370 | break :blk @intCast(host_size); |
| 19538 | 19371 | } else 0; |
| 19539 | 19372 | |
| ... | ... | @@ -19767,7 +19600,7 @@ fn unionInit( |
| 19767 | 19600 | const zcu = pt.zcu; |
| 19768 | 19601 | const ip = &zcu.intern_pool; |
| 19769 | 19602 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src); |
| 19770 | const field_ty = Type.fromInterned(zcu.typeToUnion(union_ty).?.field_types.get(ip)[field_index]); | |
| 19603 | const field_ty: Type = .fromInterned(zcu.typeToUnion(union_ty).?.field_types.get(ip)[field_index]); | |
| 19771 | 19604 | const init = try sema.coerce(block, field_ty, uncasted_init, init_src); |
| 19772 | 19605 | _ = union_ty_src; |
| 19773 | 19606 | return unionInitFromEnumTag(sema, block, init_src, union_ty, field_index, init); |
| ... | ... | @@ -19902,7 +19735,7 @@ fn zirStructInit( |
| 19902 | 19735 | const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src); |
| 19903 | 19736 | const tag_ty = resolved_ty.unionTagTypeHypothetical(zcu); |
| 19904 | 19737 | const tag_val = try pt.enumValueFieldIndex(tag_ty, field_index); |
| 19905 | const field_ty = Type.fromInterned(zcu.typeToUnion(resolved_ty).?.field_types.get(ip)[field_index]); | |
| 19738 | const field_ty: Type = .fromInterned(zcu.typeToUnion(resolved_ty).?.field_types.get(ip)[field_index]); | |
| 19906 | 19739 | |
| 19907 | 19740 | if (field_ty.zigTypeTag(zcu) == .noreturn) { |
| 19908 | 19741 | return sema.failWithOwnedErrorMsg(block, msg: { |
| ... | ... | @@ -19990,7 +19823,7 @@ fn finishStructInit( |
| 19990 | 19823 | .init_node_offset = init_src.offset.node_offset.x, |
| 19991 | 19824 | .elem_index = @intCast(i), |
| 19992 | 19825 | } }); |
| 19993 | const field_ty = Type.fromInterned(tuple.types.get(ip)[i]); | |
| 19826 | const field_ty: Type = .fromInterned(tuple.types.get(ip)[i]); | |
| 19994 | 19827 | field_inits[i] = try sema.coerce(block, field_ty, field_inits[i], field_src); |
| 19995 | 19828 | continue; |
| 19996 | 19829 | } |
| ... | ... | @@ -20018,7 +19851,7 @@ fn finishStructInit( |
| 20018 | 19851 | .init_node_offset = init_src.offset.node_offset.x, |
| 20019 | 19852 | .elem_index = @intCast(i), |
| 20020 | 19853 | } }); |
| 20021 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 19854 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 20022 | 19855 | field_inits[i] = try sema.coerce(block, field_ty, field_inits[i], field_src); |
| 20023 | 19856 | continue; |
| 20024 | 19857 | } |
| ... | ... | @@ -20183,7 +20016,7 @@ fn structInitAnon( |
| 20183 | 20016 | const msg = try sema.errMsg(field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); |
| 20184 | 20017 | errdefer msg.destroy(sema.gpa); |
| 20185 | 20018 | |
| 20186 | try sema.addDeclaredHereNote(msg, Type.fromInterned(field_ty.*)); | |
| 20019 | try sema.addDeclaredHereNote(msg, .fromInterned(field_ty.*)); | |
| 20187 | 20020 | break :msg msg; |
| 20188 | 20021 | }; |
| 20189 | 20022 | return sema.failWithOwnedErrorMsg(block, msg); |
| ... | ... | @@ -20317,7 +20150,7 @@ fn structInitAnon( |
| 20317 | 20150 | element_refs[i] = try sema.resolveInst(item.data.init); |
| 20318 | 20151 | } |
| 20319 | 20152 | |
| 20320 | return block.addAggregateInit(Type.fromInterned(struct_ty), element_refs); | |
| 20153 | return block.addAggregateInit(.fromInterned(struct_ty), element_refs); | |
| 20321 | 20154 | } |
| 20322 | 20155 | |
| 20323 | 20156 | fn zirArrayInit( |
| ... | ... | @@ -20441,7 +20274,7 @@ fn zirArrayInit( |
| 20441 | 20274 | }); |
| 20442 | 20275 | const elem_ptr_ty_ref = Air.internedToRef(elem_ptr_ty.toIntern()); |
| 20443 | 20276 | |
| 20444 | const index = try pt.intRef(Type.usize, i); | |
| 20277 | const index = try pt.intRef(.usize, i); | |
| 20445 | 20278 | const elem_ptr = try block.addPtrElemPtrTypeRef(base_ptr, index, elem_ptr_ty_ref); |
| 20446 | 20279 | _ = try block.addBinOp(.store, elem_ptr, arg); |
| 20447 | 20280 | } |
| ... | ... | @@ -20455,7 +20288,7 @@ fn zirArrayInit( |
| 20455 | 20288 | const elem_ptr_ty_ref = Air.internedToRef(elem_ptr_ty.toIntern()); |
| 20456 | 20289 | |
| 20457 | 20290 | for (resolved_args, 0..) |arg, i| { |
| 20458 | const index = try pt.intRef(Type.usize, i); | |
| 20291 | const index = try pt.intRef(.usize, i); | |
| 20459 | 20292 | const elem_ptr = try block.addPtrElemPtrTypeRef(base_ptr, index, elem_ptr_ty_ref); |
| 20460 | 20293 | _ = try block.addBinOp(.store, elem_ptr, arg); |
| 20461 | 20294 | } |
| ... | ... | @@ -20504,7 +20337,7 @@ fn arrayInitAnon( |
| 20504 | 20337 | const msg = try sema.errMsg(operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{}); |
| 20505 | 20338 | errdefer msg.destroy(gpa); |
| 20506 | 20339 | |
| 20507 | try sema.addDeclaredHereNote(msg, Type.fromInterned(types[i])); | |
| 20340 | try sema.addDeclaredHereNote(msg, .fromInterned(types[i])); | |
| 20508 | 20341 | break :msg msg; |
| 20509 | 20342 | }; |
| 20510 | 20343 | return sema.failWithOwnedErrorMsg(block, msg); |
| ... | ... | @@ -20561,7 +20394,7 @@ fn arrayInitAnon( |
| 20561 | 20394 | element_refs[i] = try sema.resolveInst(operand); |
| 20562 | 20395 | } |
| 20563 | 20396 | |
| 20564 | return block.addAggregateInit(Type.fromInterned(tuple_ty), element_refs); | |
| 20397 | return block.addAggregateInit(.fromInterned(tuple_ty), element_refs); | |
| 20565 | 20398 | } |
| 20566 | 20399 | |
| 20567 | 20400 | fn addConstantMaybeRef(sema: *Sema, val: InternPool.Index, is_ref: bool) !Air.Inst.Ref { |
| ... | ... | @@ -20632,7 +20465,7 @@ fn fieldType( |
| 20632 | 20465 | .optional => { |
| 20633 | 20466 | // Struct/array init through optional requires the child type to not be a pointer. |
| 20634 | 20467 | // If the child of .optional is a pointer it'll error on the next loop. |
| 20635 | cur_ty = Type.fromInterned(ip.indexToKey(cur_ty.toIntern()).opt_type); | |
| 20468 | cur_ty = .fromInterned(ip.indexToKey(cur_ty.toIntern()).opt_type); | |
| 20636 | 20469 | continue; |
| 20637 | 20470 | }, |
| 20638 | 20471 | .error_union => { |
| ... | ... | @@ -20710,44 +20543,32 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 20710 | 20543 | const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .u1_type, .len = len }) else .u1; |
| 20711 | 20544 | if (try sema.resolveValue(operand)) |val| { |
| 20712 | 20545 | if (!is_vector) { |
| 20713 | if (val.isUndef(zcu)) return pt.undefRef(Type.u1); | |
| 20714 | if (val.toBool()) return Air.internedToRef((try pt.intValue(Type.u1, 1)).toIntern()); | |
| 20715 | return Air.internedToRef((try pt.intValue(Type.u1, 0)).toIntern()); | |
| 20546 | return if (val.isUndef(zcu)) .undef_u1 else if (val.toBool()) .one_u1 else .zero_u1; | |
| 20716 | 20547 | } |
| 20717 | 20548 | if (val.isUndef(zcu)) return pt.undefRef(dest_ty); |
| 20718 | 20549 | const new_elems = try sema.arena.alloc(InternPool.Index, len); |
| 20719 | 20550 | for (new_elems, 0..) |*new_elem, i| { |
| 20720 | 20551 | const old_elem = try val.elemValue(pt, i); |
| 20721 | const new_val = if (old_elem.isUndef(zcu)) | |
| 20722 | try pt.undefValue(Type.u1) | |
| 20552 | new_elem.* = if (old_elem.isUndef(zcu)) | |
| 20553 | .undef_u1 | |
| 20723 | 20554 | else if (old_elem.toBool()) |
| 20724 | try pt.intValue(Type.u1, 1) | |
| 20555 | .one_u1 | |
| 20725 | 20556 | else |
| 20726 | try pt.intValue(Type.u1, 0); | |
| 20727 | new_elem.* = new_val.toIntern(); | |
| 20557 | .zero_u1; | |
| 20728 | 20558 | } |
| 20729 | 20559 | return Air.internedToRef(try pt.intern(.{ .aggregate = .{ |
| 20730 | 20560 | .ty = dest_ty.toIntern(), |
| 20731 | 20561 | .storage = .{ .elems = new_elems }, |
| 20732 | 20562 | } })); |
| 20733 | 20563 | } |
| 20734 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 20735 | return block.addBitCast(dest_ty, operand); | |
| 20736 | } | |
| 20737 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 20738 | for (new_elems, 0..) |*new_elem, i| { | |
| 20739 | const idx_ref = try pt.intRef(Type.usize, i); | |
| 20740 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 20741 | new_elem.* = try block.addBitCast(.u1, old_elem); | |
| 20742 | } | |
| 20743 | return block.addAggregateInit(dest_ty, new_elems); | |
| 20564 | return block.addBitCast(dest_ty, operand); | |
| 20744 | 20565 | } |
| 20745 | 20566 | |
| 20746 | 20567 | fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 20747 | 20568 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 20748 | 20569 | const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); |
| 20749 | 20570 | const uncoerced_operand = try sema.resolveInst(inst_data.operand); |
| 20750 | const operand = try sema.coerce(block, Type.anyerror, uncoerced_operand, operand_src); | |
| 20571 | const operand = try sema.coerce(block, .anyerror, uncoerced_operand, operand_src); | |
| 20751 | 20572 | |
| 20752 | 20573 | if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { |
| 20753 | 20574 | const err_name = sema.pt.zcu.intern_pool.indexToKey(val.toIntern()).err.name; |
| ... | ... | @@ -20993,12 +20814,12 @@ fn zirReify( |
| 20993 | 20814 | .float => { |
| 20994 | 20815 | const float = try sema.interpretBuiltinType(block, operand_src, .fromInterned(union_val.val), std.builtin.Type.Float); |
| 20995 | 20816 | |
| 20996 | const ty = switch (float.bits) { | |
| 20997 | 16 => Type.f16, | |
| 20998 | 32 => Type.f32, | |
| 20999 | 64 => Type.f64, | |
| 21000 | 80 => Type.f80, | |
| 21001 | 128 => Type.f128, | |
| 20817 | const ty: Type = switch (float.bits) { | |
| 20818 | 16 => .f16, | |
| 20819 | 32 => .f32, | |
| 20820 | 64 => .f64, | |
| 20821 | 80 => .f80, | |
| 20822 | 128 => .f128, | |
| 21002 | 20823 | else => return sema.fail(block, src, "{}-bit float unsupported", .{float.bits}), |
| 21003 | 20824 | }; |
| 21004 | 20825 | return Air.internedToRef(ty.toIntern()); |
| ... | ... | @@ -21038,7 +20859,7 @@ fn zirReify( |
| 21038 | 20859 | try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls), |
| 21039 | 20860 | ).?); |
| 21040 | 20861 | |
| 21041 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { | |
| 20862 | if (!try sema.intFitsInType(alignment_val, .u32, null)) { | |
| 21042 | 20863 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); |
| 21043 | 20864 | } |
| 21044 | 20865 | |
| ... | ... | @@ -21174,7 +20995,7 @@ fn zirReify( |
| 21174 | 20995 | }, |
| 21175 | 20996 | .error_set => { |
| 21176 | 20997 | const payload_val = Value.fromInterned(union_val.val).optionalValue(zcu) orelse |
| 21177 | return Air.internedToRef(Type.anyerror.toIntern()); | |
| 20998 | return .anyerror_type; | |
| 21178 | 20999 | |
| 21179 | 21000 | const names_val = try sema.derefSliceAsArray(block, src, payload_val, .{ .simple = .error_set_contents }); |
| 21180 | 21001 | |
| ... | ... | @@ -21776,7 +21597,7 @@ fn reifyUnion( |
| 21776 | 21597 | errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error |
| 21777 | 21598 | |
| 21778 | 21599 | for (field_types) |field_ty_ip| { |
| 21779 | const field_ty = Type.fromInterned(field_ty_ip); | |
| 21600 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 21780 | 21601 | if (field_ty.zigTypeTag(zcu) == .@"opaque") { |
| 21781 | 21602 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 21782 | 21603 | const msg = try sema.errMsg(src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{}); |
| ... | ... | @@ -22060,7 +21881,7 @@ fn reifyStruct( |
| 22060 | 21881 | } |
| 22061 | 21882 | |
| 22062 | 21883 | if (any_aligned_fields) { |
| 22063 | if (!try sema.intFitsInType(field_alignment_val, Type.u32, null)) { | |
| 21884 | if (!try sema.intFitsInType(field_alignment_val, .u32, null)) { | |
| 22064 | 21885 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); |
| 22065 | 21886 | } |
| 22066 | 21887 | |
| ... | ... | @@ -22149,7 +21970,7 @@ fn reifyStruct( |
| 22149 | 21970 | if (layout == .@"packed") { |
| 22150 | 21971 | var fields_bit_sum: u64 = 0; |
| 22151 | 21972 | for (0..struct_type.field_types.len) |field_idx| { |
| 22152 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_idx]); | |
| 21973 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_idx]); | |
| 22153 | 21974 | field_ty.resolveLayout(pt) catch |err| switch (err) { |
| 22154 | 21975 | error.AnalysisFail => { |
| 22155 | 21976 | const msg = sema.err orelse return err; |
| ... | ... | @@ -22325,7 +22146,7 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22325 | 22146 | if (block.wantSafety()) { |
| 22326 | 22147 | const len = dest_ty.vectorLen(zcu); |
| 22327 | 22148 | for (0..len) |i| { |
| 22328 | const idx_ref = try pt.intRef(Type.usize, i); | |
| 22149 | const idx_ref = try pt.intRef(.usize, i); | |
| 22329 | 22150 | const elem_ref = try block.addBinOp(.array_elem_val, operand, idx_ref); |
| 22330 | 22151 | const ok = try block.addBinOp(if (block.float_mode == .optimized) .cmp_eq_optimized else .cmp_eq, elem_ref, Air.internedToRef((try pt.floatValue(operand_scalar_ty, 0.0)).toIntern())); |
| 22331 | 22152 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); |
| ... | ... | @@ -22336,42 +22157,23 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22336 | 22157 | .storage = .{ .repeated_elem = (try pt.intValue(dest_scalar_ty, 0)).toIntern() }, |
| 22337 | 22158 | } })); |
| 22338 | 22159 | } |
| 22339 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 22340 | const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand); | |
| 22341 | if (block.wantSafety()) { | |
| 22342 | const back = try block.addTyOp(.float_from_int, operand_ty, result); | |
| 22343 | const diff = try block.addBinOp(if (block.float_mode == .optimized) .sub_optimized else .sub, operand, back); | |
| 22344 | const ok = if (is_vector) ok: { | |
| 22345 | const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt); | |
| 22346 | const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt); | |
| 22347 | const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg); | |
| 22348 | break :ok try block.addReduce(ok, .And); | |
| 22349 | } else ok: { | |
| 22350 | const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_ty, 1.0)).toIntern())); | |
| 22351 | const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_ty, -1.0)).toIntern())); | |
| 22352 | break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg); | |
| 22353 | }; | |
| 22354 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); | |
| 22355 | } | |
| 22356 | return result; | |
| 22357 | } | |
| 22358 | const len = dest_ty.vectorLen(zcu); | |
| 22359 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 22360 | for (new_elems, 0..) |*new_elem, i| { | |
| 22361 | const idx_ref = try pt.intRef(Type.usize, i); | |
| 22362 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 22363 | const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_scalar_ty, old_elem); | |
| 22364 | if (block.wantSafety()) { | |
| 22365 | const back = try block.addTyOp(.float_from_int, operand_scalar_ty, result); | |
| 22366 | const diff = try block.addBinOp(.sub, old_elem, back); | |
| 22367 | const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_scalar_ty, 1.0)).toIntern())); | |
| 22368 | const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_scalar_ty, -1.0)).toIntern())); | |
| 22369 | const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg); | |
| 22370 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); | |
| 22371 | } | |
| 22372 | new_elem.* = result; | |
| 22160 | const result = try block.addTyOp(if (block.float_mode == .optimized) .int_from_float_optimized else .int_from_float, dest_ty, operand); | |
| 22161 | if (block.wantSafety()) { | |
| 22162 | const back = try block.addTyOp(.float_from_int, operand_ty, result); | |
| 22163 | const diff = try block.addBinOp(if (block.float_mode == .optimized) .sub_optimized else .sub, operand, back); | |
| 22164 | const ok = if (is_vector) ok: { | |
| 22165 | const ok_pos = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, 1.0))).toIntern()), .lt); | |
| 22166 | const ok_neg = try block.addCmpVector(diff, Air.internedToRef((try sema.splat(operand_ty, try pt.floatValue(operand_scalar_ty, -1.0))).toIntern()), .gt); | |
| 22167 | const ok = try block.addBinOp(.bit_and, ok_pos, ok_neg); | |
| 22168 | break :ok try block.addReduce(ok, .And); | |
| 22169 | } else ok: { | |
| 22170 | const ok_pos = try block.addBinOp(if (block.float_mode == .optimized) .cmp_lt_optimized else .cmp_lt, diff, Air.internedToRef((try pt.floatValue(operand_ty, 1.0)).toIntern())); | |
| 22171 | const ok_neg = try block.addBinOp(if (block.float_mode == .optimized) .cmp_gt_optimized else .cmp_gt, diff, Air.internedToRef((try pt.floatValue(operand_ty, -1.0)).toIntern())); | |
| 22172 | break :ok try block.addBinOp(.bool_and, ok_pos, ok_neg); | |
| 22173 | }; | |
| 22174 | try sema.addSafetyCheck(block, src, ok, .integer_part_out_of_bounds); | |
| 22373 | 22175 | } |
| 22374 | return block.addAggregateInit(dest_ty, new_elems); | |
| 22176 | return result; | |
| 22375 | 22177 | } |
| 22376 | 22178 | |
| 22377 | 22179 | fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -22386,7 +22188,6 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22386 | 22188 | const operand_ty = sema.typeOf(operand); |
| 22387 | 22189 | |
| 22388 | 22190 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); |
| 22389 | const is_vector = dest_ty.zigTypeTag(zcu) == .vector; | |
| 22390 | 22191 | |
| 22391 | 22192 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 22392 | 22193 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| ... | ... | @@ -22402,17 +22203,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 22402 | 22203 | } |
| 22403 | 22204 | |
| 22404 | 22205 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 22405 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 22406 | return block.addTyOp(.float_from_int, dest_ty, operand); | |
| 22407 | } | |
| 22408 | const len = operand_ty.vectorLen(zcu); | |
| 22409 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 22410 | for (new_elems, 0..) |*new_elem, i| { | |
| 22411 | const idx_ref = try pt.intRef(Type.usize, i); | |
| 22412 | const old_elem = try block.addBinOp(.array_elem_val, operand, idx_ref); | |
| 22413 | new_elem.* = try block.addTyOp(.float_from_int, dest_scalar_ty, old_elem); | |
| 22414 | } | |
| 22415 | return block.addAggregateInit(dest_ty, new_elems); | |
| 22206 | return block.addTyOp(.float_from_int, dest_ty, operand); | |
| 22416 | 22207 | } |
| 22417 | 22208 | |
| 22418 | 22209 | fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -22431,10 +22222,10 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22431 | 22222 | try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, uncoerced_operand_ty, src, operand_src); |
| 22432 | 22223 | |
| 22433 | 22224 | const is_vector = dest_ty.zigTypeTag(zcu) == .vector; |
| 22434 | const operand_ty = if (is_vector) operand_ty: { | |
| 22225 | const operand_ty: Type = if (is_vector) operand_ty: { | |
| 22435 | 22226 | const len = dest_ty.vectorLen(zcu); |
| 22436 | 22227 | break :operand_ty try pt.vectorType(.{ .child = .usize_type, .len = len }); |
| 22437 | } else Type.usize; | |
| 22228 | } else .usize; | |
| 22438 | 22229 | |
| 22439 | 22230 | const operand_coerced = try sema.coerce(block, operand_ty, operand_res, operand_src); |
| 22440 | 22231 | |
| ... | ... | @@ -22482,69 +22273,34 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22482 | 22273 | } |
| 22483 | 22274 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 22484 | 22275 | try sema.checkLogicalPtrOperation(block, src, ptr_ty); |
| 22485 | if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) { | |
| 22486 | if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) { | |
| 22487 | if (!ptr_ty.isAllowzeroPtr(zcu)) { | |
| 22488 | const is_non_zero = if (is_vector) all_non_zero: { | |
| 22489 | const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); | |
| 22490 | const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq); | |
| 22491 | break :all_non_zero try block.addReduce(is_non_zero, .And); | |
| 22492 | } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); | |
| 22493 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | |
| 22494 | } | |
| 22495 | if (ptr_align.compare(.gt, .@"1")) { | |
| 22496 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; | |
| 22497 | const align_mask = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue( | |
| 22498 | Type.usize, | |
| 22499 | if (elem_ty.fnPtrMaskOrNull(zcu)) |mask| | |
| 22500 | align_bytes_minus_1 & mask | |
| 22501 | else | |
| 22502 | align_bytes_minus_1, | |
| 22503 | ))).toIntern()); | |
| 22504 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_mask); | |
| 22505 | const is_aligned = if (is_vector) all_aligned: { | |
| 22506 | const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); | |
| 22507 | const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq); | |
| 22508 | break :all_aligned try block.addReduce(is_aligned, .And); | |
| 22509 | } else try block.addBinOp(.cmp_eq, remainder, .zero_usize); | |
| 22510 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); | |
| 22511 | } | |
| 22512 | } | |
| 22513 | return block.addBitCast(dest_ty, operand_coerced); | |
| 22514 | } | |
| 22515 | ||
| 22516 | const len = dest_ty.vectorLen(zcu); | |
| 22517 | 22276 | if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) { |
| 22518 | for (0..len) |i| { | |
| 22519 | const idx_ref = try pt.intRef(Type.usize, i); | |
| 22520 | const elem_coerced = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref); | |
| 22521 | if (!ptr_ty.isAllowzeroPtr(zcu)) { | |
| 22522 | const is_non_zero = try block.addBinOp(.cmp_neq, elem_coerced, .zero_usize); | |
| 22523 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | |
| 22524 | } | |
| 22525 | if (ptr_align.compare(.gt, .@"1")) { | |
| 22526 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; | |
| 22527 | const align_mask = Air.internedToRef((try pt.intValue( | |
| 22528 | Type.usize, | |
| 22529 | if (elem_ty.fnPtrMaskOrNull(zcu)) |mask| | |
| 22530 | align_bytes_minus_1 & mask | |
| 22531 | else | |
| 22532 | align_bytes_minus_1, | |
| 22533 | )).toIntern()); | |
| 22534 | const remainder = try block.addBinOp(.bit_and, elem_coerced, align_mask); | |
| 22535 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); | |
| 22536 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); | |
| 22537 | } | |
| 22277 | if (!ptr_ty.isAllowzeroPtr(zcu)) { | |
| 22278 | const is_non_zero = if (is_vector) all_non_zero: { | |
| 22279 | const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); | |
| 22280 | const is_non_zero = try block.addCmpVector(operand_coerced, zero_usize, .neq); | |
| 22281 | break :all_non_zero try block.addReduce(is_non_zero, .And); | |
| 22282 | } else try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize); | |
| 22283 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | |
| 22284 | } | |
| 22285 | if (ptr_align.compare(.gt, .@"1")) { | |
| 22286 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; | |
| 22287 | const align_mask = Air.internedToRef((try sema.splat(operand_ty, try pt.intValue( | |
| 22288 | .usize, | |
| 22289 | if (elem_ty.fnPtrMaskOrNull(zcu)) |mask| | |
| 22290 | align_bytes_minus_1 & mask | |
| 22291 | else | |
| 22292 | align_bytes_minus_1, | |
| 22293 | ))).toIntern()); | |
| 22294 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_mask); | |
| 22295 | const is_aligned = if (is_vector) all_aligned: { | |
| 22296 | const splat_zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern()); | |
| 22297 | const is_aligned = try block.addCmpVector(remainder, splat_zero_usize, .eq); | |
| 22298 | break :all_aligned try block.addReduce(is_aligned, .And); | |
| 22299 | } else try block.addBinOp(.cmp_eq, remainder, .zero_usize); | |
| 22300 | try sema.addSafetyCheck(block, src, is_aligned, .incorrect_alignment); | |
| 22538 | 22301 | } |
| 22539 | 22302 | } |
| 22540 | ||
| 22541 | const new_elems = try sema.arena.alloc(Air.Inst.Ref, len); | |
| 22542 | for (new_elems, 0..) |*new_elem, i| { | |
| 22543 | const idx_ref = try pt.intRef(Type.usize, i); | |
| 22544 | const old_elem = try block.addBinOp(.array_elem_val, operand_coerced, idx_ref); | |
| 22545 | new_elem.* = try block.addBitCast(ptr_ty, old_elem); | |
| 22546 | } | |
| 22547 | return block.addAggregateInit(dest_ty, new_elems); | |
| 22303 | return block.addBitCast(dest_ty, operand_coerced); | |
| 22548 | 22304 | } |
| 22549 | 22305 | |
| 22550 | 22306 | fn ptrFromIntVal( |
| ... | ... | @@ -22918,12 +22674,12 @@ fn ptrCastFull( |
| 22918 | 22674 | } |
| 22919 | 22675 | |
| 22920 | 22676 | check_child: { |
| 22921 | const src_child = if (dest_info.flags.size == .slice and src_info.flags.size == .one) blk: { | |
| 22677 | const src_child: Type = if (dest_info.flags.size == .slice and src_info.flags.size == .one) blk: { | |
| 22922 | 22678 | // *[n]T -> []T |
| 22923 | 22679 | break :blk Type.fromInterned(src_info.child).childType(zcu); |
| 22924 | } else Type.fromInterned(src_info.child); | |
| 22680 | } else .fromInterned(src_info.child); | |
| 22925 | 22681 | |
| 22926 | const dest_child = Type.fromInterned(dest_info.child); | |
| 22682 | const dest_child: Type = .fromInterned(dest_info.child); | |
| 22927 | 22683 | |
| 22928 | 22684 | const imc_res = try sema.coerceInMemoryAllowed( |
| 22929 | 22685 | block, |
| ... | ... | @@ -22956,7 +22712,7 @@ fn ptrCastFull( |
| 22956 | 22712 | } |
| 22957 | 22713 | if (is_array_ptr_to_slice) { |
| 22958 | 22714 | // [*]nT -> []T |
| 22959 | const arr_ty = Type.fromInterned(src_info.child); | |
| 22715 | const arr_ty: Type = .fromInterned(src_info.child); | |
| 22960 | 22716 | if (arr_ty.sentinel(zcu)) |src_sentinel| { |
| 22961 | 22717 | const coerced_sent = try zcu.intern_pool.getCoerced(sema.gpa, pt.tid, src_sentinel.toIntern(), dest_info.child); |
| 22962 | 22718 | if (dest_info.sentinel == coerced_sent) break :check_sent; |
| ... | ... | @@ -23158,7 +22914,7 @@ fn ptrCastFull( |
| 23158 | 22914 | if (dest_info.flags.size == .slice) { |
| 23159 | 22915 | // Because the operand is comptime-known and not `null`, the slice length has already been computed: |
| 23160 | 22916 | const len: Value = switch (dest_slice_len.?) { |
| 23161 | .undef => try pt.undefValue(.usize), | |
| 22917 | .undef => .undef_usize, | |
| 23162 | 22918 | .constant => |n| try pt.intValue(.usize, n), |
| 23163 | 22919 | .equal_runtime_src_slice => unreachable, |
| 23164 | 22920 | .change_runtime_src_slice => unreachable, |
| ... | ... | @@ -23267,7 +23023,7 @@ fn ptrCastFull( |
| 23267 | 23023 | if (need_align_check) { |
| 23268 | 23024 | assert(operand_ptr_int != .none); |
| 23269 | 23025 | const align_mask = try pt.intRef(.usize, mask: { |
| 23270 | const target_ptr_mask: u64 = Type.fromInterned(dest_info.child).fnPtrMaskOrNull(zcu) orelse ~@as(u64, 0); | |
| 23026 | const target_ptr_mask = Type.fromInterned(dest_info.child).fnPtrMaskOrNull(zcu) orelse ~@as(u64, 0); | |
| 23271 | 23027 | break :mask (dest_align.toByteUnits().? - 1) & target_ptr_mask; |
| 23272 | 23028 | }); |
| 23273 | 23029 | const ptr_masked = try block.addBinOp(.bit_and, operand_ptr_int, align_mask); |
| ... | ... | @@ -23288,7 +23044,7 @@ fn ptrCastFull( |
| 23288 | 23044 | assert(need_operand_ptr); |
| 23289 | 23045 | |
| 23290 | 23046 | const result_len: Air.Inst.Ref = switch (dest_slice_len.?) { |
| 23291 | .undef => try pt.undefRef(.usize), | |
| 23047 | .undef => .undef_usize, | |
| 23292 | 23048 | .constant => |n| try pt.intRef(.usize, n), |
| 23293 | 23049 | .equal_runtime_src_slice => len: { |
| 23294 | 23050 | assert(need_operand_len); |
| ... | ... | @@ -23658,13 +23414,13 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 23658 | 23414 | |
| 23659 | 23415 | fn zirBitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 23660 | 23416 | const offset = try sema.bitOffsetOf(block, inst); |
| 23661 | return sema.pt.intRef(Type.comptime_int, offset); | |
| 23417 | return sema.pt.intRef(.comptime_int, offset); | |
| 23662 | 23418 | } |
| 23663 | 23419 | |
| 23664 | 23420 | fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 23665 | 23421 | const offset = try sema.bitOffsetOf(block, inst); |
| 23666 | 23422 | // TODO reminder to make this a compile error for packed structs |
| 23667 | return sema.pt.intRef(Type.comptime_int, offset / 8); | |
| 23423 | return sema.pt.intRef(.comptime_int, offset / 8); | |
| 23668 | 23424 | } |
| 23669 | 23425 | |
| 23670 | 23426 | fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u64 { |
| ... | ... | @@ -23705,7 +23461,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 |
| 23705 | 23461 | if (i == field_index) { |
| 23706 | 23462 | return bit_sum; |
| 23707 | 23463 | } |
| 23708 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 23464 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 23709 | 23465 | bit_sum += field_ty.bitSize(zcu); |
| 23710 | 23466 | } else unreachable; |
| 23711 | 23467 | }, |
| ... | ... | @@ -24497,8 +24253,8 @@ fn analyzeShuffle( |
| 24497 | 24253 | block: *Block, |
| 24498 | 24254 | src_node: std.zig.Ast.Node.Offset, |
| 24499 | 24255 | elem_ty: Type, |
| 24500 | a_arg: Air.Inst.Ref, | |
| 24501 | b_arg: Air.Inst.Ref, | |
| 24256 | a_uncoerced: Air.Inst.Ref, | |
| 24257 | b_uncoerced: Air.Inst.Ref, | |
| 24502 | 24258 | mask: Value, |
| 24503 | 24259 | mask_len: u32, |
| 24504 | 24260 | ) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -24507,150 +24263,154 @@ fn analyzeShuffle( |
| 24507 | 24263 | const a_src = block.builtinCallArgSrc(src_node, 1); |
| 24508 | 24264 | const b_src = block.builtinCallArgSrc(src_node, 2); |
| 24509 | 24265 | const mask_src = block.builtinCallArgSrc(src_node, 3); |
| 24510 | var a = a_arg; | |
| 24511 | var b = b_arg; | |
| 24512 | ||
| 24513 | const res_ty = try pt.vectorType(.{ | |
| 24514 | .len = mask_len, | |
| 24515 | .child = elem_ty.toIntern(), | |
| 24516 | }); | |
| 24517 | 24266 | |
| 24518 | const maybe_a_len = switch (sema.typeOf(a).zigTypeTag(zcu)) { | |
| 24519 | .array, .vector => sema.typeOf(a).arrayLen(zcu), | |
| 24520 | .undefined => null, | |
| 24521 | else => return sema.fail(block, a_src, "expected vector or array with element type '{}', found '{}'", .{ | |
| 24522 | elem_ty.fmt(pt), | |
| 24523 | sema.typeOf(a).fmt(pt), | |
| 24524 | }), | |
| 24525 | }; | |
| 24526 | const maybe_b_len = switch (sema.typeOf(b).zigTypeTag(zcu)) { | |
| 24527 | .array, .vector => sema.typeOf(b).arrayLen(zcu), | |
| 24528 | .undefined => null, | |
| 24529 | else => return sema.fail(block, b_src, "expected vector or array with element type '{}', found '{}'", .{ | |
| 24530 | elem_ty.fmt(pt), | |
| 24531 | sema.typeOf(b).fmt(pt), | |
| 24532 | }), | |
| 24533 | }; | |
| 24534 | if (maybe_a_len == null and maybe_b_len == null) { | |
| 24535 | return pt.undefRef(res_ty); | |
| 24536 | } | |
| 24537 | const a_len: u32 = @intCast(maybe_a_len orelse maybe_b_len.?); | |
| 24538 | const b_len: u32 = @intCast(maybe_b_len orelse a_len); | |
| 24539 | ||
| 24540 | const a_ty = try pt.vectorType(.{ | |
| 24541 | .len = a_len, | |
| 24542 | .child = elem_ty.toIntern(), | |
| 24543 | }); | |
| 24544 | const b_ty = try pt.vectorType(.{ | |
| 24545 | .len = b_len, | |
| 24546 | .child = elem_ty.toIntern(), | |
| 24547 | }); | |
| 24548 | ||
| 24549 | if (maybe_a_len == null) a = try pt.undefRef(a_ty) else a = try sema.coerce(block, a_ty, a, a_src); | |
| 24550 | if (maybe_b_len == null) b = try pt.undefRef(b_ty) else b = try sema.coerce(block, b_ty, b, b_src); | |
| 24551 | ||
| 24552 | const operand_info = [2]std.meta.Tuple(&.{ u64, LazySrcLoc, Type }){ | |
| 24553 | .{ a_len, a_src, a_ty }, | |
| 24554 | .{ b_len, b_src, b_ty }, | |
| 24555 | }; | |
| 24556 | ||
| 24557 | for (0..@intCast(mask_len)) |i| { | |
| 24558 | const elem = try mask.elemValue(pt, i); | |
| 24559 | if (elem.isUndef(zcu)) continue; | |
| 24560 | const elem_resolved = try sema.resolveLazyValue(elem); | |
| 24561 | const int = elem_resolved.toSignedInt(zcu); | |
| 24562 | var unsigned: u32 = undefined; | |
| 24563 | var chosen: u32 = undefined; | |
| 24564 | if (int >= 0) { | |
| 24565 | unsigned = @intCast(int); | |
| 24566 | chosen = 0; | |
| 24567 | } else { | |
| 24568 | unsigned = @intCast(~int); | |
| 24569 | chosen = 1; | |
| 24267 | // If the type of `a` is `@Type(.undefined)`, i.e. the argument is untyped, this is 0, because it is an error to index into this vector. | |
| 24268 | const a_len: u32 = switch (sema.typeOf(a_uncoerced).zigTypeTag(zcu)) { | |
| 24269 | .array, .vector => @intCast(sema.typeOf(a_uncoerced).arrayLen(zcu)), | |
| 24270 | .undefined => 0, | |
| 24271 | else => return sema.fail(block, a_src, "expected vector of '{}', found '{}'", .{ elem_ty.fmt(pt), sema.typeOf(a_uncoerced).fmt(pt) }), | |
| 24272 | }; | |
| 24273 | const a_ty = try pt.vectorType(.{ .len = a_len, .child = elem_ty.toIntern() }); | |
| 24274 | const a_coerced = try sema.coerce(block, a_ty, a_uncoerced, a_src); | |
| 24275 | ||
| 24276 | // If the type of `b` is `@Type(.undefined)`, i.e. the argument is untyped, this is 0, because it is an error to index into this vector. | |
| 24277 | const b_len: u32 = switch (sema.typeOf(b_uncoerced).zigTypeTag(zcu)) { | |
| 24278 | .array, .vector => @intCast(sema.typeOf(b_uncoerced).arrayLen(zcu)), | |
| 24279 | .undefined => 0, | |
| 24280 | else => return sema.fail(block, b_src, "expected vector of '{}', found '{}'", .{ elem_ty.fmt(pt), sema.typeOf(b_uncoerced).fmt(pt) }), | |
| 24281 | }; | |
| 24282 | const b_ty = try pt.vectorType(.{ .len = b_len, .child = elem_ty.toIntern() }); | |
| 24283 | const b_coerced = try sema.coerce(block, b_ty, b_uncoerced, b_src); | |
| 24284 | ||
| 24285 | const result_ty = try pt.vectorType(.{ .len = mask_len, .child = elem_ty.toIntern() }); | |
| 24286 | ||
| 24287 | // We're going to pre-emptively reserve space in `sema.air_extra`. The reason for this is we need | |
| 24288 | // a `u32` buffer of length `mask_len` anyway, and putting it in `sema.air_extra` avoids a copy | |
| 24289 | // in the runtime case. If the result is comptime-known, we'll shrink `air_extra` back. | |
| 24290 | const air_extra_idx: u32 = @intCast(sema.air_extra.items.len); | |
| 24291 | const air_mask_buf = try sema.air_extra.addManyAsSlice(sema.gpa, mask_len); | |
| 24292 | ||
| 24293 | // We want to interpret that buffer in `air_extra` in a few ways. Initially, we'll consider its | |
| 24294 | // elements as `Air.Inst.ShuffleTwoMask`, essentially representing the raw mask values; then, we'll | |
| 24295 | // convert it to `InternPool.Index` or `Air.Inst.ShuffleOneMask` if there are comptime-known operands. | |
| 24296 | const mask_ip_index: []InternPool.Index = @ptrCast(air_mask_buf); | |
| 24297 | const mask_shuffle_one: []Air.ShuffleOneMask = @ptrCast(air_mask_buf); | |
| 24298 | const mask_shuffle_two: []Air.ShuffleTwoMask = @ptrCast(air_mask_buf); | |
| 24299 | ||
| 24300 | // Initial loop: check mask elements, populate `mask_shuffle_two`. | |
| 24301 | var a_used = false; | |
| 24302 | var b_used = false; | |
| 24303 | for (mask_shuffle_two, 0..mask_len) |*out, mask_idx| { | |
| 24304 | const mask_val = try mask.elemValue(pt, mask_idx); | |
| 24305 | if (mask_val.isUndef(zcu)) { | |
| 24306 | out.* = .undef; | |
| 24307 | continue; | |
| 24570 | 24308 | } |
| 24571 | if (unsigned >= operand_info[chosen][0]) { | |
| 24572 | const msg = msg: { | |
| 24573 | const msg = try sema.errMsg(mask_src, "mask index '{d}' has out-of-bounds selection", .{i}); | |
| 24309 | // Safe because mask elements are `i32` and we already checked for undef: | |
| 24310 | const raw = (try sema.resolveLazyValue(mask_val)).toSignedInt(zcu); | |
| 24311 | if (raw >= 0) { | |
| 24312 | const idx: u32 = @intCast(raw); | |
| 24313 | a_used = true; | |
| 24314 | out.* = .aElem(idx); | |
| 24315 | if (idx >= a_len) return sema.failWithOwnedErrorMsg(block, msg: { | |
| 24316 | const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx}); | |
| 24574 | 24317 | errdefer msg.destroy(sema.gpa); |
| 24575 | ||
| 24576 | try sema.errNote(operand_info[chosen][1], msg, "selected index '{d}' out of bounds of '{}'", .{ | |
| 24577 | unsigned, | |
| 24578 | operand_info[chosen][2].fmt(pt), | |
| 24579 | }); | |
| 24580 | ||
| 24581 | if (chosen == 0) { | |
| 24582 | try sema.errNote(b_src, msg, "selections from the second vector are specified with negative numbers", .{}); | |
| 24318 | try sema.errNote(a_src, msg, "index '{d}' exceeds bounds of '{}' given here", .{ idx, a_ty.fmt(pt) }); | |
| 24319 | if (idx < b_len) { | |
| 24320 | try sema.errNote(b_src, msg, "use '~@as(u32, {d})' to index into second vector given here", .{idx}); | |
| 24583 | 24321 | } |
| 24584 | ||
| 24585 | 24322 | break :msg msg; |
| 24586 | }; | |
| 24587 | return sema.failWithOwnedErrorMsg(block, msg); | |
| 24323 | }); | |
| 24324 | } else { | |
| 24325 | const idx: u32 = @intCast(~raw); | |
| 24326 | b_used = true; | |
| 24327 | out.* = .bElem(idx); | |
| 24328 | if (idx >= b_len) return sema.failWithOwnedErrorMsg(block, msg: { | |
| 24329 | const msg = try sema.errMsg(mask_src, "mask element at index '{d}' selects out-of-bounds index", .{mask_idx}); | |
| 24330 | errdefer msg.destroy(sema.gpa); | |
| 24331 | try sema.errNote(b_src, msg, "index '{d}' exceeds bounds of '{}' given here", .{ idx, b_ty.fmt(pt) }); | |
| 24332 | break :msg msg; | |
| 24333 | }); | |
| 24588 | 24334 | } |
| 24589 | 24335 | } |
| 24590 | 24336 | |
| 24591 | if (try sema.resolveValue(a)) |a_val| { | |
| 24592 | if (try sema.resolveValue(b)) |b_val| { | |
| 24593 | const values = try sema.arena.alloc(InternPool.Index, mask_len); | |
| 24594 | for (values, 0..) |*value, i| { | |
| 24595 | const mask_elem_val = try mask.elemValue(pt, i); | |
| 24596 | if (mask_elem_val.isUndef(zcu)) { | |
| 24597 | value.* = try pt.intern(.{ .undef = elem_ty.toIntern() }); | |
| 24598 | continue; | |
| 24599 | } | |
| 24600 | const int = mask_elem_val.toSignedInt(zcu); | |
| 24601 | const unsigned: u32 = @intCast(if (int >= 0) int else ~int); | |
| 24602 | values[i] = (try (if (int >= 0) a_val else b_val).elemValue(pt, unsigned)).toIntern(); | |
| 24603 | } | |
| 24604 | return Air.internedToRef((try pt.intern(.{ .aggregate = .{ | |
| 24605 | .ty = res_ty.toIntern(), | |
| 24606 | .storage = .{ .elems = values }, | |
| 24607 | } }))); | |
| 24608 | } | |
| 24609 | } | |
| 24337 | const maybe_a_val = try sema.resolveValue(a_coerced); | |
| 24338 | const maybe_b_val = try sema.resolveValue(b_coerced); | |
| 24610 | 24339 | |
| 24611 | // All static analysis passed, and not comptime. | |
| 24612 | // For runtime codegen, vectors a and b must be the same length. Here we | |
| 24613 | // recursively @shuffle the smaller vector to append undefined elements | |
| 24614 | // to it up to the length of the longer vector. This recursion terminates | |
| 24615 | // in 1 call because these calls to analyzeShuffle guarantee a_len == b_len. | |
| 24616 | if (a_len != b_len) { | |
| 24617 | const min_len = @min(a_len, b_len); | |
| 24618 | const max_src = if (a_len > b_len) a_src else b_src; | |
| 24619 | const max_len = try sema.usizeCast(block, max_src, @max(a_len, b_len)); | |
| 24340 | const a_rt = a_used and maybe_a_val == null; | |
| 24341 | const b_rt = b_used and maybe_b_val == null; | |
| 24620 | 24342 | |
| 24621 | const expand_mask_values = try sema.arena.alloc(InternPool.Index, max_len); | |
| 24622 | for (@intCast(0)..@intCast(min_len)) |i| { | |
| 24623 | expand_mask_values[i] = (try pt.intValue(Type.comptime_int, i)).toIntern(); | |
| 24343 | if (a_rt and b_rt) { | |
| 24344 | // Both operands are needed and runtime-known. We need a `[]ShuffleTwomask`... which is | |
| 24345 | // exactly what we already have in `mask_shuffle_two`! So, we're basically done already. | |
| 24346 | // We just need to append the two operands. | |
| 24347 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, 2); | |
| 24348 | sema.appendRefsAssumeCapacity(&.{ a_coerced, b_coerced }); | |
| 24349 | return block.addInst(.{ | |
| 24350 | .tag = .shuffle_two, | |
| 24351 | .data = .{ .ty_pl = .{ | |
| 24352 | .ty = Air.internedToRef(result_ty.toIntern()), | |
| 24353 | .payload = air_extra_idx, | |
| 24354 | } }, | |
| 24355 | }); | |
| 24356 | } else if (a_rt) { | |
| 24357 | // We need to convert the `ShuffleTwoMask` values to `ShuffleOneMask`. | |
| 24358 | for (mask_shuffle_two, mask_shuffle_one) |in, *out| { | |
| 24359 | out.* = switch (in.unwrap()) { | |
| 24360 | .undef => .value(try pt.undefValue(elem_ty)), | |
| 24361 | .a_elem => |idx| .elem(idx), | |
| 24362 | .b_elem => |idx| .value(try maybe_b_val.?.elemValue(pt, idx)), | |
| 24363 | }; | |
| 24624 | 24364 | } |
| 24625 | for (@intCast(min_len)..@intCast(max_len)) |i| { | |
| 24626 | expand_mask_values[i] = (try pt.intValue(Type.comptime_int, -1)).toIntern(); | |
| 24365 | // Now just append our single runtime operand, and we're done. | |
| 24366 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, 1); | |
| 24367 | sema.appendRefsAssumeCapacity(&.{a_coerced}); | |
| 24368 | return block.addInst(.{ | |
| 24369 | .tag = .shuffle_one, | |
| 24370 | .data = .{ .ty_pl = .{ | |
| 24371 | .ty = Air.internedToRef(result_ty.toIntern()), | |
| 24372 | .payload = air_extra_idx, | |
| 24373 | } }, | |
| 24374 | }); | |
| 24375 | } else if (b_rt) { | |
| 24376 | // We need to convert the `ShuffleTwoMask` values to `ShuffleOneMask`. | |
| 24377 | for (mask_shuffle_two, mask_shuffle_one) |in, *out| { | |
| 24378 | out.* = switch (in.unwrap()) { | |
| 24379 | .undef => .value(try pt.undefValue(elem_ty)), | |
| 24380 | .a_elem => |idx| .value(try maybe_a_val.?.elemValue(pt, idx)), | |
| 24381 | .b_elem => |idx| .elem(idx), | |
| 24382 | }; | |
| 24627 | 24383 | } |
| 24628 | const expand_mask = try pt.intern(.{ .aggregate = .{ | |
| 24629 | .ty = (try pt.vectorType(.{ .len = @intCast(max_len), .child = .comptime_int_type })).toIntern(), | |
| 24630 | .storage = .{ .elems = expand_mask_values }, | |
| 24631 | } }); | |
| 24632 | ||
| 24633 | if (a_len < b_len) { | |
| 24634 | const undef = try pt.undefRef(a_ty); | |
| 24635 | a = try sema.analyzeShuffle(block, src_node, elem_ty, a, undef, Value.fromInterned(expand_mask), @intCast(max_len)); | |
| 24636 | } else { | |
| 24637 | const undef = try pt.undefRef(b_ty); | |
| 24638 | b = try sema.analyzeShuffle(block, src_node, elem_ty, b, undef, Value.fromInterned(expand_mask), @intCast(max_len)); | |
| 24384 | // Now just append our single runtime operand, and we're done. | |
| 24385 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, 1); | |
| 24386 | sema.appendRefsAssumeCapacity(&.{b_coerced}); | |
| 24387 | return block.addInst(.{ | |
| 24388 | .tag = .shuffle_one, | |
| 24389 | .data = .{ .ty_pl = .{ | |
| 24390 | .ty = Air.internedToRef(result_ty.toIntern()), | |
| 24391 | .payload = air_extra_idx, | |
| 24392 | } }, | |
| 24393 | }); | |
| 24394 | } else { | |
| 24395 | // The result will be comptime-known. We must convert the `ShuffleTwoMask` values to | |
| 24396 | // `InternPool.Index` values using the known operands. | |
| 24397 | for (mask_shuffle_two, mask_ip_index) |in, *out| { | |
| 24398 | const val: Value = switch (in.unwrap()) { | |
| 24399 | .undef => try pt.undefValue(elem_ty), | |
| 24400 | .a_elem => |idx| try maybe_a_val.?.elemValue(pt, idx), | |
| 24401 | .b_elem => |idx| try maybe_b_val.?.elemValue(pt, idx), | |
| 24402 | }; | |
| 24403 | out.* = val.toIntern(); | |
| 24639 | 24404 | } |
| 24405 | const res = try pt.intern(.{ .aggregate = .{ | |
| 24406 | .ty = result_ty.toIntern(), | |
| 24407 | .storage = .{ .elems = mask_ip_index }, | |
| 24408 | } }); | |
| 24409 | // We have a comptime-known result, so didn't need `air_mask_buf` -- remove it from `sema.air_extra`. | |
| 24410 | assert(sema.air_extra.items.len == air_extra_idx + air_mask_buf.len); | |
| 24411 | sema.air_extra.shrinkRetainingCapacity(air_extra_idx); | |
| 24412 | return Air.internedToRef(res); | |
| 24640 | 24413 | } |
| 24641 | ||
| 24642 | return block.addInst(.{ | |
| 24643 | .tag = .shuffle, | |
| 24644 | .data = .{ .ty_pl = .{ | |
| 24645 | .ty = Air.internedToRef(res_ty.toIntern()), | |
| 24646 | .payload = try block.sema.addExtra(Air.Shuffle{ | |
| 24647 | .a = a, | |
| 24648 | .b = b, | |
| 24649 | .mask = mask.toIntern(), | |
| 24650 | .mask_len = mask_len, | |
| 24651 | }), | |
| 24652 | } }, | |
| 24653 | }); | |
| 24654 | 24414 | } |
| 24655 | 24415 | |
| 24656 | 24416 | fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -25087,7 +24847,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins |
| 25087 | 24847 | if (parent_ptr_info.flags.size != .one) { |
| 25088 | 24848 | return sema.fail(block, inst_src, "expected single pointer type, found '{}'", .{parent_ptr_ty.fmt(pt)}); |
| 25089 | 24849 | } |
| 25090 | const parent_ty = Type.fromInterned(parent_ptr_info.child); | |
| 24850 | const parent_ty: Type = .fromInterned(parent_ptr_info.child); | |
| 25091 | 24851 | switch (parent_ty.zigTypeTag(zcu)) { |
| 25092 | 24852 | .@"struct", .@"union" => {}, |
| 25093 | 24853 | else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(pt)}), |
| ... | ... | @@ -25741,7 +25501,7 @@ fn zirMemcpy( |
| 25741 | 25501 | if (try sema.resolveDefinedValue(block, dest_src, dest_len)) |dest_len_val| { |
| 25742 | 25502 | len_val = dest_len_val; |
| 25743 | 25503 | if (try sema.resolveDefinedValue(block, src_src, src_len)) |src_len_val| { |
| 25744 | if (!(try sema.valuesEqual(dest_len_val, src_len_val, Type.usize))) { | |
| 25504 | if (!(try sema.valuesEqual(dest_len_val, src_len_val, .usize))) { | |
| 25745 | 25505 | const msg = msg: { |
| 25746 | 25506 | const msg = try sema.errMsg(src, "non-matching copy lengths", .{}); |
| 25747 | 25507 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -25952,7 +25712,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 25952 | 25712 | const dest_elem_ty: Type = dest_elem_ty: { |
| 25953 | 25713 | const ptr_info = dest_ptr_ty.ptrInfo(zcu); |
| 25954 | 25714 | switch (ptr_info.flags.size) { |
| 25955 | .slice => break :dest_elem_ty Type.fromInterned(ptr_info.child), | |
| 25715 | .slice => break :dest_elem_ty .fromInterned(ptr_info.child), | |
| 25956 | 25716 | .one => { |
| 25957 | 25717 | if (Type.fromInterned(ptr_info.child).zigTypeTag(zcu) == .array) { |
| 25958 | 25718 | break :dest_elem_ty Type.fromInterned(ptr_info.child).childType(zcu); |
| ... | ... | @@ -26118,7 +25878,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 26118 | 25878 | extra_index += body.len; |
| 26119 | 25879 | if (extra.data.bits.ret_ty_is_generic) break :blk .generic_poison; |
| 26120 | 25880 | |
| 26121 | const val = try sema.resolveGenericBody(block, ret_src, body, inst, Type.type, .{ .simple = .function_ret_ty }); | |
| 25881 | const val = try sema.resolveGenericBody(block, ret_src, body, inst, .type, .{ .simple = .function_ret_ty }); | |
| 26122 | 25882 | const ty = val.toType(); |
| 26123 | 25883 | break :blk ty; |
| 26124 | 25884 | } else if (extra.data.bits.has_ret_ty_ref) blk: { |
| ... | ... | @@ -26129,7 +25889,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 26129 | 25889 | const ret_ty_air_ref = try sema.resolveInst(ret_ty_ref); |
| 26130 | 25890 | const ret_ty_val = try sema.resolveConstDefinedValue(block, ret_src, ret_ty_air_ref, .{ .simple = .function_ret_ty }); |
| 26131 | 25891 | break :blk ret_ty_val.toType(); |
| 26132 | } else Type.void; | |
| 25892 | } else .void; | |
| 26133 | 25893 | |
| 26134 | 25894 | const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: { |
| 26135 | 25895 | const x = sema.code.extra[extra_index]; |
| ... | ... | @@ -26223,7 +25983,7 @@ fn zirWasmMemorySize( |
| 26223 | 25983 | return sema.fail(block, builtin_src, "builtin @wasmMemorySize is available when targeting WebAssembly; targeted CPU architecture is {s}", .{@tagName(target.cpu.arch)}); |
| 26224 | 25984 | } |
| 26225 | 25985 | |
| 26226 | const index: u32 = @intCast(try sema.resolveInt(block, index_src, extra.operand, Type.u32, .{ .simple = .wasm_memory_index })); | |
| 25986 | const index: u32 = @intCast(try sema.resolveInt(block, index_src, extra.operand, .u32, .{ .simple = .wasm_memory_index })); | |
| 26227 | 25987 | try sema.requireRuntimeBlock(block, builtin_src, null); |
| 26228 | 25988 | return block.addInst(.{ |
| 26229 | 25989 | .tag = .wasm_memory_size, |
| ... | ... | @@ -26248,8 +26008,8 @@ fn zirWasmMemoryGrow( |
| 26248 | 26008 | return sema.fail(block, builtin_src, "builtin @wasmMemoryGrow is available when targeting WebAssembly; targeted CPU architecture is {s}", .{@tagName(target.cpu.arch)}); |
| 26249 | 26009 | } |
| 26250 | 26010 | |
| 26251 | const index: u32 = @intCast(try sema.resolveInt(block, index_src, extra.lhs, Type.u32, .{ .simple = .wasm_memory_index })); | |
| 26252 | const delta = try sema.coerce(block, Type.usize, try sema.resolveInst(extra.rhs), delta_src); | |
| 26011 | const index: u32 = @intCast(try sema.resolveInt(block, index_src, extra.lhs, .u32, .{ .simple = .wasm_memory_index })); | |
| 26012 | const delta = try sema.coerce(block, .usize, try sema.resolveInst(extra.rhs), delta_src); | |
| 26253 | 26013 | |
| 26254 | 26014 | try sema.requireRuntimeBlock(block, builtin_src, null); |
| 26255 | 26015 | return block.addInst(.{ |
| ... | ... | @@ -26484,7 +26244,7 @@ fn zirWorkItem( |
| 26484 | 26244 | }, |
| 26485 | 26245 | } |
| 26486 | 26246 | |
| 26487 | const dimension: u32 = @intCast(try sema.resolveInt(block, dimension_src, extra.operand, Type.u32, .{ .simple = .work_group_dim_index })); | |
| 26247 | const dimension: u32 = @intCast(try sema.resolveInt(block, dimension_src, extra.operand, .u32, .{ .simple = .work_group_dim_index })); | |
| 26488 | 26248 | try sema.requireRuntimeBlock(block, builtin_src, null); |
| 26489 | 26249 | |
| 26490 | 26250 | return block.addInst(.{ |
| ... | ... | @@ -26552,7 +26312,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD |
| 26552 | 26312 | const inline_tag_val = try pt.enumValue( |
| 26553 | 26313 | callconv_tag_ty, |
| 26554 | 26314 | (try pt.intValue( |
| 26555 | Type.u8, | |
| 26315 | .u8, | |
| 26556 | 26316 | @intFromEnum(std.builtin.CallingConvention.@"inline"), |
| 26557 | 26317 | )).toIntern(), |
| 26558 | 26318 | ); |
| ... | ... | @@ -26760,7 +26520,7 @@ fn explainWhyTypeIsComptimeInner( |
| 26760 | 26520 | |
| 26761 | 26521 | if (zcu.typeToStruct(ty)) |struct_type| { |
| 26762 | 26522 | for (0..struct_type.field_types.len) |i| { |
| 26763 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 26523 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 26764 | 26524 | const field_src: LazySrcLoc = .{ |
| 26765 | 26525 | .base_node_inst = struct_type.zir_index, |
| 26766 | 26526 | .offset = .{ .container_field_type = @intCast(i) }, |
| ... | ... | @@ -26780,7 +26540,7 @@ fn explainWhyTypeIsComptimeInner( |
| 26780 | 26540 | |
| 26781 | 26541 | if (zcu.typeToUnion(ty)) |union_obj| { |
| 26782 | 26542 | for (0..union_obj.field_types.len) |i| { |
| 26783 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[i]); | |
| 26543 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[i]); | |
| 26784 | 26544 | const field_src: LazySrcLoc = .{ |
| 26785 | 26545 | .base_node_inst = union_obj.zir_index, |
| 26786 | 26546 | .offset = .{ .container_field_type = @intCast(i) }, |
| ... | ... | @@ -27171,7 +26931,7 @@ fn addSafetyCheckUnwrapError( |
| 27171 | 26931 | |
| 27172 | 26932 | defer fail_block.instructions.deinit(gpa); |
| 27173 | 26933 | |
| 27174 | const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand); | |
| 26934 | const err = try fail_block.addTyOp(unwrap_err_tag, .anyerror, operand); | |
| 27175 | 26935 | try safetyPanicUnwrapError(sema, &fail_block, src, err); |
| 27176 | 26936 | |
| 27177 | 26937 | try sema.addSafetyCheckExtra(parent_block, ok, &fail_block); |
| ... | ... | @@ -27344,7 +27104,7 @@ fn fieldVal( |
| 27344 | 27104 | switch (inner_ty.zigTypeTag(zcu)) { |
| 27345 | 27105 | .array => { |
| 27346 | 27106 | if (field_name.eqlSlice("len", ip)) { |
| 27347 | return Air.internedToRef((try pt.intValue(Type.usize, inner_ty.arrayLen(zcu))).toIntern()); | |
| 27107 | return Air.internedToRef((try pt.intValue(.usize, inner_ty.arrayLen(zcu))).toIntern()); | |
| 27348 | 27108 | } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { |
| 27349 | 27109 | const ptr_info = object_ty.ptrInfo(zcu); |
| 27350 | 27110 | const result_ty = try pt.ptrTypeSema(.{ |
| ... | ... | @@ -27527,7 +27287,7 @@ fn fieldPtr( |
| 27527 | 27287 | switch (inner_ty.zigTypeTag(zcu)) { |
| 27528 | 27288 | .array => { |
| 27529 | 27289 | if (field_name.eqlSlice("len", ip)) { |
| 27530 | const int_val = try pt.intValue(Type.usize, inner_ty.arrayLen(zcu)); | |
| 27290 | const int_val = try pt.intValue(.usize, inner_ty.arrayLen(zcu)); | |
| 27531 | 27291 | return uavRef(sema, int_val.toIntern()); |
| 27532 | 27292 | } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) { |
| 27533 | 27293 | const ptr_info = object_ty.ptrInfo(zcu); |
| ... | ... | @@ -27769,12 +27529,12 @@ fn fieldCallBind( |
| 27769 | 27529 | if (zcu.typeToStruct(concrete_ty)) |struct_type| { |
| 27770 | 27530 | const field_index = struct_type.nameIndex(ip, field_name) orelse |
| 27771 | 27531 | break :find_field; |
| 27772 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 27532 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 27773 | 27533 | |
| 27774 | 27534 | return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr); |
| 27775 | 27535 | } else if (concrete_ty.isTuple(zcu)) { |
| 27776 | 27536 | if (field_name.eqlSlice("len", ip)) { |
| 27777 | return .{ .direct = try pt.intRef(Type.usize, concrete_ty.structFieldCount(zcu)) }; | |
| 27537 | return .{ .direct = try pt.intRef(.usize, concrete_ty.structFieldCount(zcu)) }; | |
| 27778 | 27538 | } |
| 27779 | 27539 | if (field_name.toUnsigned(ip)) |field_index| { |
| 27780 | 27540 | if (field_index >= concrete_ty.structFieldCount(zcu)) break :find_field; |
| ... | ... | @@ -27817,7 +27577,7 @@ fn fieldCallBind( |
| 27817 | 27577 | if (zcu.typeToFunc(decl_type)) |func_type| f: { |
| 27818 | 27578 | if (func_type.param_types.len == 0) break :f; |
| 27819 | 27579 | |
| 27820 | const first_param_type = Type.fromInterned(func_type.param_types.get(ip)[0]); | |
| 27580 | const first_param_type: Type = .fromInterned(func_type.param_types.get(ip)[0]); | |
| 27821 | 27581 | if (first_param_type.isGenericPoison() or |
| 27822 | 27582 | (first_param_type.zigTypeTag(zcu) == .pointer and |
| 27823 | 27583 | (first_param_type.ptrSize(zcu) == .one or |
| ... | ... | @@ -28003,7 +27763,7 @@ fn structFieldPtr( |
| 28003 | 27763 | |
| 28004 | 27764 | if (struct_ty.isTuple(zcu)) { |
| 28005 | 27765 | if (field_name.eqlSlice("len", ip)) { |
| 28006 | const len_inst = try pt.intRef(Type.usize, struct_ty.structFieldCount(zcu)); | |
| 27766 | const len_inst = try pt.intRef(.usize, struct_ty.structFieldCount(zcu)); | |
| 28007 | 27767 | return sema.analyzeRef(block, src, len_inst); |
| 28008 | 27768 | } |
| 28009 | 27769 | const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); |
| ... | ... | @@ -28134,7 +27894,7 @@ fn structFieldVal( |
| 28134 | 27894 | return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]); |
| 28135 | 27895 | } |
| 28136 | 27896 | |
| 28137 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 27897 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 28138 | 27898 | if (try sema.typeHasOnePossibleValue(field_ty)) |field_val| |
| 28139 | 27899 | return Air.internedToRef(field_val.toIntern()); |
| 28140 | 27900 | |
| ... | ... | @@ -28167,7 +27927,7 @@ fn tupleFieldVal( |
| 28167 | 27927 | const pt = sema.pt; |
| 28168 | 27928 | const zcu = pt.zcu; |
| 28169 | 27929 | if (field_name.eqlSlice("len", &zcu.intern_pool)) { |
| 28170 | return pt.intRef(Type.usize, tuple_ty.structFieldCount(zcu)); | |
| 27930 | return pt.intRef(.usize, tuple_ty.structFieldCount(zcu)); | |
| 28171 | 27931 | } |
| 28172 | 27932 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src); |
| 28173 | 27933 | return sema.tupleFieldValByIndex(block, tuple_byval, field_index, tuple_ty); |
| ... | ... | @@ -28220,7 +27980,7 @@ fn tupleFieldValByIndex( |
| 28220 | 27980 | return switch (zcu.intern_pool.indexToKey(tuple_val.toIntern())) { |
| 28221 | 27981 | .undef => pt.undefRef(field_ty), |
| 28222 | 27982 | .aggregate => |aggregate| Air.internedToRef(switch (aggregate.storage) { |
| 28223 | .bytes => |bytes| try pt.intValue(Type.u8, bytes.at(field_index, &zcu.intern_pool)), | |
| 27983 | .bytes => |bytes| try pt.intValue(.u8, bytes.at(field_index, &zcu.intern_pool)), | |
| 28224 | 27984 | .elems => |elems| Value.fromInterned(elems[field_index]), |
| 28225 | 27985 | .repeated_elem => |elem| Value.fromInterned(elem), |
| 28226 | 27986 | }.toIntern()), |
| ... | ... | @@ -28253,7 +28013,7 @@ fn unionFieldPtr( |
| 28253 | 28013 | try union_ty.resolveFields(pt); |
| 28254 | 28014 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 28255 | 28015 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 28256 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 28016 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 28257 | 28017 | const ptr_field_ty = try pt.ptrTypeSema(.{ |
| 28258 | 28018 | .child = field_ty.toIntern(), |
| 28259 | 28019 | .flags = .{ |
| ... | ... | @@ -28295,8 +28055,8 @@ fn unionFieldPtr( |
| 28295 | 28055 | break :ct; |
| 28296 | 28056 | } |
| 28297 | 28057 | // Store to the union to initialize the tag. |
| 28298 | const field_tag = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28299 | const payload_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 28058 | const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28059 | const payload_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 28300 | 28060 | const new_union_val = try pt.unionValue(union_ty, field_tag, try pt.undefValue(payload_ty)); |
| 28301 | 28061 | try sema.storePtrVal(block, src, union_ptr_val, new_union_val, union_ty); |
| 28302 | 28062 | } else { |
| ... | ... | @@ -28306,7 +28066,7 @@ fn unionFieldPtr( |
| 28306 | 28066 | return sema.failWithUseOfUndef(block, src); |
| 28307 | 28067 | } |
| 28308 | 28068 | const un = ip.indexToKey(union_val.toIntern()).un; |
| 28309 | const field_tag = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28069 | const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28310 | 28070 | const tag_matches = un.tag == field_tag.toIntern(); |
| 28311 | 28071 | if (!tag_matches) { |
| 28312 | 28072 | const msg = msg: { |
| ... | ... | @@ -28332,11 +28092,11 @@ fn unionFieldPtr( |
| 28332 | 28092 | if (!initializing and union_obj.flagsUnordered(ip).layout == .auto and block.wantSafety() and |
| 28333 | 28093 | union_ty.unionTagTypeSafety(zcu) != null and union_obj.field_types.len > 1) |
| 28334 | 28094 | { |
| 28335 | const wanted_tag_val = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28095 | const wanted_tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28336 | 28096 | const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern()); |
| 28337 | 28097 | // TODO would it be better if get_union_tag supported pointers to unions? |
| 28338 | 28098 | const union_val = try block.addTyOp(.load, union_ty, union_ptr); |
| 28339 | const active_tag = try block.addTyOp(.get_union_tag, Type.fromInterned(union_obj.enum_tag_ty), union_val); | |
| 28099 | const active_tag = try block.addTyOp(.get_union_tag, .fromInterned(union_obj.enum_tag_ty), union_val); | |
| 28340 | 28100 | try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag); |
| 28341 | 28101 | } |
| 28342 | 28102 | if (field_ty.zigTypeTag(zcu) == .noreturn) { |
| ... | ... | @@ -28363,14 +28123,14 @@ fn unionFieldVal( |
| 28363 | 28123 | try union_ty.resolveFields(pt); |
| 28364 | 28124 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 28365 | 28125 | const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); |
| 28366 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 28126 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 28367 | 28127 | const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_ty).enumFieldIndex(field_name, zcu).?); |
| 28368 | 28128 | |
| 28369 | 28129 | if (try sema.resolveValue(union_byval)) |union_val| { |
| 28370 | 28130 | if (union_val.isUndef(zcu)) return pt.undefRef(field_ty); |
| 28371 | 28131 | |
| 28372 | 28132 | const un = ip.indexToKey(union_val.toIntern()).un; |
| 28373 | const field_tag = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28133 | const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28374 | 28134 | const tag_matches = un.tag == field_tag.toIntern(); |
| 28375 | 28135 | switch (union_obj.flagsUnordered(ip).layout) { |
| 28376 | 28136 | .auto => { |
| ... | ... | @@ -28408,9 +28168,9 @@ fn unionFieldVal( |
| 28408 | 28168 | if (union_obj.flagsUnordered(ip).layout == .auto and block.wantSafety() and |
| 28409 | 28169 | union_ty.unionTagTypeSafety(zcu) != null and union_obj.field_types.len > 1) |
| 28410 | 28170 | { |
| 28411 | const wanted_tag_val = try pt.enumValueFieldIndex(Type.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28171 | const wanted_tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index); | |
| 28412 | 28172 | const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern()); |
| 28413 | const active_tag = try block.addTyOp(.get_union_tag, Type.fromInterned(union_obj.enum_tag_ty), union_byval); | |
| 28173 | const active_tag = try block.addTyOp(.get_union_tag, .fromInterned(union_obj.enum_tag_ty), union_byval); | |
| 28414 | 28174 | try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag); |
| 28415 | 28175 | } |
| 28416 | 28176 | if (field_ty.zigTypeTag(zcu) == .noreturn) { |
| ... | ... | @@ -28540,7 +28300,7 @@ fn elemVal( |
| 28540 | 28300 | |
| 28541 | 28301 | // TODO in case of a vector of pointers, we need to detect whether the element |
| 28542 | 28302 | // index is a scalar or vector instead of unconditionally casting to usize. |
| 28543 | const elem_index = try sema.coerce(block, Type.usize, elem_index_uncasted, elem_index_src); | |
| 28303 | const elem_index = try sema.coerce(block, .usize, elem_index_uncasted, elem_index_src); | |
| 28544 | 28304 | |
| 28545 | 28305 | switch (indexable_ty.zigTypeTag(zcu)) { |
| 28546 | 28306 | .pointer => switch (indexable_ty.ptrSize(zcu)) { |
| ... | ... | @@ -28795,7 +28555,7 @@ fn elemValArray( |
| 28795 | 28555 | if (oob_safety and block.wantSafety()) { |
| 28796 | 28556 | // Runtime check is only needed if unable to comptime check. |
| 28797 | 28557 | if (maybe_index_val == null) { |
| 28798 | const len_inst = try pt.intRef(Type.usize, array_len); | |
| 28558 | const len_inst = try pt.intRef(.usize, array_len); | |
| 28799 | 28559 | const cmp_op: Air.Inst.Tag = if (array_sent != null) .cmp_lte else .cmp_lt; |
| 28800 | 28560 | try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); |
| 28801 | 28561 | } |
| ... | ... | @@ -28860,7 +28620,7 @@ fn elemPtrArray( |
| 28860 | 28620 | |
| 28861 | 28621 | // Runtime check is only needed if unable to comptime check. |
| 28862 | 28622 | if (oob_safety and block.wantSafety() and offset == null) { |
| 28863 | const len_inst = try pt.intRef(Type.usize, array_len); | |
| 28623 | const len_inst = try pt.intRef(.usize, array_len); | |
| 28864 | 28624 | const cmp_op: Air.Inst.Tag = if (array_sent) .cmp_lte else .cmp_lt; |
| 28865 | 28625 | try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); |
| 28866 | 28626 | } |
| ... | ... | @@ -28917,9 +28677,9 @@ fn elemValSlice( |
| 28917 | 28677 | |
| 28918 | 28678 | if (oob_safety and block.wantSafety()) { |
| 28919 | 28679 | const len_inst = if (maybe_slice_val) |slice_val| |
| 28920 | try pt.intRef(Type.usize, try slice_val.sliceLen(pt)) | |
| 28680 | try pt.intRef(.usize, try slice_val.sliceLen(pt)) | |
| 28921 | 28681 | else |
| 28922 | try block.addTyOp(.slice_len, Type.usize, slice); | |
| 28682 | try block.addTyOp(.slice_len, .usize, slice); | |
| 28923 | 28683 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| 28924 | 28684 | try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); |
| 28925 | 28685 | } |
| ... | ... | @@ -28976,8 +28736,8 @@ fn elemPtrSlice( |
| 28976 | 28736 | const len_inst = len: { |
| 28977 | 28737 | if (maybe_undef_slice_val) |slice_val| |
| 28978 | 28738 | if (!slice_val.isUndef(zcu)) |
| 28979 | break :len try pt.intRef(Type.usize, try slice_val.sliceLen(pt)); | |
| 28980 | break :len try block.addTyOp(.slice_len, Type.usize, slice); | |
| 28739 | break :len try pt.intRef(.usize, try slice_val.sliceLen(pt)); | |
| 28740 | break :len try block.addTyOp(.slice_len, .usize, slice); | |
| 28981 | 28741 | }; |
| 28982 | 28742 | const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt; |
| 28983 | 28743 | try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op); |
| ... | ... | @@ -29142,7 +28902,7 @@ fn coerceExtra( |
| 29142 | 28902 | if (!inst_ty.isSinglePointer(zcu)) break :single_item; |
| 29143 | 28903 | if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer; |
| 29144 | 28904 | const ptr_elem_ty = inst_ty.childType(zcu); |
| 29145 | const array_ty = Type.fromInterned(dest_info.child); | |
| 28905 | const array_ty: Type = .fromInterned(dest_info.child); | |
| 29146 | 28906 | if (array_ty.zigTypeTag(zcu) != .array) break :single_item; |
| 29147 | 28907 | const array_elem_ty = array_ty.childType(zcu); |
| 29148 | 28908 | if (array_ty.arrayLen(zcu) != 1) break :single_item; |
| ... | ... | @@ -29164,7 +28924,7 @@ fn coerceExtra( |
| 29164 | 28924 | const array_elem_type = array_ty.childType(zcu); |
| 29165 | 28925 | const dest_is_mut = !dest_info.flags.is_const; |
| 29166 | 28926 | |
| 29167 | const dst_elem_type = Type.fromInterned(dest_info.child); | |
| 28927 | const dst_elem_type: Type = .fromInterned(dest_info.child); | |
| 29168 | 28928 | const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val); |
| 29169 | 28929 | switch (elem_res) { |
| 29170 | 28930 | .ok => {}, |
| ... | ... | @@ -29225,7 +28985,7 @@ fn coerceExtra( |
| 29225 | 28985 | // could be null. |
| 29226 | 28986 | const src_elem_ty = inst_ty.childType(zcu); |
| 29227 | 28987 | const dest_is_mut = !dest_info.flags.is_const; |
| 29228 | const dst_elem_type = Type.fromInterned(dest_info.child); | |
| 28988 | const dst_elem_type: Type = .fromInterned(dest_info.child); | |
| 29229 | 28989 | switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val)) { |
| 29230 | 28990 | .ok => {}, |
| 29231 | 28991 | else => break :src_c_ptr, |
| ... | ... | @@ -29265,16 +29025,16 @@ fn coerceExtra( |
| 29265 | 29025 | .byte_offset = 0, |
| 29266 | 29026 | } })), |
| 29267 | 29027 | .comptime_int => { |
| 29268 | const addr = sema.coerceExtra(block, Type.usize, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) { | |
| 29028 | const addr = sema.coerceExtra(block, .usize, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) { | |
| 29269 | 29029 | error.NotCoercible => break :pointer, |
| 29270 | 29030 | else => |e| return e, |
| 29271 | 29031 | }; |
| 29272 | 29032 | return try sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src); |
| 29273 | 29033 | }, |
| 29274 | 29034 | .int => { |
| 29275 | const ptr_size_ty = switch (inst_ty.intInfo(zcu).signedness) { | |
| 29276 | .signed => Type.isize, | |
| 29277 | .unsigned => Type.usize, | |
| 29035 | const ptr_size_ty: Type = switch (inst_ty.intInfo(zcu).signedness) { | |
| 29036 | .signed => .isize, | |
| 29037 | .unsigned => .usize, | |
| 29278 | 29038 | }; |
| 29279 | 29039 | const addr = sema.coerceExtra(block, ptr_size_ty, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) { |
| 29280 | 29040 | error.NotCoercible => { |
| ... | ... | @@ -29291,8 +29051,8 @@ fn coerceExtra( |
| 29291 | 29051 | const inst_info = inst_ty.ptrInfo(zcu); |
| 29292 | 29052 | switch (try sema.coerceInMemoryAllowed( |
| 29293 | 29053 | block, |
| 29294 | Type.fromInterned(dest_info.child), | |
| 29295 | Type.fromInterned(inst_info.child), | |
| 29054 | .fromInterned(dest_info.child), | |
| 29055 | .fromInterned(inst_info.child), | |
| 29296 | 29056 | !dest_info.flags.is_const, |
| 29297 | 29057 | target, |
| 29298 | 29058 | dest_ty_src, |
| ... | ... | @@ -29305,7 +29065,7 @@ fn coerceExtra( |
| 29305 | 29065 | if (inst_info.flags.size == .slice) { |
| 29306 | 29066 | assert(dest_info.sentinel == .none); |
| 29307 | 29067 | if (inst_info.sentinel == .none or |
| 29308 | inst_info.sentinel != (try pt.intValue(Type.fromInterned(inst_info.child), 0)).toIntern()) | |
| 29068 | inst_info.sentinel != (try pt.intValue(.fromInterned(inst_info.child), 0)).toIntern()) | |
| 29309 | 29069 | break :p; |
| 29310 | 29070 | |
| 29311 | 29071 | const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty); |
| ... | ... | @@ -29364,8 +29124,8 @@ fn coerceExtra( |
| 29364 | 29124 | |
| 29365 | 29125 | switch (try sema.coerceInMemoryAllowed( |
| 29366 | 29126 | block, |
| 29367 | Type.fromInterned(dest_info.child), | |
| 29368 | Type.fromInterned(inst_info.child), | |
| 29127 | .fromInterned(dest_info.child), | |
| 29128 | .fromInterned(inst_info.child), | |
| 29369 | 29129 | !dest_info.flags.is_const, |
| 29370 | 29130 | target, |
| 29371 | 29131 | dest_ty_src, |
| ... | ... | @@ -29378,7 +29138,7 @@ fn coerceExtra( |
| 29378 | 29138 | |
| 29379 | 29139 | if (dest_info.sentinel == .none or inst_info.sentinel == .none or |
| 29380 | 29140 | Air.internedToRef(dest_info.sentinel) != |
| 29381 | try sema.coerceInMemory(Value.fromInterned(inst_info.sentinel), Type.fromInterned(dest_info.child))) | |
| 29141 | try sema.coerceInMemory(Value.fromInterned(inst_info.sentinel), .fromInterned(dest_info.child))) | |
| 29382 | 29142 | break :p; |
| 29383 | 29143 | |
| 29384 | 29144 | const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty); |
| ... | ... | @@ -30658,8 +30418,8 @@ fn coerceInMemoryAllowedPtrs( |
| 30658 | 30418 | } }; |
| 30659 | 30419 | } |
| 30660 | 30420 | |
| 30661 | const dest_child = Type.fromInterned(dest_info.child); | |
| 30662 | const src_child = Type.fromInterned(src_info.child); | |
| 30421 | const dest_child: Type = .fromInterned(dest_info.child); | |
| 30422 | const src_child: Type = .fromInterned(src_info.child); | |
| 30663 | 30423 | const child = try sema.coerceInMemoryAllowed( |
| 30664 | 30424 | block, |
| 30665 | 30425 | dest_child, |
| ... | ... | @@ -30731,7 +30491,7 @@ fn coerceInMemoryAllowedPtrs( |
| 30731 | 30491 | .none => Value.@"unreachable", |
| 30732 | 30492 | else => Value.fromInterned(dest_info.sentinel), |
| 30733 | 30493 | }, |
| 30734 | .ty = Type.fromInterned(dest_info.child), | |
| 30494 | .ty = .fromInterned(dest_info.child), | |
| 30735 | 30495 | } }; |
| 30736 | 30496 | } |
| 30737 | 30497 | |
| ... | ... | @@ -30794,8 +30554,8 @@ fn coerceVarArgParam( |
| 30794 | 30554 | const inst_bits = uncasted_ty.floatBits(target); |
| 30795 | 30555 | if (inst_bits >= double_bits) break :float inst; |
| 30796 | 30556 | switch (double_bits) { |
| 30797 | 32 => break :float try sema.coerce(block, Type.f32, inst, inst_src), | |
| 30798 | 64 => break :float try sema.coerce(block, Type.f64, inst, inst_src), | |
| 30557 | 32 => break :float try sema.coerce(block, .f32, inst, inst_src), | |
| 30558 | 64 => break :float try sema.coerce(block, .f64, inst, inst_src), | |
| 30799 | 30559 | else => unreachable, |
| 30800 | 30560 | } |
| 30801 | 30561 | }, |
| ... | ... | @@ -30807,22 +30567,22 @@ fn coerceVarArgParam( |
| 30807 | 30567 | .signed => .int, |
| 30808 | 30568 | .unsigned => .uint, |
| 30809 | 30569 | })) break :int try sema.coerce(block, switch (uncasted_info.signedness) { |
| 30810 | .signed => Type.c_int, | |
| 30811 | .unsigned => Type.c_uint, | |
| 30570 | .signed => .c_int, | |
| 30571 | .unsigned => .c_uint, | |
| 30812 | 30572 | }, inst, inst_src); |
| 30813 | 30573 | if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { |
| 30814 | 30574 | .signed => .long, |
| 30815 | 30575 | .unsigned => .ulong, |
| 30816 | 30576 | })) break :int try sema.coerce(block, switch (uncasted_info.signedness) { |
| 30817 | .signed => Type.c_long, | |
| 30818 | .unsigned => Type.c_ulong, | |
| 30577 | .signed => .c_long, | |
| 30578 | .unsigned => .c_ulong, | |
| 30819 | 30579 | }, inst, inst_src); |
| 30820 | 30580 | if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { |
| 30821 | 30581 | .signed => .longlong, |
| 30822 | 30582 | .unsigned => .ulonglong, |
| 30823 | 30583 | })) break :int try sema.coerce(block, switch (uncasted_info.signedness) { |
| 30824 | .signed => Type.c_longlong, | |
| 30825 | .unsigned => Type.c_ulonglong, | |
| 30584 | .signed => .c_longlong, | |
| 30585 | .unsigned => .c_ulonglong, | |
| 30826 | 30586 | }, inst, inst_src); |
| 30827 | 30587 | break :int inst; |
| 30828 | 30588 | } else inst, |
| ... | ... | @@ -30889,7 +30649,7 @@ fn storePtr2( |
| 30889 | 30649 | while (i < field_count) : (i += 1) { |
| 30890 | 30650 | const elem_src = operand_src; // TODO better source location |
| 30891 | 30651 | const elem = try sema.tupleField(block, operand_src, uncasted_operand, elem_src, i); |
| 30892 | const elem_index = try pt.intRef(Type.usize, i); | |
| 30652 | const elem_index = try pt.intRef(.usize, i); | |
| 30893 | 30653 | const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src, false, true); |
| 30894 | 30654 | try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store); |
| 30895 | 30655 | } |
| ... | ... | @@ -31216,7 +30976,7 @@ fn coerceArrayPtrToSlice( |
| 31216 | 30976 | const slice_val = try pt.intern(.{ .slice = .{ |
| 31217 | 30977 | .ty = dest_ty.toIntern(), |
| 31218 | 30978 | .ptr = slice_ptr.toIntern(), |
| 31219 | .len = (try pt.intValue(Type.usize, array_ty.arrayLen(zcu))).toIntern(), | |
| 30979 | .len = (try pt.intValue(.usize, array_ty.arrayLen(zcu))).toIntern(), | |
| 31220 | 30980 | } }); |
| 31221 | 30981 | return Air.internedToRef(slice_val); |
| 31222 | 30982 | } |
| ... | ... | @@ -31358,7 +31118,7 @@ fn coerceEnumToUnion( |
| 31358 | 31118 | }; |
| 31359 | 31119 | |
| 31360 | 31120 | const union_obj = zcu.typeToUnion(union_ty).?; |
| 31361 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 31121 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 31362 | 31122 | try field_ty.resolveFields(pt); |
| 31363 | 31123 | if (field_ty.zigTypeTag(zcu) == .noreturn) { |
| 31364 | 31124 | const msg = msg: { |
| ... | ... | @@ -31448,7 +31208,7 @@ fn coerceEnumToUnion( |
| 31448 | 31208 | |
| 31449 | 31209 | for (0..union_obj.field_types.len) |field_index| { |
| 31450 | 31210 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; |
| 31451 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 31211 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 31452 | 31212 | if (!(try field_ty.hasRuntimeBitsSema(pt))) continue; |
| 31453 | 31213 | try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{ |
| 31454 | 31214 | field_name.fmt(ip), |
| ... | ... | @@ -31536,7 +31296,7 @@ fn coerceArrayLike( |
| 31536 | 31296 | var runtime_src: ?LazySrcLoc = null; |
| 31537 | 31297 | |
| 31538 | 31298 | for (element_vals, element_refs, 0..) |*val, *ref, i| { |
| 31539 | const index_ref = Air.internedToRef((try pt.intValue(Type.usize, i)).toIntern()); | |
| 31299 | const index_ref = Air.internedToRef((try pt.intValue(.usize, i)).toIntern()); | |
| 31540 | 31300 | const src = inst_src; // TODO better source location |
| 31541 | 31301 | const elem_src = inst_src; // TODO better source location |
| 31542 | 31302 | const elem_ref = try sema.elemValArray(block, src, inst_src, inst, elem_src, index_ref, true); |
| ... | ... | @@ -31668,7 +31428,7 @@ fn coerceTupleToArrayPtrs( |
| 31668 | 31428 | const zcu = pt.zcu; |
| 31669 | 31429 | const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src); |
| 31670 | 31430 | const ptr_info = ptr_array_ty.ptrInfo(zcu); |
| 31671 | const array_ty = Type.fromInterned(ptr_info.child); | |
| 31431 | const array_ty: Type = .fromInterned(ptr_info.child); | |
| 31672 | 31432 | const array_inst = try sema.coerceTupleToArray(block, array_ty, array_ty_src, tuple, tuple_src); |
| 31673 | 31433 | if (ptr_info.flags.alignment != .none) { |
| 31674 | 31434 | return sema.fail(block, array_ty_src, "TODO: override the alignment of the array decl we create here", .{}); |
| ... | ... | @@ -31721,14 +31481,14 @@ fn coerceTupleToTuple( |
| 31721 | 31481 | const field_index: u32 = @intCast(field_index_usize); |
| 31722 | 31482 | |
| 31723 | 31483 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); |
| 31724 | const coerced = try sema.coerce(block, Type.fromInterned(field_ty), elem_ref, field_src); | |
| 31484 | const coerced = try sema.coerce(block, .fromInterned(field_ty), elem_ref, field_src); | |
| 31725 | 31485 | field_refs[field_index] = coerced; |
| 31726 | 31486 | if (default_val != .none) { |
| 31727 | 31487 | const init_val = (try sema.resolveValue(coerced)) orelse { |
| 31728 | 31488 | return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field }); |
| 31729 | 31489 | }; |
| 31730 | 31490 | |
| 31731 | if (!init_val.eql(Value.fromInterned(default_val), Type.fromInterned(field_ty), pt.zcu)) { | |
| 31491 | if (!init_val.eql(Value.fromInterned(default_val), .fromInterned(field_ty), pt.zcu)) { | |
| 31732 | 31492 | return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i); |
| 31733 | 31493 | } |
| 31734 | 31494 | } |
| ... | ... | @@ -31885,7 +31645,7 @@ pub fn ensureNavResolved(sema: *Sema, block: *Block, src: LazySrcLoc, nav_index: |
| 31885 | 31645 | |
| 31886 | 31646 | fn optRefValue(sema: *Sema, opt_val: ?Value) !Value { |
| 31887 | 31647 | const pt = sema.pt; |
| 31888 | const ptr_anyopaque_ty = try pt.singleConstPtrType(Type.anyopaque); | |
| 31648 | const ptr_anyopaque_ty = try pt.singleConstPtrType(.anyopaque); | |
| 31889 | 31649 | return Value.fromInterned(try pt.intern(.{ .opt = .{ |
| 31890 | 31650 | .ty = (try pt.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(), |
| 31891 | 31651 | .val = if (opt_val) |val| (try pt.getCoerced( |
| ... | ... | @@ -32140,12 +31900,12 @@ fn analyzeSliceLen( |
| 32140 | 31900 | const zcu = pt.zcu; |
| 32141 | 31901 | if (try sema.resolveValue(slice_inst)) |slice_val| { |
| 32142 | 31902 | if (slice_val.isUndef(zcu)) { |
| 32143 | return pt.undefRef(Type.usize); | |
| 31903 | return .undef_usize; | |
| 32144 | 31904 | } |
| 32145 | return pt.intRef(Type.usize, try slice_val.sliceLen(pt)); | |
| 31905 | return pt.intRef(.usize, try slice_val.sliceLen(pt)); | |
| 32146 | 31906 | } |
| 32147 | 31907 | try sema.requireRuntimeBlock(block, src, null); |
| 32148 | return block.addTyOp(.slice_len, Type.usize, slice_inst); | |
| 31908 | return block.addTyOp(.slice_len, .usize, slice_inst); | |
| 32149 | 31909 | } |
| 32150 | 31910 | |
| 32151 | 31911 | fn analyzeIsNull( |
| ... | ... | @@ -32156,7 +31916,7 @@ fn analyzeIsNull( |
| 32156 | 31916 | ) CompileError!Air.Inst.Ref { |
| 32157 | 31917 | const pt = sema.pt; |
| 32158 | 31918 | const zcu = pt.zcu; |
| 32159 | const result_ty = Type.bool; | |
| 31919 | const result_ty: Type = .bool; | |
| 32160 | 31920 | if (try sema.resolveValue(operand)) |opt_val| { |
| 32161 | 31921 | if (opt_val.isUndef(zcu)) { |
| 32162 | 31922 | return pt.undefRef(result_ty); |
| ... | ... | @@ -32224,7 +31984,7 @@ fn analyzeIsNonErrComptimeOnly( |
| 32224 | 31984 | else => {}, |
| 32225 | 31985 | } |
| 32226 | 31986 | } else if (operand == .undef) { |
| 32227 | return pt.undefRef(Type.bool); | |
| 31987 | return .undef_bool; | |
| 32228 | 31988 | } else if (@intFromEnum(operand) < InternPool.static_len) { |
| 32229 | 31989 | // None of the ref tags can be errors. |
| 32230 | 31990 | return .bool_true; |
| ... | ... | @@ -32308,14 +32068,7 @@ fn analyzeIsNonErrComptimeOnly( |
| 32308 | 32068 | } |
| 32309 | 32069 | |
| 32310 | 32070 | if (maybe_operand_val) |err_union| { |
| 32311 | if (err_union.isUndef(zcu)) { | |
| 32312 | return pt.undefRef(Type.bool); | |
| 32313 | } | |
| 32314 | if (err_union.getErrorName(zcu) == .none) { | |
| 32315 | return .bool_true; | |
| 32316 | } else { | |
| 32317 | return .bool_false; | |
| 32318 | } | |
| 32071 | return if (err_union.isUndef(zcu)) .undef_bool else if (err_union.getErrorName(zcu) == .none) .bool_true else .bool_false; | |
| 32319 | 32072 | } |
| 32320 | 32073 | return .none; |
| 32321 | 32074 | } |
| ... | ... | @@ -32412,8 +32165,8 @@ fn analyzeSlice( |
| 32412 | 32165 | ); |
| 32413 | 32166 | |
| 32414 | 32167 | const bounds_error_message = "slice of single-item pointer must have bounds [0..0], [0..1], or [1..1]"; |
| 32415 | if (try sema.compareScalar(start_value, .neq, end_value, Type.comptime_int)) { | |
| 32416 | if (try sema.compareScalar(start_value, .neq, Value.zero_comptime_int, Type.comptime_int)) { | |
| 32168 | if (try sema.compareScalar(start_value, .neq, end_value, .comptime_int)) { | |
| 32169 | if (try sema.compareScalar(start_value, .neq, Value.zero_comptime_int, .comptime_int)) { | |
| 32417 | 32170 | const msg = msg: { |
| 32418 | 32171 | const msg = try sema.errMsg(start_src, bounds_error_message, .{}); |
| 32419 | 32172 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -32429,7 +32182,7 @@ fn analyzeSlice( |
| 32429 | 32182 | break :msg msg; |
| 32430 | 32183 | }; |
| 32431 | 32184 | return sema.failWithOwnedErrorMsg(block, msg); |
| 32432 | } else if (try sema.compareScalar(end_value, .neq, Value.one_comptime_int, Type.comptime_int)) { | |
| 32185 | } else if (try sema.compareScalar(end_value, .neq, Value.one_comptime_int, .comptime_int)) { | |
| 32433 | 32186 | const msg = msg: { |
| 32434 | 32187 | const msg = try sema.errMsg(end_src, bounds_error_message, .{}); |
| 32435 | 32188 | errdefer msg.destroy(sema.gpa); |
| ... | ... | @@ -32447,7 +32200,7 @@ fn analyzeSlice( |
| 32447 | 32200 | return sema.failWithOwnedErrorMsg(block, msg); |
| 32448 | 32201 | } |
| 32449 | 32202 | } else { |
| 32450 | if (try sema.compareScalar(end_value, .gt, Value.one_comptime_int, Type.comptime_int)) { | |
| 32203 | if (try sema.compareScalar(end_value, .gt, Value.one_comptime_int, .comptime_int)) { | |
| 32451 | 32204 | return sema.fail( |
| 32452 | 32205 | block, |
| 32453 | 32206 | end_src, |
| ... | ... | @@ -32512,7 +32265,7 @@ fn analyzeSlice( |
| 32512 | 32265 | break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(manyptr_ty_key), ptr_or_slice, ptr_src); |
| 32513 | 32266 | } else ptr_or_slice; |
| 32514 | 32267 | |
| 32515 | const start = try sema.coerce(block, Type.usize, uncasted_start, start_src); | |
| 32268 | const start = try sema.coerce(block, .usize, uncasted_start, start_src); | |
| 32516 | 32269 | const new_ptr = try sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src); |
| 32517 | 32270 | const new_ptr_ty = sema.typeOf(new_ptr); |
| 32518 | 32271 | |
| ... | ... | @@ -32523,20 +32276,20 @@ fn analyzeSlice( |
| 32523 | 32276 | var end_is_len = uncasted_end_opt == .none; |
| 32524 | 32277 | const end = e: { |
| 32525 | 32278 | if (array_ty.zigTypeTag(zcu) == .array) { |
| 32526 | const len_val = try pt.intValue(Type.usize, array_ty.arrayLen(zcu)); | |
| 32279 | const len_val = try pt.intValue(.usize, array_ty.arrayLen(zcu)); | |
| 32527 | 32280 | |
| 32528 | 32281 | if (!end_is_len) { |
| 32529 | 32282 | const end = if (by_length) end: { |
| 32530 | const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); | |
| 32283 | const len = try sema.coerce(block, .usize, uncasted_end_opt, end_src); | |
| 32531 | 32284 | const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false); |
| 32532 | break :end try sema.coerce(block, Type.usize, uncasted_end, end_src); | |
| 32533 | } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); | |
| 32285 | break :end try sema.coerce(block, .usize, uncasted_end, end_src); | |
| 32286 | } else try sema.coerce(block, .usize, uncasted_end_opt, end_src); | |
| 32534 | 32287 | if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { |
| 32535 | 32288 | const len_s_val = try pt.intValue( |
| 32536 | Type.usize, | |
| 32289 | .usize, | |
| 32537 | 32290 | array_ty.arrayLenIncludingSentinel(zcu), |
| 32538 | 32291 | ); |
| 32539 | if (!(try sema.compareAll(end_val, .lte, len_s_val, Type.usize))) { | |
| 32292 | if (!(try sema.compareAll(end_val, .lte, len_s_val, .usize))) { | |
| 32540 | 32293 | const sentinel_label: []const u8 = if (array_ty.sentinel(zcu) != null) |
| 32541 | 32294 | " +1 (sentinel)" |
| 32542 | 32295 | else |
| ... | ... | @@ -32557,7 +32310,7 @@ fn analyzeSlice( |
| 32557 | 32310 | // end_is_len is only true if we are NOT using the sentinel |
| 32558 | 32311 | // length. For sentinel-length, we don't want the type to |
| 32559 | 32312 | // contain the sentinel. |
| 32560 | if (end_val.eql(len_val, Type.usize, zcu)) { | |
| 32313 | if (end_val.eql(len_val, .usize, zcu)) { | |
| 32561 | 32314 | end_is_len = true; |
| 32562 | 32315 | } |
| 32563 | 32316 | } |
| ... | ... | @@ -32568,10 +32321,10 @@ fn analyzeSlice( |
| 32568 | 32321 | } else if (slice_ty.isSlice(zcu)) { |
| 32569 | 32322 | if (!end_is_len) { |
| 32570 | 32323 | const end = if (by_length) end: { |
| 32571 | const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); | |
| 32324 | const len = try sema.coerce(block, .usize, uncasted_end_opt, end_src); | |
| 32572 | 32325 | const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false); |
| 32573 | break :end try sema.coerce(block, Type.usize, uncasted_end, end_src); | |
| 32574 | } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); | |
| 32326 | break :end try sema.coerce(block, .usize, uncasted_end, end_src); | |
| 32327 | } else try sema.coerce(block, .usize, uncasted_end_opt, end_src); | |
| 32575 | 32328 | if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { |
| 32576 | 32329 | if (try sema.resolveValue(ptr_or_slice)) |slice_val| { |
| 32577 | 32330 | if (slice_val.isUndef(zcu)) { |
| ... | ... | @@ -32580,8 +32333,8 @@ fn analyzeSlice( |
| 32580 | 32333 | const has_sentinel = slice_ty.sentinel(zcu) != null; |
| 32581 | 32334 | const slice_len = try slice_val.sliceLen(pt); |
| 32582 | 32335 | const len_plus_sent = slice_len + @intFromBool(has_sentinel); |
| 32583 | const slice_len_val_with_sentinel = try pt.intValue(Type.usize, len_plus_sent); | |
| 32584 | if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, Type.usize))) { | |
| 32336 | const slice_len_val_with_sentinel = try pt.intValue(.usize, len_plus_sent); | |
| 32337 | if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, .usize))) { | |
| 32585 | 32338 | const sentinel_label: []const u8 = if (has_sentinel) |
| 32586 | 32339 | " +1 (sentinel)" |
| 32587 | 32340 | else |
| ... | ... | @@ -32602,8 +32355,8 @@ fn analyzeSlice( |
| 32602 | 32355 | // If the slice has a sentinel, we consider end_is_len |
| 32603 | 32356 | // is only true if it equals the length WITHOUT the |
| 32604 | 32357 | // sentinel, so we don't add a sentinel type. |
| 32605 | const slice_len_val = try pt.intValue(Type.usize, slice_len); | |
| 32606 | if (end_val.eql(slice_len_val, Type.usize, zcu)) { | |
| 32358 | const slice_len_val = try pt.intValue(.usize, slice_len); | |
| 32359 | if (end_val.eql(slice_len_val, .usize, zcu)) { | |
| 32607 | 32360 | end_is_len = true; |
| 32608 | 32361 | } |
| 32609 | 32362 | } |
| ... | ... | @@ -32614,10 +32367,10 @@ fn analyzeSlice( |
| 32614 | 32367 | } |
| 32615 | 32368 | if (!end_is_len) { |
| 32616 | 32369 | if (by_length) { |
| 32617 | const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); | |
| 32370 | const len = try sema.coerce(block, .usize, uncasted_end_opt, end_src); | |
| 32618 | 32371 | const uncasted_end = try sema.analyzeArithmetic(block, .add, start, len, src, start_src, end_src, false); |
| 32619 | break :e try sema.coerce(block, Type.usize, uncasted_end, end_src); | |
| 32620 | } else break :e try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); | |
| 32372 | break :e try sema.coerce(block, .usize, uncasted_end, end_src); | |
| 32373 | } else break :e try sema.coerce(block, .usize, uncasted_end_opt, end_src); | |
| 32621 | 32374 | } |
| 32622 | 32375 | return sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src); |
| 32623 | 32376 | }; |
| ... | ... | @@ -32645,7 +32398,7 @@ fn analyzeSlice( |
| 32645 | 32398 | // requirement: start <= end |
| 32646 | 32399 | if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { |
| 32647 | 32400 | if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| { |
| 32648 | if (!by_length and !(try sema.compareAll(start_val, .lte, end_val, Type.usize))) { | |
| 32401 | if (!by_length and !(try sema.compareAll(start_val, .lte, end_val, .usize))) { | |
| 32649 | 32402 | return sema.fail( |
| 32650 | 32403 | block, |
| 32651 | 32404 | start_src, |
| ... | ... | @@ -32715,7 +32468,7 @@ fn analyzeSlice( |
| 32715 | 32468 | try sema.addSafetyCheckCall(block, src, ok, .@"panic.startGreaterThanEnd", &.{ start, end }); |
| 32716 | 32469 | } |
| 32717 | 32470 | const new_len = if (by_length) |
| 32718 | try sema.coerce(block, Type.usize, uncasted_end_opt, end_src) | |
| 32471 | try sema.coerce(block, .usize, uncasted_end_opt, end_src) | |
| 32719 | 32472 | else |
| 32720 | 32473 | try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src, false); |
| 32721 | 32474 | const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len); |
| ... | ... | @@ -32753,9 +32506,9 @@ fn analyzeSlice( |
| 32753 | 32506 | |
| 32754 | 32507 | bounds_check: { |
| 32755 | 32508 | const actual_len = if (array_ty.zigTypeTag(zcu) == .array) |
| 32756 | try pt.intRef(Type.usize, array_ty.arrayLenIncludingSentinel(zcu)) | |
| 32509 | try pt.intRef(.usize, array_ty.arrayLenIncludingSentinel(zcu)) | |
| 32757 | 32510 | else if (slice_ty.isSlice(zcu)) l: { |
| 32758 | const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); | |
| 32511 | const slice_len_inst = try block.addTyOp(.slice_len, .usize, ptr_or_slice); | |
| 32759 | 32512 | break :l if (slice_ty.sentinel(zcu) == null) |
| 32760 | 32513 | slice_len_inst |
| 32761 | 32514 | else |
| ... | ... | @@ -32811,15 +32564,15 @@ fn analyzeSlice( |
| 32811 | 32564 | |
| 32812 | 32565 | // requirement: end <= len |
| 32813 | 32566 | const opt_len_inst = if (array_ty.zigTypeTag(zcu) == .array) |
| 32814 | try pt.intRef(Type.usize, array_ty.arrayLenIncludingSentinel(zcu)) | |
| 32567 | try pt.intRef(.usize, array_ty.arrayLenIncludingSentinel(zcu)) | |
| 32815 | 32568 | else if (slice_ty.isSlice(zcu)) blk: { |
| 32816 | 32569 | if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { |
| 32817 | 32570 | // we don't need to add one for sentinels because the |
| 32818 | 32571 | // underlying value data includes the sentinel |
| 32819 | break :blk try pt.intRef(Type.usize, try slice_val.sliceLen(pt)); | |
| 32572 | break :blk try pt.intRef(.usize, try slice_val.sliceLen(pt)); | |
| 32820 | 32573 | } |
| 32821 | 32574 | |
| 32822 | const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); | |
| 32575 | const slice_len_inst = try block.addTyOp(.slice_len, .usize, ptr_or_slice); | |
| 32823 | 32576 | if (slice_ty.sentinel(zcu) == null) break :blk slice_len_inst; |
| 32824 | 32577 | |
| 32825 | 32578 | // we have to add one because slice lengths don't include the sentinel |
| ... | ... | @@ -32935,8 +32688,8 @@ fn cmpNumeric( |
| 32935 | 32688 | } |
| 32936 | 32689 | |
| 32937 | 32690 | // Any other comparison depends on both values, so the result is undef if either is undef. |
| 32938 | if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(Type.bool); | |
| 32939 | if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return pt.undefRef(Type.bool); | |
| 32691 | if (maybe_lhs_val) |v| if (v.isUndef(zcu)) return .undef_bool; | |
| 32692 | if (maybe_rhs_val) |v| if (v.isUndef(zcu)) return .undef_bool; | |
| 32940 | 32693 | |
| 32941 | 32694 | const runtime_src: LazySrcLoc = if (maybe_lhs_val) |lhs_val| rs: { |
| 32942 | 32695 | if (maybe_rhs_val) |rhs_val| { |
| ... | ... | @@ -33646,7 +33399,7 @@ fn resolvePeerTypes( |
| 33646 | 33399 | candidate_srcs: PeerTypeCandidateSrc, |
| 33647 | 33400 | ) !Type { |
| 33648 | 33401 | switch (instructions.len) { |
| 33649 | 0 => return Type.noreturn, | |
| 33402 | 0 => return .noreturn, | |
| 33650 | 33403 | 1 => return sema.typeOf(instructions[0]), |
| 33651 | 33404 | else => {}, |
| 33652 | 33405 | } |
| ... | ... | @@ -33780,12 +33533,12 @@ fn resolvePeerTypesInner( |
| 33780 | 33533 | .nullable => { |
| 33781 | 33534 | for (peer_tys, 0..) |opt_ty, i| { |
| 33782 | 33535 | const ty = opt_ty orelse continue; |
| 33783 | if (!ty.eql(Type.null, zcu)) return .{ .conflict = .{ | |
| 33536 | if (!ty.eql(.null, zcu)) return .{ .conflict = .{ | |
| 33784 | 33537 | .peer_idx_a = strat_reason, |
| 33785 | 33538 | .peer_idx_b = i, |
| 33786 | 33539 | } }; |
| 33787 | 33540 | } |
| 33788 | return .{ .success = Type.null }; | |
| 33541 | return .{ .success = .null }; | |
| 33789 | 33542 | }, |
| 33790 | 33543 | |
| 33791 | 33544 | .optional => { |
| ... | ... | @@ -34006,7 +33759,7 @@ fn resolvePeerTypesInner( |
| 34006 | 33759 | }; |
| 34007 | 33760 | |
| 34008 | 33761 | // Try peer -> cur, then cur -> peer |
| 34009 | ptr_info.child = ((try sema.resolvePairInMemoryCoercible(block, src, Type.fromInterned(ptr_info.child), Type.fromInterned(peer_info.child))) orelse { | |
| 33762 | ptr_info.child = ((try sema.resolvePairInMemoryCoercible(block, src, .fromInterned(ptr_info.child), .fromInterned(peer_info.child))) orelse { | |
| 34010 | 33763 | return .{ .conflict = .{ |
| 34011 | 33764 | .peer_idx_a = first_idx, |
| 34012 | 33765 | .peer_idx_b = i, |
| ... | ... | @@ -34153,8 +33906,8 @@ fn resolvePeerTypesInner( |
| 34153 | 33906 | }; |
| 34154 | 33907 | |
| 34155 | 33908 | // We abstract array handling slightly so that tuple pointers can work like array pointers |
| 34156 | const peer_pointee_array = sema.typeIsArrayLike(Type.fromInterned(peer_info.child)); | |
| 34157 | const cur_pointee_array = sema.typeIsArrayLike(Type.fromInterned(ptr_info.child)); | |
| 33909 | const peer_pointee_array = sema.typeIsArrayLike(.fromInterned(peer_info.child)); | |
| 33910 | const cur_pointee_array = sema.typeIsArrayLike(.fromInterned(ptr_info.child)); | |
| 34158 | 33911 | |
| 34159 | 33912 | // This switch is just responsible for deciding the size and pointee (not including |
| 34160 | 33913 | // single-pointer array sentinel). |
| ... | ... | @@ -34162,7 +33915,7 @@ fn resolvePeerTypesInner( |
| 34162 | 33915 | switch (peer_info.flags.size) { |
| 34163 | 33916 | .one => switch (ptr_info.flags.size) { |
| 34164 | 33917 | .one => { |
| 34165 | if (try sema.resolvePairInMemoryCoercible(block, src, Type.fromInterned(ptr_info.child), Type.fromInterned(peer_info.child))) |pointee| { | |
| 33918 | if (try sema.resolvePairInMemoryCoercible(block, src, .fromInterned(ptr_info.child), .fromInterned(peer_info.child))) |pointee| { | |
| 34166 | 33919 | ptr_info.child = pointee.toIntern(); |
| 34167 | 33920 | break :good; |
| 34168 | 33921 | } |
| ... | ... | @@ -34204,7 +33957,7 @@ fn resolvePeerTypesInner( |
| 34204 | 33957 | .many => { |
| 34205 | 33958 | // Only works for *[n]T + [*]T -> [*]T |
| 34206 | 33959 | const arr = peer_pointee_array orelse return generic_err; |
| 34207 | if (try sema.resolvePairInMemoryCoercible(block, src, Type.fromInterned(ptr_info.child), arr.elem_ty)) |pointee| { | |
| 33960 | if (try sema.resolvePairInMemoryCoercible(block, src, .fromInterned(ptr_info.child), arr.elem_ty)) |pointee| { | |
| 34208 | 33961 | ptr_info.child = pointee.toIntern(); |
| 34209 | 33962 | break :good; |
| 34210 | 33963 | } |
| ... | ... | @@ -34217,7 +33970,7 @@ fn resolvePeerTypesInner( |
| 34217 | 33970 | .slice => { |
| 34218 | 33971 | // Only works for *[n]T + []T -> []T |
| 34219 | 33972 | const arr = peer_pointee_array orelse return generic_err; |
| 34220 | if (try sema.resolvePairInMemoryCoercible(block, src, Type.fromInterned(ptr_info.child), arr.elem_ty)) |pointee| { | |
| 33973 | if (try sema.resolvePairInMemoryCoercible(block, src, .fromInterned(ptr_info.child), arr.elem_ty)) |pointee| { | |
| 34221 | 33974 | ptr_info.child = pointee.toIntern(); |
| 34222 | 33975 | break :good; |
| 34223 | 33976 | } |
| ... | ... | @@ -34233,7 +33986,7 @@ fn resolvePeerTypesInner( |
| 34233 | 33986 | .one => { |
| 34234 | 33987 | // Only works for [*]T + *[n]T -> [*]T |
| 34235 | 33988 | const arr = cur_pointee_array orelse return generic_err; |
| 34236 | if (try sema.resolvePairInMemoryCoercible(block, src, arr.elem_ty, Type.fromInterned(peer_info.child))) |pointee| { | |
| 33989 | if (try sema.resolvePairInMemoryCoercible(block, src, arr.elem_ty, .fromInterned(peer_info.child))) |pointee| { | |
| 34237 | 33990 | ptr_info.flags.size = .many; |
| 34238 | 33991 | ptr_info.child = pointee.toIntern(); |
| 34239 | 33992 | break :good; |
| ... | ... | @@ -34247,7 +34000,7 @@ fn resolvePeerTypesInner( |
| 34247 | 34000 | return generic_err; |
| 34248 | 34001 | }, |
| 34249 | 34002 | .many => { |
| 34250 | if (try sema.resolvePairInMemoryCoercible(block, src, Type.fromInterned(ptr_info.child), Type.fromInterned(peer_info.child))) |pointee| { | |
| 34003 | if (try sema.resolvePairInMemoryCoercible(block, src, .fromInterned(ptr_info.child), .fromInterned(peer_info.child))) |pointee| { | |
| 34251 | 34004 | ptr_info.child = pointee.toIntern(); |
| 34252 | 34005 | break :good; |
| 34253 | 34006 | } |
| ... | ... | @@ -34262,7 +34015,7 @@ fn resolvePeerTypesInner( |
| 34262 | 34015 | } }; |
| 34263 | 34016 | } |
| 34264 | 34017 | // Okay, then works for [*]T + "[]T" -> [*]T |
| 34265 | if (try sema.resolvePairInMemoryCoercible(block, src, Type.fromInterned(ptr_info.child), Type.fromInterned(peer_info.child))) |pointee| { | |
| 34018 | if (try sema.resolvePairInMemoryCoercible(block, src, .fromInterned(ptr_info.child), .fromInterned(peer_info.child))) |pointee| { | |
| 34266 | 34019 | ptr_info.flags.size = .many; |
| 34267 | 34020 | ptr_info.child = pointee.toIntern(); |
| 34268 | 34021 | break :good; |
| ... | ... | @@ -34275,7 +34028,7 @@ fn resolvePeerTypesInner( |
| 34275 | 34028 | .one => { |
| 34276 | 34029 | // Only works for []T + *[n]T -> []T |
| 34277 | 34030 | const arr = cur_pointee_array orelse return generic_err; |
| 34278 | if (try sema.resolvePairInMemoryCoercible(block, src, arr.elem_ty, Type.fromInterned(peer_info.child))) |pointee| { | |
| 34031 | if (try sema.resolvePairInMemoryCoercible(block, src, arr.elem_ty, .fromInterned(peer_info.child))) |pointee| { | |
| 34279 | 34032 | ptr_info.flags.size = .slice; |
| 34280 | 34033 | ptr_info.child = pointee.toIntern(); |
| 34281 | 34034 | break :good; |
| ... | ... | @@ -34293,7 +34046,7 @@ fn resolvePeerTypesInner( |
| 34293 | 34046 | return generic_err; |
| 34294 | 34047 | }, |
| 34295 | 34048 | .slice => { |
| 34296 | if (try sema.resolvePairInMemoryCoercible(block, src, Type.fromInterned(ptr_info.child), Type.fromInterned(peer_info.child))) |pointee| { | |
| 34049 | if (try sema.resolvePairInMemoryCoercible(block, src, .fromInterned(ptr_info.child), .fromInterned(peer_info.child))) |pointee| { | |
| 34297 | 34050 | ptr_info.child = pointee.toIntern(); |
| 34298 | 34051 | break :good; |
| 34299 | 34052 | } |
| ... | ... | @@ -34479,7 +34232,7 @@ fn resolvePeerTypesInner( |
| 34479 | 34232 | } }, |
| 34480 | 34233 | } |
| 34481 | 34234 | } |
| 34482 | return .{ .success = Type.comptime_int }; | |
| 34235 | return .{ .success = .comptime_int }; | |
| 34483 | 34236 | }, |
| 34484 | 34237 | |
| 34485 | 34238 | .comptime_float => { |
| ... | ... | @@ -34493,7 +34246,7 @@ fn resolvePeerTypesInner( |
| 34493 | 34246 | } }, |
| 34494 | 34247 | } |
| 34495 | 34248 | } |
| 34496 | return .{ .success = Type.comptime_float }; | |
| 34249 | return .{ .success = .comptime_float }; | |
| 34497 | 34250 | }, |
| 34498 | 34251 | |
| 34499 | 34252 | .fixed_int => { |
| ... | ... | @@ -34601,11 +34354,11 @@ fn resolvePeerTypesInner( |
| 34601 | 34354 | // Recreate the type so we eliminate any c_longdouble |
| 34602 | 34355 | const bits = @max(cur_ty.floatBits(target), ty.floatBits(target)); |
| 34603 | 34356 | opt_cur_ty = switch (bits) { |
| 34604 | 16 => Type.f16, | |
| 34605 | 32 => Type.f32, | |
| 34606 | 64 => Type.f64, | |
| 34607 | 80 => Type.f80, | |
| 34608 | 128 => Type.f128, | |
| 34357 | 16 => .f16, | |
| 34358 | 32 => .f32, | |
| 34359 | 64 => .f64, | |
| 34360 | 80 => .f80, | |
| 34361 | 128 => .f128, | |
| 34609 | 34362 | else => unreachable, |
| 34610 | 34363 | }; |
| 34611 | 34364 | } else { |
| ... | ... | @@ -34716,7 +34469,7 @@ fn resolvePeerTypesInner( |
| 34716 | 34469 | break; |
| 34717 | 34470 | }; |
| 34718 | 34471 | const uncoerced_field = Air.internedToRef(uncoerced_field_val.toIntern()); |
| 34719 | const coerced_inst = sema.coerceExtra(block, Type.fromInterned(field_ty.*), uncoerced_field, src, .{ .report_err = false }) catch |err| switch (err) { | |
| 34472 | const coerced_inst = sema.coerceExtra(block, .fromInterned(field_ty.*), uncoerced_field, src, .{ .report_err = false }) catch |err| switch (err) { | |
| 34720 | 34473 | // It's possible for PTR to give false positives. Just give up on making this a comptime field, we'll get an error later anyway |
| 34721 | 34474 | error.NotCoercible => { |
| 34722 | 34475 | comptime_val = null; |
| ... | ... | @@ -34729,7 +34482,7 @@ fn resolvePeerTypesInner( |
| 34729 | 34482 | comptime_val = coerced_val; |
| 34730 | 34483 | continue; |
| 34731 | 34484 | }; |
| 34732 | if (!coerced_val.eql(existing, Type.fromInterned(field_ty.*), zcu)) { | |
| 34485 | if (!coerced_val.eql(existing, .fromInterned(field_ty.*), zcu)) { | |
| 34733 | 34486 | comptime_val = null; |
| 34734 | 34487 | break; |
| 34735 | 34488 | } |
| ... | ... | @@ -34743,7 +34496,7 @@ fn resolvePeerTypesInner( |
| 34743 | 34496 | .values = field_vals, |
| 34744 | 34497 | }); |
| 34745 | 34498 | |
| 34746 | return .{ .success = Type.fromInterned(final_ty) }; | |
| 34499 | return .{ .success = .fromInterned(final_ty) }; | |
| 34747 | 34500 | }, |
| 34748 | 34501 | |
| 34749 | 34502 | .exact => { |
| ... | ... | @@ -34813,7 +34566,7 @@ fn typeIsArrayLike(sema: *Sema, ty: Type) ?ArrayLike { |
| 34813 | 34566 | const field_count = ty.structFieldCount(zcu); |
| 34814 | 34567 | if (field_count == 0) return .{ |
| 34815 | 34568 | .len = 0, |
| 34816 | .elem_ty = Type.noreturn, | |
| 34569 | .elem_ty = .noreturn, | |
| 34817 | 34570 | }; |
| 34818 | 34571 | if (!ty.isTuple(zcu)) return null; |
| 34819 | 34572 | const elem_ty = ty.fieldType(0, zcu); |
| ... | ... | @@ -34902,7 +34655,7 @@ pub fn resolveStructAlignment( |
| 34902 | 34655 | var alignment: Alignment = .@"1"; |
| 34903 | 34656 | |
| 34904 | 34657 | for (0..struct_type.field_types.len) |i| { |
| 34905 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34658 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34906 | 34659 | if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) |
| 34907 | 34660 | continue; |
| 34908 | 34661 | const field_align = try field_ty.structFieldAlignmentSema( |
| ... | ... | @@ -34953,7 +34706,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { |
| 34953 | 34706 | var big_align: Alignment = .@"1"; |
| 34954 | 34707 | |
| 34955 | 34708 | for (aligns, sizes, 0..) |*field_align, *field_size, i| { |
| 34956 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34709 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34957 | 34710 | if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) { |
| 34958 | 34711 | struct_type.offsets.get(ip)[i] = 0; |
| 34959 | 34712 | field_size.* = 0; |
| ... | ... | @@ -35001,7 +34754,7 @@ pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void { |
| 35001 | 34754 | const runtime_order = struct_type.runtime_order.get(ip); |
| 35002 | 34755 | |
| 35003 | 34756 | for (runtime_order, 0..) |*ro, i| { |
| 35004 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34757 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 35005 | 34758 | if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) { |
| 35006 | 34759 | ro.* = .omitted; |
| 35007 | 34760 | } else { |
| ... | ... | @@ -35095,7 +34848,7 @@ fn backingIntType( |
| 35095 | 34848 | const fields_bit_sum = blk: { |
| 35096 | 34849 | var accumulator: u64 = 0; |
| 35097 | 34850 | for (0..struct_type.field_types.len) |i| { |
| 35098 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 34851 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 35099 | 34852 | accumulator += try field_ty.bitSizeSema(pt); |
| 35100 | 34853 | } |
| 35101 | 34854 | break :blk accumulator; |
| ... | ... | @@ -35234,7 +34987,7 @@ pub fn resolveUnionAlignment( |
| 35234 | 34987 | |
| 35235 | 34988 | var max_align: Alignment = .@"1"; |
| 35236 | 34989 | for (0..union_type.field_types.len) |field_index| { |
| 35237 | const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]); | |
| 34990 | const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]); | |
| 35238 | 34991 | if (!(try field_ty.hasRuntimeBitsSema(pt))) continue; |
| 35239 | 34992 | |
| 35240 | 34993 | const explicit_align = union_type.fieldAlign(ip, field_index); |
| ... | ... | @@ -35282,7 +35035,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { |
| 35282 | 35035 | var max_size: u64 = 0; |
| 35283 | 35036 | var max_align: Alignment = .@"1"; |
| 35284 | 35037 | for (0..union_type.field_types.len) |field_index| { |
| 35285 | const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]); | |
| 35038 | const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]); | |
| 35286 | 35039 | |
| 35287 | 35040 | if (try field_ty.comptimeOnlySema(pt) or field_ty.zigTypeTag(pt.zcu) == .noreturn) continue; // TODO: should this affect alignment? |
| 35288 | 35041 | |
| ... | ... | @@ -35307,7 +35060,7 @@ pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void { |
| 35307 | 35060 | const has_runtime_tag = union_type.flagsUnordered(ip).runtime_tag.hasTag() and |
| 35308 | 35061 | try Type.fromInterned(union_type.enum_tag_ty).hasRuntimeBitsSema(pt); |
| 35309 | 35062 | const size, const alignment, const padding = if (has_runtime_tag) layout: { |
| 35310 | const enum_tag_type = Type.fromInterned(union_type.enum_tag_ty); | |
| 35063 | const enum_tag_type: Type = .fromInterned(union_type.enum_tag_ty); | |
| 35311 | 35064 | const tag_align = try enum_tag_type.abiAlignmentSema(pt); |
| 35312 | 35065 | const tag_size = try enum_tag_type.abiSizeSema(pt); |
| 35313 | 35066 | |
| ... | ... | @@ -35392,7 +35145,7 @@ pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void { |
| 35392 | 35145 | // See also similar code for unions. |
| 35393 | 35146 | |
| 35394 | 35147 | for (0..struct_type.field_types.len) |i| { |
| 35395 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 35148 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 35396 | 35149 | try field_ty.resolveFully(pt); |
| 35397 | 35150 | } |
| 35398 | 35151 | } |
| ... | ... | @@ -35421,7 +35174,7 @@ pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void { |
| 35421 | 35174 | |
| 35422 | 35175 | union_obj.setStatus(ip, .fully_resolved_wip); |
| 35423 | 35176 | for (0..union_obj.field_types.len) |field_index| { |
| 35424 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 35177 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 35425 | 35178 | try field_ty.resolveFully(pt); |
| 35426 | 35179 | } |
| 35427 | 35180 | union_obj.setStatus(ip, .fully_resolved); |
| ... | ... | @@ -35553,7 +35306,7 @@ fn resolveInferredErrorSet( |
| 35553 | 35306 | // set. However, in the case of comptime/inline function calls with |
| 35554 | 35307 | // inferred error sets, each call gets an adhoc InferredErrorSet object, which |
| 35555 | 35308 | // has no corresponding function body. |
| 35556 | const ies_func_info = zcu.typeToFunc(Type.fromInterned(func.ty)).?; | |
| 35309 | const ies_func_info = zcu.typeToFunc(.fromInterned(func.ty)).?; | |
| 35557 | 35310 | // if ies declared by a inline function with generic return type, the return_type should be generic_poison, |
| 35558 | 35311 | // because inline function does not create a new declaration, and the ies has been filled with analyzeCall, |
| 35559 | 35312 | // so here we can simply skip this case. |
| ... | ... | @@ -36008,7 +35761,7 @@ fn structFieldInits( |
| 36008 | 35761 | // In init bodies, the zir index of the struct itself is used |
| 36009 | 35762 | // to refer to the current field type. |
| 36010 | 35763 | |
| 36011 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_i]); | |
| 35764 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_i]); | |
| 36012 | 35765 | const type_ref = Air.internedToRef(field_ty.toIntern()); |
| 36013 | 35766 | try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index}); |
| 36014 | 35767 | sema.inst_map.putAssumeCapacity(zir_index, type_ref); |
| ... | ... | @@ -36135,7 +35888,7 @@ fn unionFields( |
| 36135 | 35888 | } |
| 36136 | 35889 | |
| 36137 | 35890 | if (fields_len > 0) { |
| 36138 | const field_count_val = try pt.intValue(Type.comptime_int, fields_len - 1); | |
| 35891 | const field_count_val = try pt.intValue(.comptime_int, fields_len - 1); | |
| 36139 | 35892 | if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) { |
| 36140 | 35893 | const msg = msg: { |
| 36141 | 35894 | const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{}); |
| ... | ... | @@ -36288,9 +36041,9 @@ fn unionFields( |
| 36288 | 36041 | } |
| 36289 | 36042 | |
| 36290 | 36043 | const field_ty: Type = if (!has_type) |
| 36291 | Type.void | |
| 36044 | .void | |
| 36292 | 36045 | else if (field_type_ref == .none) |
| 36293 | Type.noreturn | |
| 36046 | .noreturn | |
| 36294 | 36047 | else |
| 36295 | 36048 | try sema.resolveType(&block_scope, type_src, field_type_ref); |
| 36296 | 36049 | |
| ... | ... | @@ -36388,11 +36141,11 @@ fn unionFields( |
| 36388 | 36141 | |
| 36389 | 36142 | for (tag_info.names.get(ip), 0..) |field_name, field_index| { |
| 36390 | 36143 | if (explicit_tags_seen[field_index]) continue; |
| 36391 | try sema.addFieldErrNote(Type.fromInterned(tag_ty), field_index, msg, "field '{}' missing, declared here", .{ | |
| 36144 | try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{}' missing, declared here", .{ | |
| 36392 | 36145 | field_name.fmt(ip), |
| 36393 | 36146 | }); |
| 36394 | 36147 | } |
| 36395 | try sema.addDeclaredHereNote(msg, Type.fromInterned(tag_ty)); | |
| 36148 | try sema.addDeclaredHereNote(msg, .fromInterned(tag_ty)); | |
| 36396 | 36149 | break :msg msg; |
| 36397 | 36150 | }; |
| 36398 | 36151 | return sema.failWithOwnedErrorMsg(&block_scope, msg); |
| ... | ... | @@ -36530,10 +36283,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36530 | 36283 | .comptime_int_type, |
| 36531 | 36284 | .comptime_float_type, |
| 36532 | 36285 | .enum_literal_type, |
| 36286 | .ptr_usize_type, | |
| 36287 | .ptr_const_comptime_int_type, | |
| 36533 | 36288 | .manyptr_u8_type, |
| 36534 | 36289 | .manyptr_const_u8_type, |
| 36535 | 36290 | .manyptr_const_u8_sentinel_0_type, |
| 36536 | .single_const_pointer_to_comptime_int_type, | |
| 36537 | 36291 | .slice_const_u8_type, |
| 36538 | 36292 | .slice_const_u8_sentinel_0_type, |
| 36539 | 36293 | .vector_8_i8_type, |
| ... | ... | @@ -36595,11 +36349,16 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36595 | 36349 | .empty_tuple_type => Value.empty_tuple, |
| 36596 | 36350 | // values, not types |
| 36597 | 36351 | .undef, |
| 36352 | .undef_bool, | |
| 36353 | .undef_usize, | |
| 36354 | .undef_u1, | |
| 36598 | 36355 | .zero, |
| 36599 | 36356 | .zero_usize, |
| 36357 | .zero_u1, | |
| 36600 | 36358 | .zero_u8, |
| 36601 | 36359 | .one, |
| 36602 | 36360 | .one_usize, |
| 36361 | .one_u1, | |
| 36603 | 36362 | .one_u8, |
| 36604 | 36363 | .four_u8, |
| 36605 | 36364 | .negative_one, |
| ... | ... | @@ -36705,7 +36464,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36705 | 36464 | .storage = .{ .elems = &.{} }, |
| 36706 | 36465 | } })); |
| 36707 | 36466 | |
| 36708 | if (try sema.typeHasOnePossibleValue(Type.fromInterned(seq_type.child))) |opv| { | |
| 36467 | if (try sema.typeHasOnePossibleValue(.fromInterned(seq_type.child))) |opv| { | |
| 36709 | 36468 | return Value.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 36710 | 36469 | .ty = ty.toIntern(), |
| 36711 | 36470 | .storage = .{ .repeated_elem = opv.toIntern() }, |
| ... | ... | @@ -36740,7 +36499,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36740 | 36499 | field_val.* = struct_type.field_inits.get(ip)[i]; |
| 36741 | 36500 | continue; |
| 36742 | 36501 | } |
| 36743 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); | |
| 36502 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]); | |
| 36744 | 36503 | if (try sema.typeHasOnePossibleValue(field_ty)) |field_opv| { |
| 36745 | 36504 | field_val.* = field_opv.toIntern(); |
| 36746 | 36505 | } else return null; |
| ... | ... | @@ -36773,13 +36532,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36773 | 36532 | try ty.resolveLayout(pt); |
| 36774 | 36533 | |
| 36775 | 36534 | const union_obj = ip.loadUnionType(ty.toIntern()); |
| 36776 | const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.tagTypeUnordered(ip)))) orelse | |
| 36535 | const tag_val = (try sema.typeHasOnePossibleValue(.fromInterned(union_obj.tagTypeUnordered(ip)))) orelse | |
| 36777 | 36536 | return null; |
| 36778 | 36537 | if (union_obj.field_types.len == 0) { |
| 36779 | 36538 | const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() }); |
| 36780 | 36539 | return Value.fromInterned(only); |
| 36781 | 36540 | } |
| 36782 | const only_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]); | |
| 36541 | const only_field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[0]); | |
| 36783 | 36542 | const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse |
| 36784 | 36543 | return null; |
| 36785 | 36544 | const only = try pt.internUnion(.{ |
| ... | ... | @@ -36796,7 +36555,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36796 | 36555 | .nonexhaustive => { |
| 36797 | 36556 | if (enum_type.tag_ty == .comptime_int_type) return null; |
| 36798 | 36557 | |
| 36799 | if (try sema.typeHasOnePossibleValue(Type.fromInterned(enum_type.tag_ty))) |int_opv| { | |
| 36558 | if (try sema.typeHasOnePossibleValue(.fromInterned(enum_type.tag_ty))) |int_opv| { | |
| 36800 | 36559 | const only = try pt.intern(.{ .enum_tag = .{ |
| 36801 | 36560 | .ty = ty.toIntern(), |
| 36802 | 36561 | .int = int_opv.toIntern(), |
| ... | ... | @@ -36814,7 +36573,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36814 | 36573 | 1 => try pt.intern(.{ .enum_tag = .{ |
| 36815 | 36574 | .ty = ty.toIntern(), |
| 36816 | 36575 | .int = if (enum_type.values.len == 0) |
| 36817 | (try pt.intValue(Type.fromInterned(enum_type.tag_ty), 0)).toIntern() | |
| 36576 | (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern() | |
| 36818 | 36577 | else |
| 36819 | 36578 | try ip.getCoercedInts( |
| 36820 | 36579 | zcu.gpa, |
| ... | ... | @@ -37041,7 +36800,7 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type { |
| 37041 | 36800 | if (ptr_type.flags.is_allowzero) return null; |
| 37042 | 36801 | |
| 37043 | 36802 | // optionals of zero sized types behave like bools, not pointers |
| 37044 | const payload_ty = Type.fromInterned(opt_child); | |
| 36803 | const payload_ty: Type = .fromInterned(opt_child); | |
| 37045 | 36804 | if ((try sema.typeHasOnePossibleValue(payload_ty)) != null) { |
| 37046 | 36805 | return null; |
| 37047 | 36806 | } |
| ... | ... | @@ -37175,7 +36934,7 @@ fn intFromFloatScalar( |
| 37175 | 36934 | var big_int = try float128IntPartToBigInt(sema.arena, float); |
| 37176 | 36935 | defer big_int.deinit(); |
| 37177 | 36936 | |
| 37178 | const cti_result = try pt.intValue_big(Type.comptime_int, big_int.toConst()); | |
| 36937 | const cti_result = try pt.intValue_big(.comptime_int, big_int.toConst()); | |
| 37179 | 36938 | |
| 37180 | 36939 | if (!(try sema.intFitsInType(cti_result, int_ty, null))) { |
| 37181 | 36940 | return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{ |
| ... | ... | @@ -37278,8 +37037,8 @@ fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool { |
| 37278 | 37037 | assert(enum_type.tag_mode != .nonexhaustive); |
| 37279 | 37038 | // The `tagValueIndex` function call below relies on the type being the integer tag type. |
| 37280 | 37039 | // `getCoerced` assumes the value will fit the new type. |
| 37281 | if (!(try sema.intFitsInType(int, Type.fromInterned(enum_type.tag_ty), null))) return false; | |
| 37282 | const int_coerced = try pt.getCoerced(int, Type.fromInterned(enum_type.tag_ty)); | |
| 37040 | if (!(try sema.intFitsInType(int, .fromInterned(enum_type.tag_ty), null))) return false; | |
| 37041 | const int_coerced = try pt.getCoerced(int, .fromInterned(enum_type.tag_ty)); | |
| 37283 | 37042 | |
| 37284 | 37043 | return enum_type.tagValueIndex(&zcu.intern_pool, int_coerced.toIntern()) != null; |
| 37285 | 37044 | } |
| ... | ... | @@ -37359,7 +37118,7 @@ fn compareVector( |
| 37359 | 37118 | const lhs_elem = try lhs.elemValue(pt, i); |
| 37360 | 37119 | const rhs_elem = try rhs.elemValue(pt, i); |
| 37361 | 37120 | if (lhs_elem.isUndef(zcu) or rhs_elem.isUndef(zcu)) { |
| 37362 | scalar.* = try pt.intern(.{ .undef = .bool_type }); | |
| 37121 | scalar.* = .undef_bool; | |
| 37363 | 37122 | } else { |
| 37364 | 37123 | const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(zcu)); |
| 37365 | 37124 | scalar.* = Value.makeBool(res_bool).toIntern(); |
| ... | ... | @@ -37826,7 +37585,7 @@ pub fn resolveDeclaredEnum( |
| 37826 | 37585 | .owner = .wrap(.{ .type = wip_ty.index }), |
| 37827 | 37586 | .func_index = .none, |
| 37828 | 37587 | .func_is_naked = false, |
| 37829 | .fn_ret_ty = Type.void, | |
| 37588 | .fn_ret_ty = .void, | |
| 37830 | 37589 | .fn_ret_ty_ies = null, |
| 37831 | 37590 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 37832 | 37591 | }; |
| ... | ... | @@ -37999,7 +37758,7 @@ fn resolveDeclaredEnumInner( |
| 37999 | 37758 | break :overflow false; |
| 38000 | 37759 | } else overflow: { |
| 38001 | 37760 | assert(wip_ty.nextField(ip, field_name, .none) == null); |
| 38002 | last_tag_val = try pt.intValue(Type.comptime_int, field_i); | |
| 37761 | last_tag_val = try pt.intValue(.comptime_int, field_i); | |
| 38003 | 37762 | if (!try sema.intFitsInType(last_tag_val.?, int_tag_ty, null)) break :overflow true; |
| 38004 | 37763 | last_tag_val = try pt.getCoerced(last_tag_val.?, int_tag_ty); |
| 38005 | 37764 | break :overflow false; |
| ... | ... | @@ -38222,8 +37981,7 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ |
| 38222 | 37981 | .@"panic.castToNull", |
| 38223 | 37982 | .@"panic.incorrectAlignment", |
| 38224 | 37983 | .@"panic.invalidErrorCode", |
| 38225 | .@"panic.castTruncatedData", | |
| 38226 | .@"panic.negativeToUnsigned", | |
| 37984 | .@"panic.integerOutOfBounds", | |
| 38227 | 37985 | .@"panic.integerOverflow", |
| 38228 | 37986 | .@"panic.shlOverflow", |
| 38229 | 37987 | .@"panic.shrOverflow", |
src/Sema/arith.zig+6-6| ... | ... | @@ -168,7 +168,7 @@ fn addWithOverflowScalar( |
| 168 | 168 | else => unreachable, |
| 169 | 169 | } |
| 170 | 170 | if (lhs.isUndef(zcu) or rhs.isUndef(zcu)) return .{ |
| 171 | .overflow_bit = try pt.undefValue(.u1), | |
| 171 | .overflow_bit = .undef_u1, | |
| 172 | 172 | .wrapped_result = try pt.undefValue(ty), |
| 173 | 173 | }; |
| 174 | 174 | return intAddWithOverflow(sema, lhs, rhs, ty); |
| ... | ... | @@ -229,7 +229,7 @@ fn subWithOverflowScalar( |
| 229 | 229 | else => unreachable, |
| 230 | 230 | } |
| 231 | 231 | if (lhs.isUndef(zcu) or rhs.isUndef(zcu)) return .{ |
| 232 | .overflow_bit = try pt.undefValue(.u1), | |
| 232 | .overflow_bit = .undef_u1, | |
| 233 | 233 | .wrapped_result = try pt.undefValue(ty), |
| 234 | 234 | }; |
| 235 | 235 | return intSubWithOverflow(sema, lhs, rhs, ty); |
| ... | ... | @@ -290,7 +290,7 @@ fn mulWithOverflowScalar( |
| 290 | 290 | else => unreachable, |
| 291 | 291 | } |
| 292 | 292 | if (lhs.isUndef(zcu) or rhs.isUndef(zcu)) return .{ |
| 293 | .overflow_bit = try pt.undefValue(.u1), | |
| 293 | .overflow_bit = .undef_u1, | |
| 294 | 294 | .wrapped_result = try pt.undefValue(ty), |
| 295 | 295 | }; |
| 296 | 296 | return intMulWithOverflow(sema, lhs, rhs, ty); |
| ... | ... | @@ -1043,7 +1043,7 @@ fn comptimeIntAdd(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 1043 | 1043 | fn intAddWithOverflow(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResult { |
| 1044 | 1044 | switch (ty.toIntern()) { |
| 1045 | 1045 | .comptime_int_type => return .{ |
| 1046 | .overflow_bit = try sema.pt.intValue(.u1, 0), | |
| 1046 | .overflow_bit = .zero_u1, | |
| 1047 | 1047 | .wrapped_result = try comptimeIntAdd(sema, lhs, rhs), |
| 1048 | 1048 | }, |
| 1049 | 1049 | else => return intAddWithOverflowInner(sema, lhs, rhs, ty), |
| ... | ... | @@ -1125,7 +1125,7 @@ fn comptimeIntSub(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 1125 | 1125 | fn intSubWithOverflow(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResult { |
| 1126 | 1126 | switch (ty.toIntern()) { |
| 1127 | 1127 | .comptime_int_type => return .{ |
| 1128 | .overflow_bit = try sema.pt.intValue(.u1, 0), | |
| 1128 | .overflow_bit = .zero_u1, | |
| 1129 | 1129 | .wrapped_result = try comptimeIntSub(sema, lhs, rhs), |
| 1130 | 1130 | }, |
| 1131 | 1131 | else => return intSubWithOverflowInner(sema, lhs, rhs, ty), |
| ... | ... | @@ -1211,7 +1211,7 @@ fn comptimeIntMul(sema: *Sema, lhs: Value, rhs: Value) !Value { |
| 1211 | 1211 | fn intMulWithOverflow(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value.OverflowArithmeticResult { |
| 1212 | 1212 | switch (ty.toIntern()) { |
| 1213 | 1213 | .comptime_int_type => return .{ |
| 1214 | .overflow_bit = try sema.pt.intValue(.u1, 0), | |
| 1214 | .overflow_bit = .zero_u1, | |
| 1215 | 1215 | .wrapped_result = try comptimeIntMul(sema, lhs, rhs), |
| 1216 | 1216 | }, |
| 1217 | 1217 | else => return intMulWithOverflowInner(sema, lhs, rhs, ty), |
src/Type.zig+7-6| ... | ... | @@ -2641,10 +2641,7 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value { |
| 2641 | 2641 | if (enum_type.values.len == 0) { |
| 2642 | 2642 | const only = try pt.intern(.{ .enum_tag = .{ |
| 2643 | 2643 | .ty = ty.toIntern(), |
| 2644 | .int = try pt.intern(.{ .int = .{ | |
| 2645 | .ty = enum_type.tag_ty, | |
| 2646 | .storage = .{ .u64 = 0 }, | |
| 2647 | } }), | |
| 2644 | .int = (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern(), | |
| 2648 | 2645 | } }); |
| 2649 | 2646 | return Value.fromInterned(only); |
| 2650 | 2647 | } else { |
| ... | ... | @@ -3676,10 +3673,11 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void { |
| 3676 | 3673 | .null_type, |
| 3677 | 3674 | .undefined_type, |
| 3678 | 3675 | .enum_literal_type, |
| 3676 | .ptr_usize_type, | |
| 3677 | .ptr_const_comptime_int_type, | |
| 3679 | 3678 | .manyptr_u8_type, |
| 3680 | 3679 | .manyptr_const_u8_type, |
| 3681 | 3680 | .manyptr_const_u8_sentinel_0_type, |
| 3682 | .single_const_pointer_to_comptime_int_type, | |
| 3683 | 3681 | .slice_const_u8_type, |
| 3684 | 3682 | .slice_const_u8_sentinel_0_type, |
| 3685 | 3683 | .optional_noreturn_type, |
| ... | ... | @@ -3691,9 +3689,11 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void { |
| 3691 | 3689 | .undef => unreachable, |
| 3692 | 3690 | .zero => unreachable, |
| 3693 | 3691 | .zero_usize => unreachable, |
| 3692 | .zero_u1 => unreachable, | |
| 3694 | 3693 | .zero_u8 => unreachable, |
| 3695 | 3694 | .one => unreachable, |
| 3696 | 3695 | .one_usize => unreachable, |
| 3696 | .one_u1 => unreachable, | |
| 3697 | 3697 | .one_u8 => unreachable, |
| 3698 | 3698 | .four_u8 => unreachable, |
| 3699 | 3699 | .negative_one => unreachable, |
| ... | ... | @@ -4100,10 +4100,11 @@ pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type }; |
| 4100 | 4100 | pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type }; |
| 4101 | 4101 | pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type }; |
| 4102 | 4102 | |
| 4103 | pub const ptr_usize: Type = .{ .ip_index = .ptr_usize_type }; | |
| 4104 | pub const ptr_const_comptime_int: Type = .{ .ip_index = .ptr_const_comptime_int_type }; | |
| 4103 | 4105 | pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type }; |
| 4104 | 4106 | pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type }; |
| 4105 | 4107 | pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type }; |
| 4106 | pub const single_const_pointer_to_comptime_int: Type = .{ .ip_index = .single_const_pointer_to_comptime_int_type }; | |
| 4107 | 4108 | pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type }; |
| 4108 | 4109 | pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type }; |
| 4109 | 4110 |
src/Value.zig+12-6| ... | ... | @@ -2895,19 +2895,25 @@ pub fn intValueBounds(val: Value, pt: Zcu.PerThread) !?[2]Value { |
| 2895 | 2895 | |
| 2896 | 2896 | pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace; |
| 2897 | 2897 | |
| 2898 | pub const undef: Value = .{ .ip_index = .undef }; | |
| 2899 | pub const undef_bool: Value = .{ .ip_index = .undef_bool }; | |
| 2900 | pub const undef_usize: Value = .{ .ip_index = .undef_usize }; | |
| 2901 | pub const undef_u1: Value = .{ .ip_index = .undef_u1 }; | |
| 2902 | pub const zero_comptime_int: Value = .{ .ip_index = .zero }; | |
| 2898 | 2903 | pub const zero_usize: Value = .{ .ip_index = .zero_usize }; |
| 2904 | pub const zero_u1: Value = .{ .ip_index = .zero_u1 }; | |
| 2899 | 2905 | pub const zero_u8: Value = .{ .ip_index = .zero_u8 }; |
| 2900 | pub const zero_comptime_int: Value = .{ .ip_index = .zero }; | |
| 2901 | 2906 | pub const one_comptime_int: Value = .{ .ip_index = .one }; |
| 2907 | pub const one_usize: Value = .{ .ip_index = .one_usize }; | |
| 2908 | pub const one_u1: Value = .{ .ip_index = .one_u1 }; | |
| 2909 | pub const one_u8: Value = .{ .ip_index = .one_u8 }; | |
| 2910 | pub const four_u8: Value = .{ .ip_index = .four_u8 }; | |
| 2902 | 2911 | pub const negative_one_comptime_int: Value = .{ .ip_index = .negative_one }; |
| 2903 | pub const undef: Value = .{ .ip_index = .undef }; | |
| 2904 | 2912 | pub const @"void": Value = .{ .ip_index = .void_value }; |
| 2913 | pub const @"unreachable": Value = .{ .ip_index = .unreachable_value }; | |
| 2905 | 2914 | pub const @"null": Value = .{ .ip_index = .null_value }; |
| 2906 | pub const @"false": Value = .{ .ip_index = .bool_false }; | |
| 2907 | 2915 | pub const @"true": Value = .{ .ip_index = .bool_true }; |
| 2908 | pub const @"unreachable": Value = .{ .ip_index = .unreachable_value }; | |
| 2909 | ||
| 2910 | pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type }; | |
| 2916 | pub const @"false": Value = .{ .ip_index = .bool_false }; | |
| 2911 | 2917 | pub const empty_tuple: Value = .{ .ip_index = .empty_tuple }; |
| 2912 | 2918 | |
| 2913 | 2919 | pub fn makeBool(x: bool) Value { |
src/Zcu.zig+4-26| ... | ... | @@ -441,8 +441,7 @@ pub const BuiltinDecl = enum { |
| 441 | 441 | @"panic.castToNull", |
| 442 | 442 | @"panic.incorrectAlignment", |
| 443 | 443 | @"panic.invalidErrorCode", |
| 444 | @"panic.castTruncatedData", | |
| 445 | @"panic.negativeToUnsigned", | |
| 444 | @"panic.integerOutOfBounds", | |
| 446 | 445 | @"panic.integerOverflow", |
| 447 | 446 | @"panic.shlOverflow", |
| 448 | 447 | @"panic.shrOverflow", |
| ... | ... | @@ -518,8 +517,7 @@ pub const BuiltinDecl = enum { |
| 518 | 517 | .@"panic.castToNull", |
| 519 | 518 | .@"panic.incorrectAlignment", |
| 520 | 519 | .@"panic.invalidErrorCode", |
| 521 | .@"panic.castTruncatedData", | |
| 522 | .@"panic.negativeToUnsigned", | |
| 520 | .@"panic.integerOutOfBounds", | |
| 523 | 521 | .@"panic.integerOverflow", |
| 524 | 522 | .@"panic.shlOverflow", |
| 525 | 523 | .@"panic.shrOverflow", |
| ... | ... | @@ -585,8 +583,7 @@ pub const SimplePanicId = enum { |
| 585 | 583 | cast_to_null, |
| 586 | 584 | incorrect_alignment, |
| 587 | 585 | invalid_error_code, |
| 588 | cast_truncated_data, | |
| 589 | negative_to_unsigned, | |
| 586 | integer_out_of_bounds, | |
| 590 | 587 | integer_overflow, |
| 591 | 588 | shl_overflow, |
| 592 | 589 | shr_overflow, |
| ... | ... | @@ -609,8 +606,7 @@ pub const SimplePanicId = enum { |
| 609 | 606 | .cast_to_null => .@"panic.castToNull", |
| 610 | 607 | .incorrect_alignment => .@"panic.incorrectAlignment", |
| 611 | 608 | .invalid_error_code => .@"panic.invalidErrorCode", |
| 612 | .cast_truncated_data => .@"panic.castTruncatedData", | |
| 613 | .negative_to_unsigned => .@"panic.negativeToUnsigned", | |
| 609 | .integer_out_of_bounds => .@"panic.integerOutOfBounds", | |
| 614 | 610 | .integer_overflow => .@"panic.integerOverflow", |
| 615 | 611 | .shl_overflow => .@"panic.shlOverflow", |
| 616 | 612 | .shr_overflow => .@"panic.shrOverflow", |
| ... | ... | @@ -3829,26 +3825,8 @@ pub const Feature = enum { |
| 3829 | 3825 | is_named_enum_value, |
| 3830 | 3826 | error_set_has_value, |
| 3831 | 3827 | field_reordering, |
| 3832 | /// When this feature is supported, the backend supports the following AIR instructions: | |
| 3833 | /// * `Air.Inst.Tag.add_safe` | |
| 3834 | /// * `Air.Inst.Tag.sub_safe` | |
| 3835 | /// * `Air.Inst.Tag.mul_safe` | |
| 3836 | /// * `Air.Inst.Tag.intcast_safe` | |
| 3837 | /// The motivation for this feature is that it makes AIR smaller, and makes it easier | |
| 3838 | /// to generate better machine code in the backends. All backends should migrate to | |
| 3839 | /// enabling this feature. | |
| 3840 | safety_checked_instructions, | |
| 3841 | 3828 | /// If the backend supports running from another thread. |
| 3842 | 3829 | separate_thread, |
| 3843 | /// If the backend supports the following AIR instructions with vector types: | |
| 3844 | /// * `Air.Inst.Tag.bit_and` | |
| 3845 | /// * `Air.Inst.Tag.bit_or` | |
| 3846 | /// * `Air.Inst.Tag.bitcast` | |
| 3847 | /// * `Air.Inst.Tag.float_from_int` | |
| 3848 | /// * `Air.Inst.Tag.fptrunc` | |
| 3849 | /// * `Air.Inst.Tag.int_from_float` | |
| 3850 | /// If not supported, Sema will scalarize the operation. | |
| 3851 | all_vector_instructions, | |
| 3852 | 3830 | }; |
| 3853 | 3831 | |
| 3854 | 3832 | pub fn backendSupportsFeature(zcu: *const Zcu, comptime feature: Feature) bool { |
src/Zcu/PerThread.zig+21-4| ... | ... | @@ -1741,10 +1741,11 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A |
| 1741 | 1741 | return; |
| 1742 | 1742 | } |
| 1743 | 1743 | |
| 1744 | const backend = target_util.zigBackend(zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm); | |
| 1745 | try air.legalize(backend, zcu); | |
| 1744 | legalize: { | |
| 1745 | try air.legalize(pt, @import("../codegen.zig").legalizeFeatures(pt, nav_index) orelse break :legalize); | |
| 1746 | } | |
| 1746 | 1747 | |
| 1747 | var liveness = try Air.Liveness.analyze(gpa, air.*, ip); | |
| 1748 | var liveness = try Air.Liveness.analyze(zcu, air.*, ip); | |
| 1748 | 1749 | defer liveness.deinit(gpa); |
| 1749 | 1750 | |
| 1750 | 1751 | if (build_options.enable_debug_extensions and comp.verbose_air) { |
| ... | ... | @@ -1756,6 +1757,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A |
| 1756 | 1757 | if (std.debug.runtime_safety) { |
| 1757 | 1758 | var verify: Air.Liveness.Verify = .{ |
| 1758 | 1759 | .gpa = gpa, |
| 1760 | .zcu = zcu, | |
| 1759 | 1761 | .air = air.*, |
| 1760 | 1762 | .liveness = liveness, |
| 1761 | 1763 | .intern_pool = ip, |
| ... | ... | @@ -3022,7 +3024,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE |
| 3022 | 3024 | // is unused so it just has to be a no-op. |
| 3023 | 3025 | sema.air_instructions.set(@intFromEnum(ptr_inst), .{ |
| 3024 | 3026 | .tag = .alloc, |
| 3025 | .data = .{ .ty = Type.single_const_pointer_to_comptime_int }, | |
| 3027 | .data = .{ .ty = .ptr_const_comptime_int }, | |
| 3026 | 3028 | }); |
| 3027 | 3029 | } |
| 3028 | 3030 | |
| ... | ... | @@ -3843,6 +3845,21 @@ pub fn nullValue(pt: Zcu.PerThread, opt_ty: Type) Allocator.Error!Value { |
| 3843 | 3845 | } })); |
| 3844 | 3846 | } |
| 3845 | 3847 | |
| 3848 | /// `ty` is an integer or a vector of integers. | |
| 3849 | pub fn overflowArithmeticTupleType(pt: Zcu.PerThread, ty: Type) !Type { | |
| 3850 | const zcu = pt.zcu; | |
| 3851 | const ip = &zcu.intern_pool; | |
| 3852 | const ov_ty: Type = if (ty.zigTypeTag(zcu) == .vector) try pt.vectorType(.{ | |
| 3853 | .len = ty.vectorLen(zcu), | |
| 3854 | .child = .u1_type, | |
| 3855 | }) else .u1; | |
| 3856 | const tuple_ty = try ip.getTupleType(zcu.gpa, pt.tid, .{ | |
| 3857 | .types = &.{ ty.toIntern(), ov_ty.toIntern() }, | |
| 3858 | .values = &.{ .none, .none }, | |
| 3859 | }); | |
| 3860 | return .fromInterned(tuple_ty); | |
| 3861 | } | |
| 3862 | ||
| 3846 | 3863 | pub fn smallestUnsignedInt(pt: Zcu.PerThread, max: u64) Allocator.Error!Type { |
| 3847 | 3864 | return pt.intType(.unsigned, Type.smallestUnsignedBits(max)); |
| 3848 | 3865 | } |
src/arch/aarch64/CodeGen.zig+33-12| ... | ... | @@ -40,6 +40,10 @@ const gp = abi.RegisterClass.gp; |
| 40 | 40 | |
| 41 | 41 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 42 | 42 | |
| 43 | pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { | |
| 44 | return null; | |
| 45 | } | |
| 46 | ||
| 43 | 47 | gpa: Allocator, |
| 44 | 48 | pt: Zcu.PerThread, |
| 45 | 49 | air: Air, |
| ... | ... | @@ -774,7 +778,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 774 | 778 | .error_name => try self.airErrorName(inst), |
| 775 | 779 | .splat => try self.airSplat(inst), |
| 776 | 780 | .select => try self.airSelect(inst), |
| 777 | .shuffle => try self.airShuffle(inst), | |
| 781 | .shuffle_one => try self.airShuffleOne(inst), | |
| 782 | .shuffle_two => try self.airShuffleTwo(inst), | |
| 778 | 783 | .reduce => try self.airReduce(inst), |
| 779 | 784 | .aggregate_init => try self.airAggregateInit(inst), |
| 780 | 785 | .union_init => try self.airUnionInit(inst), |
| ... | ... | @@ -2261,12 +2266,13 @@ fn shiftExact( |
| 2261 | 2266 | rhs_ty: Type, |
| 2262 | 2267 | maybe_inst: ?Air.Inst.Index, |
| 2263 | 2268 | ) InnerError!MCValue { |
| 2264 | _ = rhs_ty; | |
| 2265 | ||
| 2266 | 2269 | const pt = self.pt; |
| 2267 | 2270 | const zcu = pt.zcu; |
| 2268 | 2271 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2269 | .vector => return self.fail("TODO binary operations on vectors", .{}), | |
| 2272 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 2273 | return self.fail("TODO vector shift with scalar rhs", .{}) | |
| 2274 | else | |
| 2275 | return self.fail("TODO binary operations on vectors", .{}), | |
| 2270 | 2276 | .int => { |
| 2271 | 2277 | const int_info = lhs_ty.intInfo(zcu); |
| 2272 | 2278 | if (int_info.bits <= 64) { |
| ... | ... | @@ -2317,7 +2323,10 @@ fn shiftNormal( |
| 2317 | 2323 | const pt = self.pt; |
| 2318 | 2324 | const zcu = pt.zcu; |
| 2319 | 2325 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2320 | .vector => return self.fail("TODO binary operations on vectors", .{}), | |
| 2326 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 2327 | return self.fail("TODO vector shift with scalar rhs", .{}) | |
| 2328 | else | |
| 2329 | return self.fail("TODO binary operations on vectors", .{}), | |
| 2321 | 2330 | .int => { |
| 2322 | 2331 | const int_info = lhs_ty.intInfo(zcu); |
| 2323 | 2332 | if (int_info.bits <= 64) { |
| ... | ... | @@ -2874,7 +2883,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 2874 | 2883 | const overflow_bit_offset = @as(u32, @intCast(tuple_ty.structFieldOffset(1, zcu))); |
| 2875 | 2884 | |
| 2876 | 2885 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2877 | .vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}), | |
| 2886 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 2887 | return self.fail("TODO implement vector shl_with_overflow with scalar rhs", .{}) | |
| 2888 | else | |
| 2889 | return self.fail("TODO implement shl_with_overflow for vectors", .{}), | |
| 2878 | 2890 | .int => { |
| 2879 | 2891 | const int_info = lhs_ty.intInfo(zcu); |
| 2880 | 2892 | if (int_info.bits <= 64) { |
| ... | ... | @@ -2993,8 +3005,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 2993 | 3005 | } |
| 2994 | 3006 | |
| 2995 | 3007 | fn airShlSat(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 3008 | const zcu = self.pt.zcu; | |
| 2996 | 3009 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 2997 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 3010 | const result: MCValue = if (self.liveness.isUnused(inst)) | |
| 3011 | .dead | |
| 3012 | else if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 3013 | return self.fail("TODO implement vector shl_sat with scalar rhs for {}", .{self.target.cpu.arch}) | |
| 3014 | else | |
| 3015 | return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 2998 | 3016 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2999 | 3017 | } |
| 3000 | 3018 | |
| ... | ... | @@ -6032,11 +6050,14 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 6032 | 6050 | return self.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs }); |
| 6033 | 6051 | } |
| 6034 | 6052 | |
| 6035 | fn airShuffle(self: *Self, inst: Air.Inst.Index) InnerError!void { | |
| 6036 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 6037 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; | |
| 6038 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airShuffle for {}", .{self.target.cpu.arch}); | |
| 6039 | return self.finishAir(inst, result, .{ extra.a, extra.b, .none }); | |
| 6053 | fn airShuffleOne(self: *Self, inst: Air.Inst.Index) InnerError!void { | |
| 6054 | _ = inst; | |
| 6055 | return self.fail("TODO implement airShuffleOne for {}", .{self.target.cpu.arch}); | |
| 6056 | } | |
| 6057 | ||
| 6058 | fn airShuffleTwo(self: *Self, inst: Air.Inst.Index) InnerError!void { | |
| 6059 | _ = inst; | |
| 6060 | return self.fail("TODO implement airShuffleTwo for {}", .{self.target.cpu.arch}); | |
| 6040 | 6061 | } |
| 6041 | 6062 | |
| 6042 | 6063 | fn airReduce(self: *Self, inst: Air.Inst.Index) InnerError!void { |
src/arch/arm/CodeGen.zig+33-9| ... | ... | @@ -41,6 +41,10 @@ const gp = abi.RegisterClass.gp; |
| 41 | 41 | |
| 42 | 42 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 43 | 43 | |
| 44 | pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { | |
| 45 | return null; | |
| 46 | } | |
| 47 | ||
| 44 | 48 | gpa: Allocator, |
| 45 | 49 | pt: Zcu.PerThread, |
| 46 | 50 | air: Air, |
| ... | ... | @@ -763,7 +767,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 763 | 767 | .error_name => try self.airErrorName(inst), |
| 764 | 768 | .splat => try self.airSplat(inst), |
| 765 | 769 | .select => try self.airSelect(inst), |
| 766 | .shuffle => try self.airShuffle(inst), | |
| 770 | .shuffle_one => try self.airShuffleOne(inst), | |
| 771 | .shuffle_two => try self.airShuffleTwo(inst), | |
| 767 | 772 | .reduce => try self.airReduce(inst), |
| 768 | 773 | .aggregate_init => try self.airAggregateInit(inst), |
| 769 | 774 | .union_init => try self.airUnionInit(inst), |
| ... | ... | @@ -1857,7 +1862,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1857 | 1862 | const overflow_bit_offset: u32 = @intCast(tuple_ty.structFieldOffset(1, zcu)); |
| 1858 | 1863 | |
| 1859 | 1864 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 1860 | .vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}), | |
| 1865 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 1866 | return self.fail("TODO implement vector shl_with_overflow with scalar rhs", .{}) | |
| 1867 | else | |
| 1868 | return self.fail("TODO implement shl_with_overflow for vectors", .{}), | |
| 1861 | 1869 | .int => { |
| 1862 | 1870 | const int_info = lhs_ty.intInfo(zcu); |
| 1863 | 1871 | if (int_info.bits <= 32) { |
| ... | ... | @@ -1978,8 +1986,14 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1978 | 1986 | } |
| 1979 | 1987 | |
| 1980 | 1988 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 1989 | const zcu = self.pt.zcu; | |
| 1981 | 1990 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 1982 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 1991 | const result: MCValue = if (self.liveness.isUnused(inst)) | |
| 1992 | .dead | |
| 1993 | else if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 1994 | return self.fail("TODO implement vector shl_sat with scalar rhs for {}", .{self.target.cpu.arch}) | |
| 1995 | else | |
| 1996 | return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 1983 | 1997 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1984 | 1998 | } |
| 1985 | 1999 | |
| ... | ... | @@ -3788,7 +3802,10 @@ fn shiftExact( |
| 3788 | 3802 | const pt = self.pt; |
| 3789 | 3803 | const zcu = pt.zcu; |
| 3790 | 3804 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 3791 | .vector => return self.fail("TODO ARM binary operations on vectors", .{}), | |
| 3805 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 3806 | return self.fail("TODO ARM vector shift with scalar rhs", .{}) | |
| 3807 | else | |
| 3808 | return self.fail("TODO ARM binary operations on vectors", .{}), | |
| 3792 | 3809 | .int => { |
| 3793 | 3810 | const int_info = lhs_ty.intInfo(zcu); |
| 3794 | 3811 | if (int_info.bits <= 32) { |
| ... | ... | @@ -3828,7 +3845,10 @@ fn shiftNormal( |
| 3828 | 3845 | const pt = self.pt; |
| 3829 | 3846 | const zcu = pt.zcu; |
| 3830 | 3847 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 3831 | .vector => return self.fail("TODO ARM binary operations on vectors", .{}), | |
| 3848 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 3849 | return self.fail("TODO ARM vector shift with scalar rhs", .{}) | |
| 3850 | else | |
| 3851 | return self.fail("TODO ARM binary operations on vectors", .{}), | |
| 3832 | 3852 | .int => { |
| 3833 | 3853 | const int_info = lhs_ty.intInfo(zcu); |
| 3834 | 3854 | if (int_info.bits <= 32) { |
| ... | ... | @@ -6002,10 +6022,14 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 6002 | 6022 | return self.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs }); |
| 6003 | 6023 | } |
| 6004 | 6024 | |
| 6005 | fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { | |
| 6006 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | |
| 6007 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airShuffle for arm", .{}); | |
| 6008 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | |
| 6025 | fn airShuffleOne(self: *Self, inst: Air.Inst.Index) !void { | |
| 6026 | _ = inst; | |
| 6027 | return self.fail("TODO implement airShuffleOne for arm", .{}); | |
| 6028 | } | |
| 6029 | ||
| 6030 | fn airShuffleTwo(self: *Self, inst: Air.Inst.Index) !void { | |
| 6031 | _ = inst; | |
| 6032 | return self.fail("TODO implement airShuffleTwo for arm", .{}); | |
| 6009 | 6033 | } |
| 6010 | 6034 | |
| 6011 | 6035 | fn airReduce(self: *Self, inst: Air.Inst.Index) !void { |
src/arch/powerpc/CodeGen.zig+4| ... | ... | @@ -10,6 +10,10 @@ const Zcu = @import("../../Zcu.zig"); |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | const log = std.log.scoped(.codegen); |
| 12 | 12 | |
| 13 | pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { | |
| 14 | return null; | |
| 15 | } | |
| 16 | ||
| 13 | 17 | pub fn generate( |
| 14 | 18 | bin_file: *link.File, |
| 15 | 19 | pt: Zcu.PerThread, |
src/arch/riscv64/CodeGen.zig+34-7| ... | ... | @@ -51,6 +51,15 @@ const Instruction = encoding.Instruction; |
| 51 | 51 | |
| 52 | 52 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 53 | 53 | |
| 54 | pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 55 | return comptime &.initMany(&.{ | |
| 56 | .expand_intcast_safe, | |
| 57 | .expand_add_safe, | |
| 58 | .expand_sub_safe, | |
| 59 | .expand_mul_safe, | |
| 60 | }); | |
| 61 | } | |
| 62 | ||
| 54 | 63 | pt: Zcu.PerThread, |
| 55 | 64 | air: Air, |
| 56 | 65 | liveness: Air.Liveness, |
| ... | ... | @@ -1577,7 +1586,8 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1577 | 1586 | .error_name => try func.airErrorName(inst), |
| 1578 | 1587 | .splat => try func.airSplat(inst), |
| 1579 | 1588 | .select => try func.airSelect(inst), |
| 1580 | .shuffle => try func.airShuffle(inst), | |
| 1589 | .shuffle_one => try func.airShuffleOne(inst), | |
| 1590 | .shuffle_two => try func.airShuffleTwo(inst), | |
| 1581 | 1591 | .reduce => try func.airReduce(inst), |
| 1582 | 1592 | .aggregate_init => try func.airAggregateInit(inst), |
| 1583 | 1593 | .union_init => try func.airUnionInit(inst), |
| ... | ... | @@ -2764,6 +2774,7 @@ fn genBinOp( |
| 2764 | 2774 | .shl, |
| 2765 | 2775 | .shl_exact, |
| 2766 | 2776 | => { |
| 2777 | if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) return func.fail("TODO: vector shift with scalar rhs", .{}); | |
| 2767 | 2778 | if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size}); |
| 2768 | 2779 | try func.truncateRegister(rhs_ty, rhs_reg); |
| 2769 | 2780 | |
| ... | ... | @@ -3248,8 +3259,14 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3248 | 3259 | } |
| 3249 | 3260 | |
| 3250 | 3261 | fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3262 | const zcu = func.pt.zcu; | |
| 3251 | 3263 | const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3252 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlWithOverflow", .{}); | |
| 3264 | const result: MCValue = if (func.liveness.isUnused(inst)) | |
| 3265 | .unreach | |
| 3266 | else if (func.typeOf(bin_op.lhs).isVector(zcu) and !func.typeOf(bin_op.rhs).isVector(zcu)) | |
| 3267 | return func.fail("TODO implement vector airShlWithOverflow with scalar rhs", .{}) | |
| 3268 | else | |
| 3269 | return func.fail("TODO implement airShlWithOverflow", .{}); | |
| 3253 | 3270 | return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 3254 | 3271 | } |
| 3255 | 3272 | |
| ... | ... | @@ -3266,8 +3283,14 @@ fn airMulSat(func: *Func, inst: Air.Inst.Index) !void { |
| 3266 | 3283 | } |
| 3267 | 3284 | |
| 3268 | 3285 | fn airShlSat(func: *Func, inst: Air.Inst.Index) !void { |
| 3286 | const zcu = func.pt.zcu; | |
| 3269 | 3287 | const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3270 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShlSat", .{}); | |
| 3288 | const result: MCValue = if (func.liveness.isUnused(inst)) | |
| 3289 | .unreach | |
| 3290 | else if (func.typeOf(bin_op.lhs).isVector(zcu) and !func.typeOf(bin_op.rhs).isVector(zcu)) | |
| 3291 | return func.fail("TODO implement vector airShlSat with scalar rhs", .{}) | |
| 3292 | else | |
| 3293 | return func.fail("TODO implement airShlSat", .{}); | |
| 3271 | 3294 | return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 3272 | 3295 | } |
| 3273 | 3296 | |
| ... | ... | @@ -8008,10 +8031,14 @@ fn airSelect(func: *Func, inst: Air.Inst.Index) !void { |
| 8008 | 8031 | return func.finishAir(inst, result, .{ pl_op.operand, extra.lhs, extra.rhs }); |
| 8009 | 8032 | } |
| 8010 | 8033 | |
| 8011 | fn airShuffle(func: *Func, inst: Air.Inst.Index) !void { | |
| 8012 | const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | |
| 8013 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airShuffle for riscv64", .{}); | |
| 8014 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | |
| 8034 | fn airShuffleOne(func: *Func, inst: Air.Inst.Index) !void { | |
| 8035 | _ = inst; | |
| 8036 | return func.fail("TODO implement airShuffleOne for riscv64", .{}); | |
| 8037 | } | |
| 8038 | ||
| 8039 | fn airShuffleTwo(func: *Func, inst: Air.Inst.Index) !void { | |
| 8040 | _ = inst; | |
| 8041 | return func.fail("TODO implement airShuffleTwo for riscv64", .{}); | |
| 8015 | 8042 | } |
| 8016 | 8043 | |
| 8017 | 8044 | fn airReduce(func: *Func, inst: Air.Inst.Index) !void { |
src/arch/sparc64/CodeGen.zig+25-5| ... | ... | @@ -41,6 +41,10 @@ const Self = @This(); |
| 41 | 41 | |
| 42 | 42 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 43 | 43 | |
| 44 | pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { | |
| 45 | return null; | |
| 46 | } | |
| 47 | ||
| 44 | 48 | const RegisterView = enum(u1) { |
| 45 | 49 | caller, |
| 46 | 50 | callee, |
| ... | ... | @@ -617,7 +621,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 617 | 621 | .error_name => try self.airErrorName(inst), |
| 618 | 622 | .splat => try self.airSplat(inst), |
| 619 | 623 | .select => @panic("TODO try self.airSelect(inst)"), |
| 620 | .shuffle => @panic("TODO try self.airShuffle(inst)"), | |
| 624 | .shuffle_one => @panic("TODO try self.airShuffleOne(inst)"), | |
| 625 | .shuffle_two => @panic("TODO try self.airShuffleTwo(inst)"), | |
| 621 | 626 | .reduce => @panic("TODO try self.airReduce(inst)"), |
| 622 | 627 | .aggregate_init => try self.airAggregateInit(inst), |
| 623 | 628 | .union_init => try self.airUnionInit(inst), |
| ... | ... | @@ -2270,8 +2275,14 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 2270 | 2275 | } |
| 2271 | 2276 | |
| 2272 | 2277 | fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2278 | const zcu = self.pt.zcu; | |
| 2273 | 2279 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 2274 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 2280 | const result: MCValue = if (self.liveness.isUnused(inst)) | |
| 2281 | .dead | |
| 2282 | else if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 2283 | return self.fail("TODO implement vector shl_sat with scalar rhs for {}", .{self.target.cpu.arch}) | |
| 2284 | else | |
| 2285 | return self.fail("TODO implement shl_sat for {}", .{self.target.cpu.arch}); | |
| 2275 | 2286 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2276 | 2287 | } |
| 2277 | 2288 | |
| ... | ... | @@ -2287,7 +2298,10 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2287 | 2298 | const rhs_ty = self.typeOf(extra.rhs); |
| 2288 | 2299 | |
| 2289 | 2300 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2290 | .vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}), | |
| 2301 | .vector => if (!rhs_ty.isVector(zcu)) | |
| 2302 | return self.fail("TODO implement vector shl_with_overflow with scalar rhs", .{}) | |
| 2303 | else | |
| 2304 | return self.fail("TODO implement mul_with_overflow for vectors", .{}), | |
| 2291 | 2305 | .int => { |
| 2292 | 2306 | const int_info = lhs_ty.intInfo(zcu); |
| 2293 | 2307 | if (int_info.bits <= 64) { |
| ... | ... | @@ -3002,7 +3016,10 @@ fn binOp( |
| 3002 | 3016 | |
| 3003 | 3017 | // Truncate if necessary |
| 3004 | 3018 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 3005 | .vector => return self.fail("TODO binary operations on vectors", .{}), | |
| 3019 | .vector => if (rhs_ty.isVector(zcu)) | |
| 3020 | return self.fail("TODO vector shift with scalar rhs", .{}) | |
| 3021 | else | |
| 3022 | return self.fail("TODO binary operations on vectors", .{}), | |
| 3006 | 3023 | .int => { |
| 3007 | 3024 | const int_info = lhs_ty.intInfo(zcu); |
| 3008 | 3025 | if (int_info.bits <= 64) { |
| ... | ... | @@ -3024,7 +3041,10 @@ fn binOp( |
| 3024 | 3041 | .shr_exact, |
| 3025 | 3042 | => { |
| 3026 | 3043 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 3027 | .vector => return self.fail("TODO binary operations on vectors", .{}), | |
| 3044 | .vector => if (rhs_ty.isVector(zcu)) | |
| 3045 | return self.fail("TODO vector shift with scalar rhs", .{}) | |
| 3046 | else | |
| 3047 | return self.fail("TODO binary operations on vectors", .{}), | |
| 3028 | 3048 | .int => { |
| 3029 | 3049 | const int_info = lhs_ty.intInfo(zcu); |
| 3030 | 3050 | if (int_info.bits <= 64) { |
src/arch/wasm/CodeGen.zig+116-50| ... | ... | @@ -31,6 +31,15 @@ const libcFloatSuffix = target_util.libcFloatSuffix; |
| 31 | 31 | const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; |
| 32 | 32 | const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; |
| 33 | 33 | |
| 34 | pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 35 | return comptime &.initMany(&.{ | |
| 36 | .expand_intcast_safe, | |
| 37 | .expand_add_safe, | |
| 38 | .expand_sub_safe, | |
| 39 | .expand_mul_safe, | |
| 40 | }); | |
| 41 | } | |
| 42 | ||
| 34 | 43 | /// Reference to the function declaration the code |
| 35 | 44 | /// section belongs to |
| 36 | 45 | owner_nav: InternPool.Nav.Index, |
| ... | ... | @@ -1995,7 +2004,8 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1995 | 2004 | .ret_load => cg.airRetLoad(inst), |
| 1996 | 2005 | .splat => cg.airSplat(inst), |
| 1997 | 2006 | .select => cg.airSelect(inst), |
| 1998 | .shuffle => cg.airShuffle(inst), | |
| 2007 | .shuffle_one => cg.airShuffleOne(inst), | |
| 2008 | .shuffle_two => cg.airShuffleTwo(inst), | |
| 1999 | 2009 | .reduce => cg.airReduce(inst), |
| 2000 | 2010 | .aggregate_init => cg.airAggregateInit(inst), |
| 2001 | 2011 | .union_init => cg.airUnionInit(inst), |
| ... | ... | @@ -2638,6 +2648,10 @@ fn airBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 2638 | 2648 | // For big integers we can ignore this as we will call into compiler-rt which handles this. |
| 2639 | 2649 | const result = switch (op) { |
| 2640 | 2650 | .shr, .shl => result: { |
| 2651 | if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) { | |
| 2652 | return cg.fail("TODO: implement vector '{s}' with scalar rhs", .{@tagName(op)}); | |
| 2653 | } | |
| 2654 | ||
| 2641 | 2655 | const lhs_wasm_bits = toWasmBits(@intCast(lhs_ty.bitSize(zcu))) orelse { |
| 2642 | 2656 | return cg.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)}); |
| 2643 | 2657 | }; |
| ... | ... | @@ -3055,8 +3069,12 @@ fn airWrapBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 3055 | 3069 | const lhs_ty = cg.typeOf(bin_op.lhs); |
| 3056 | 3070 | const rhs_ty = cg.typeOf(bin_op.rhs); |
| 3057 | 3071 | |
| 3058 | if (lhs_ty.zigTypeTag(zcu) == .vector or rhs_ty.zigTypeTag(zcu) == .vector) { | |
| 3059 | return cg.fail("TODO: Implement wrapping arithmetic for vectors", .{}); | |
| 3072 | if (lhs_ty.isVector(zcu)) { | |
| 3073 | if ((op == .shr or op == .shl) and !rhs_ty.isVector(zcu)) { | |
| 3074 | return cg.fail("TODO: implement wrapping vector '{s}' with scalar rhs", .{@tagName(op)}); | |
| 3075 | } else { | |
| 3076 | return cg.fail("TODO: implement wrapping '{s}' for vectors", .{@tagName(op)}); | |
| 3077 | } | |
| 3060 | 3078 | } |
| 3061 | 3079 | |
| 3062 | 3080 | // For certain operations, such as shifting, the types are different. |
| ... | ... | @@ -5160,66 +5178,105 @@ fn airSelect(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5160 | 5178 | return cg.fail("TODO: Implement wasm airSelect", .{}); |
| 5161 | 5179 | } |
| 5162 | 5180 | |
| 5163 | fn airShuffle(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | |
| 5181 | fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | |
| 5164 | 5182 | const pt = cg.pt; |
| 5165 | 5183 | const zcu = pt.zcu; |
| 5166 | const inst_ty = cg.typeOfIndex(inst); | |
| 5167 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 5168 | const extra = cg.air.extraData(Air.Shuffle, ty_pl.payload).data; | |
| 5169 | 5184 | |
| 5170 | const a = try cg.resolveInst(extra.a); | |
| 5171 | const b = try cg.resolveInst(extra.b); | |
| 5172 | const mask = Value.fromInterned(extra.mask); | |
| 5173 | const mask_len = extra.mask_len; | |
| 5185 | const unwrapped = cg.air.unwrapShuffleOne(zcu, inst); | |
| 5186 | const result_ty = unwrapped.result_ty; | |
| 5187 | const mask = unwrapped.mask; | |
| 5188 | const operand = try cg.resolveInst(unwrapped.operand); | |
| 5174 | 5189 | |
| 5175 | const child_ty = inst_ty.childType(zcu); | |
| 5176 | const elem_size = child_ty.abiSize(zcu); | |
| 5190 | const elem_ty = result_ty.childType(zcu); | |
| 5191 | const elem_size = elem_ty.abiSize(zcu); | |
| 5177 | 5192 | |
| 5178 | // TODO: One of them could be by ref; handle in loop | |
| 5179 | if (isByRef(cg.typeOf(extra.a), zcu, cg.target) or isByRef(inst_ty, zcu, cg.target)) { | |
| 5180 | const result = try cg.allocStack(inst_ty); | |
| 5193 | // TODO: this function could have an `i8x16_shuffle` fast path like `airShuffleTwo` if we were | |
| 5194 | // to lower the comptime-known operands to a non-by-ref vector value. | |
| 5181 | 5195 | |
| 5182 | for (0..mask_len) |index| { | |
| 5183 | const value = (try mask.elemValue(pt, index)).toSignedInt(zcu); | |
| 5196 | // TODO: this is incorrect if either operand or the result is *not* by-ref, which is possible. | |
| 5197 | // I tried to fix it, but I couldn't make much sense of how this backend handles memory. | |
| 5198 | if (!isByRef(result_ty, zcu, cg.target) or | |
| 5199 | !isByRef(cg.typeOf(unwrapped.operand), zcu, cg.target)) return cg.fail("TODO: handle mixed by-ref shuffle", .{}); | |
| 5184 | 5200 | |
| 5185 | try cg.emitWValue(result); | |
| 5201 | const dest_alloc = try cg.allocStack(result_ty); | |
| 5202 | for (mask, 0..) |mask_elem, out_idx| { | |
| 5203 | try cg.emitWValue(dest_alloc); | |
| 5204 | const elem_val = switch (mask_elem.unwrap()) { | |
| 5205 | .elem => |idx| try cg.load(operand, elem_ty, @intCast(elem_size * idx)), | |
| 5206 | .value => |val| try cg.lowerConstant(.fromInterned(val), elem_ty), | |
| 5207 | }; | |
| 5208 | try cg.store(.stack, elem_val, elem_ty, @intCast(dest_alloc.offset() + elem_size * out_idx)); | |
| 5209 | } | |
| 5210 | return cg.finishAir(inst, dest_alloc, &.{unwrapped.operand}); | |
| 5211 | } | |
| 5186 | 5212 | |
| 5187 | const loaded = if (value >= 0) | |
| 5188 | try cg.load(a, child_ty, @as(u32, @intCast(@as(i64, @intCast(elem_size)) * value))) | |
| 5189 | else | |
| 5190 | try cg.load(b, child_ty, @as(u32, @intCast(@as(i64, @intCast(elem_size)) * ~value))); | |
| 5213 | fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | |
| 5214 | const pt = cg.pt; | |
| 5215 | const zcu = pt.zcu; | |
| 5191 | 5216 | |
| 5192 | try cg.store(.stack, loaded, child_ty, result.stack_offset.value + @as(u32, @intCast(elem_size)) * @as(u32, @intCast(index))); | |
| 5193 | } | |
| 5217 | const unwrapped = cg.air.unwrapShuffleTwo(zcu, inst); | |
| 5218 | const result_ty = unwrapped.result_ty; | |
| 5219 | const mask = unwrapped.mask; | |
| 5220 | const operand_a = try cg.resolveInst(unwrapped.operand_a); | |
| 5221 | const operand_b = try cg.resolveInst(unwrapped.operand_b); | |
| 5194 | 5222 | |
| 5195 | return cg.finishAir(inst, result, &.{ extra.a, extra.b }); | |
| 5196 | } else { | |
| 5197 | var operands = [_]u32{ | |
| 5198 | @intFromEnum(std.wasm.SimdOpcode.i8x16_shuffle), | |
| 5199 | } ++ [1]u32{undefined} ** 4; | |
| 5200 | ||
| 5201 | var lanes = mem.asBytes(operands[1..]); | |
| 5202 | for (0..@as(usize, @intCast(mask_len))) |index| { | |
| 5203 | const mask_elem = (try mask.elemValue(pt, index)).toSignedInt(zcu); | |
| 5204 | const base_index = if (mask_elem >= 0) | |
| 5205 | @as(u8, @intCast(@as(i64, @intCast(elem_size)) * mask_elem)) | |
| 5206 | else | |
| 5207 | 16 + @as(u8, @intCast(@as(i64, @intCast(elem_size)) * ~mask_elem)); | |
| 5223 | const a_ty = cg.typeOf(unwrapped.operand_a); | |
| 5224 | const b_ty = cg.typeOf(unwrapped.operand_b); | |
| 5225 | const elem_ty = result_ty.childType(zcu); | |
| 5226 | const elem_size = elem_ty.abiSize(zcu); | |
| 5208 | 5227 | |
| 5209 | for (0..@as(usize, @intCast(elem_size))) |byte_offset| { | |
| 5210 | lanes[index * @as(usize, @intCast(elem_size)) + byte_offset] = base_index + @as(u8, @intCast(byte_offset)); | |
| 5228 | // WASM has `i8x16_shuffle`, which we can apply if the element type bit size is a multiple of 8 | |
| 5229 | // and the input and output vectors have a bit size of 128 (and are hence not by-ref). Otherwise, | |
| 5230 | // we fall back to a naive loop lowering. | |
| 5231 | if (!isByRef(a_ty, zcu, cg.target) and | |
| 5232 | !isByRef(b_ty, zcu, cg.target) and | |
| 5233 | !isByRef(result_ty, zcu, cg.target) and | |
| 5234 | elem_ty.bitSize(zcu) % 8 == 0) | |
| 5235 | { | |
| 5236 | var lane_map: [16]u8 align(4) = undefined; | |
| 5237 | const lanes_per_elem: usize = @intCast(elem_ty.bitSize(zcu) / 8); | |
| 5238 | for (mask, 0..) |mask_elem, out_idx| { | |
| 5239 | const out_first_lane = out_idx * lanes_per_elem; | |
| 5240 | const in_first_lane = switch (mask_elem.unwrap()) { | |
| 5241 | .a_elem => |i| i * lanes_per_elem, | |
| 5242 | .b_elem => |i| i * lanes_per_elem + 16, | |
| 5243 | .undef => 0, // doesn't matter | |
| 5244 | }; | |
| 5245 | for (lane_map[out_first_lane..][0..lanes_per_elem], in_first_lane..) |*out, in| { | |
| 5246 | out.* = @intCast(in); | |
| 5211 | 5247 | } |
| 5212 | 5248 | } |
| 5213 | ||
| 5214 | try cg.emitWValue(a); | |
| 5215 | try cg.emitWValue(b); | |
| 5216 | ||
| 5249 | try cg.emitWValue(operand_a); | |
| 5250 | try cg.emitWValue(operand_b); | |
| 5217 | 5251 | const extra_index = cg.extraLen(); |
| 5218 | try cg.mir_extra.appendSlice(cg.gpa, &operands); | |
| 5252 | try cg.mir_extra.appendSlice(cg.gpa, &.{ | |
| 5253 | @intFromEnum(std.wasm.SimdOpcode.i8x16_shuffle), | |
| 5254 | @bitCast(lane_map[0..4].*), | |
| 5255 | @bitCast(lane_map[4..8].*), | |
| 5256 | @bitCast(lane_map[8..12].*), | |
| 5257 | @bitCast(lane_map[12..].*), | |
| 5258 | }); | |
| 5219 | 5259 | try cg.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 5220 | ||
| 5221 | return cg.finishAir(inst, .stack, &.{ extra.a, extra.b }); | |
| 5260 | return cg.finishAir(inst, .stack, &.{ unwrapped.operand_a, unwrapped.operand_b }); | |
| 5261 | } | |
| 5262 | ||
| 5263 | // TODO: this is incorrect if either operand or the result is *not* by-ref, which is possible. | |
| 5264 | // I tried to fix it, but I couldn't make much sense of how this backend handles memory. | |
| 5265 | if (!isByRef(result_ty, zcu, cg.target) or | |
| 5266 | !isByRef(a_ty, zcu, cg.target) or | |
| 5267 | !isByRef(b_ty, zcu, cg.target)) return cg.fail("TODO: handle mixed by-ref shuffle", .{}); | |
| 5268 | ||
| 5269 | const dest_alloc = try cg.allocStack(result_ty); | |
| 5270 | for (mask, 0..) |mask_elem, out_idx| { | |
| 5271 | try cg.emitWValue(dest_alloc); | |
| 5272 | const elem_val = switch (mask_elem.unwrap()) { | |
| 5273 | .a_elem => |idx| try cg.load(operand_a, elem_ty, @intCast(elem_size * idx)), | |
| 5274 | .b_elem => |idx| try cg.load(operand_b, elem_ty, @intCast(elem_size * idx)), | |
| 5275 | .undef => try cg.emitUndefined(elem_ty), | |
| 5276 | }; | |
| 5277 | try cg.store(.stack, elem_val, elem_ty, @intCast(dest_alloc.offset() + elem_size * out_idx)); | |
| 5222 | 5278 | } |
| 5279 | return cg.finishAir(inst, dest_alloc, &.{ unwrapped.operand_a, unwrapped.operand_b }); | |
| 5223 | 5280 | } |
| 5224 | 5281 | |
| 5225 | 5282 | fn airReduce(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| ... | ... | @@ -6067,13 +6124,17 @@ fn airShlWithOverflow(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6067 | 6124 | const ty = cg.typeOf(extra.lhs); |
| 6068 | 6125 | const rhs_ty = cg.typeOf(extra.rhs); |
| 6069 | 6126 | |
| 6070 | if (ty.zigTypeTag(zcu) == .vector) { | |
| 6071 | return cg.fail("TODO: Implement overflow arithmetic for vectors", .{}); | |
| 6127 | if (ty.isVector(zcu)) { | |
| 6128 | if (!rhs_ty.isVector(zcu)) { | |
| 6129 | return cg.fail("TODO: implement vector 'shl_with_overflow' with scalar rhs", .{}); | |
| 6130 | } else { | |
| 6131 | return cg.fail("TODO: implement vector 'shl_with_overflow'", .{}); | |
| 6132 | } | |
| 6072 | 6133 | } |
| 6073 | 6134 | |
| 6074 | 6135 | const int_info = ty.intInfo(zcu); |
| 6075 | 6136 | const wasm_bits = toWasmBits(int_info.bits) orelse { |
| 6076 | return cg.fail("TODO: Implement shl_with_overflow for integer bitsize: {d}", .{int_info.bits}); | |
| 6137 | return cg.fail("TODO: implement 'shl_with_overflow' for integer bitsize: {d}", .{int_info.bits}); | |
| 6077 | 6138 | }; |
| 6078 | 6139 | |
| 6079 | 6140 | // Ensure rhs is coerced to lhs as they must have the same WebAssembly types |
| ... | ... | @@ -6994,6 +7055,11 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6994 | 7055 | |
| 6995 | 7056 | const pt = cg.pt; |
| 6996 | 7057 | const zcu = pt.zcu; |
| 7058 | ||
| 7059 | if (cg.typeOf(bin_op.lhs).isVector(zcu) and !cg.typeOf(bin_op.rhs).isVector(zcu)) { | |
| 7060 | return cg.fail("TODO: implement vector 'shl_sat' with scalar rhs", .{}); | |
| 7061 | } | |
| 7062 | ||
| 6997 | 7063 | const ty = cg.typeOfIndex(inst); |
| 6998 | 7064 | const int_info = ty.intInfo(zcu); |
| 6999 | 7065 | const is_signed = int_info.signedness == .signed; |
src/arch/x86_64/CodeGen.zig+461-137| ... | ... | @@ -32,10 +32,79 @@ const FrameIndex = bits.FrameIndex; |
| 32 | 32 | |
| 33 | 33 | const InnerError = codegen.CodeGenError || error{OutOfRegisters}; |
| 34 | 34 | |
| 35 | pub const legalize_features: Air.Legalize.Features = .{ | |
| 36 | .remove_shift_vector_rhs_splat = false, | |
| 37 | .reduce_one_elem_to_bitcast = true, | |
| 38 | }; | |
| 35 | pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features { | |
| 36 | @setEvalBranchQuota(1_200); | |
| 37 | return switch (target.ofmt == .coff) { | |
| 38 | inline false, true => |use_old| comptime &.init(.{ | |
| 39 | .scalarize_add = use_old, | |
| 40 | .scalarize_add_sat = use_old, | |
| 41 | .scalarize_sub = use_old, | |
| 42 | .scalarize_sub_sat = use_old, | |
| 43 | .scalarize_mul = use_old, | |
| 44 | .scalarize_mul_wrap = use_old, | |
| 45 | .scalarize_mul_sat = true, | |
| 46 | .scalarize_div_float = use_old, | |
| 47 | .scalarize_div_float_optimized = use_old, | |
| 48 | .scalarize_div_trunc = use_old, | |
| 49 | .scalarize_div_trunc_optimized = use_old, | |
| 50 | .scalarize_div_floor = use_old, | |
| 51 | .scalarize_div_floor_optimized = use_old, | |
| 52 | .scalarize_div_exact = use_old, | |
| 53 | .scalarize_div_exact_optimized = use_old, | |
| 54 | .scalarize_max = use_old, | |
| 55 | .scalarize_min = use_old, | |
| 56 | .scalarize_add_with_overflow = true, | |
| 57 | .scalarize_sub_with_overflow = true, | |
| 58 | .scalarize_mul_with_overflow = true, | |
| 59 | .scalarize_shl_with_overflow = true, | |
| 60 | .scalarize_bit_and = use_old, | |
| 61 | .scalarize_bit_or = use_old, | |
| 62 | .scalarize_shr = true, | |
| 63 | .scalarize_shr_exact = true, | |
| 64 | .scalarize_shl = true, | |
| 65 | .scalarize_shl_exact = true, | |
| 66 | .scalarize_shl_sat = true, | |
| 67 | .scalarize_xor = use_old, | |
| 68 | .scalarize_not = use_old, | |
| 69 | .scalarize_clz = use_old, | |
| 70 | .scalarize_ctz = true, | |
| 71 | .scalarize_popcount = true, | |
| 72 | .scalarize_byte_swap = true, | |
| 73 | .scalarize_bit_reverse = true, | |
| 74 | .scalarize_sin = use_old, | |
| 75 | .scalarize_cos = use_old, | |
| 76 | .scalarize_tan = use_old, | |
| 77 | .scalarize_exp = use_old, | |
| 78 | .scalarize_exp2 = use_old, | |
| 79 | .scalarize_log = use_old, | |
| 80 | .scalarize_log2 = use_old, | |
| 81 | .scalarize_log10 = use_old, | |
| 82 | .scalarize_abs = use_old, | |
| 83 | .scalarize_floor = use_old, | |
| 84 | .scalarize_ceil = use_old, | |
| 85 | .scalarize_trunc_float = use_old, | |
| 86 | .scalarize_cmp_vector = true, | |
| 87 | .scalarize_cmp_vector_optimized = true, | |
| 88 | .scalarize_fptrunc = use_old, | |
| 89 | .scalarize_fpext = use_old, | |
| 90 | .scalarize_intcast = use_old, | |
| 91 | .scalarize_int_from_float = use_old, | |
| 92 | .scalarize_int_from_float_optimized = use_old, | |
| 93 | .scalarize_float_from_int = use_old, | |
| 94 | .scalarize_shuffle_one = true, | |
| 95 | .scalarize_shuffle_two = true, | |
| 96 | .scalarize_select = true, | |
| 97 | .scalarize_mul_add = use_old, | |
| 98 | ||
| 99 | .unsplat_shift_rhs = false, | |
| 100 | .reduce_one_elem_to_bitcast = true, | |
| 101 | .expand_intcast_safe = true, | |
| 102 | .expand_add_safe = true, | |
| 103 | .expand_sub_safe = true, | |
| 104 | .expand_mul_safe = true, | |
| 105 | }), | |
| 106 | }; | |
| 107 | } | |
| 39 | 108 | |
| 40 | 109 | /// Set this to `false` to uncover Sema OPV bugs. |
| 41 | 110 | /// https://github.com/ziglang/zig/issues/22419 |
| ... | ... | @@ -218,7 +287,7 @@ pub const MCValue = union(enum) { |
| 218 | 287 | /// Payload is a frame address. |
| 219 | 288 | lea_frame: bits.FrameAddr, |
| 220 | 289 | /// Supports integer_per_element abi |
| 221 | elementwise_regs_then_frame: packed struct { regs: u3, frame_off: i29, frame_index: FrameIndex }, | |
| 290 | elementwise_args: packed struct { regs: u3, frame_off: i29, frame_index: FrameIndex }, | |
| 222 | 291 | /// This indicates that we have already allocated a frame index for this instruction, |
| 223 | 292 | /// but it has not been spilled there yet in the current control flow. |
| 224 | 293 | /// Payload is a frame index. |
| ... | ... | @@ -240,7 +309,7 @@ pub const MCValue = union(enum) { |
| 240 | 309 | .lea_direct, |
| 241 | 310 | .lea_got, |
| 242 | 311 | .lea_frame, |
| 243 | .elementwise_regs_then_frame, | |
| 312 | .elementwise_args, | |
| 244 | 313 | .reserved_frame, |
| 245 | 314 | .air_ref, |
| 246 | 315 | => false, |
| ... | ... | @@ -355,7 +424,7 @@ pub const MCValue = union(enum) { |
| 355 | 424 | .lea_direct, |
| 356 | 425 | .lea_got, |
| 357 | 426 | .lea_frame, |
| 358 | .elementwise_regs_then_frame, | |
| 427 | .elementwise_args, | |
| 359 | 428 | .reserved_frame, |
| 360 | 429 | .air_ref, |
| 361 | 430 | => unreachable, // not in memory |
| ... | ... | @@ -389,7 +458,7 @@ pub const MCValue = union(enum) { |
| 389 | 458 | .load_got, |
| 390 | 459 | .load_frame, |
| 391 | 460 | .load_symbol, |
| 392 | .elementwise_regs_then_frame, | |
| 461 | .elementwise_args, | |
| 393 | 462 | .reserved_frame, |
| 394 | 463 | .air_ref, |
| 395 | 464 | => unreachable, // not dereferenceable |
| ... | ... | @@ -409,7 +478,7 @@ pub const MCValue = union(enum) { |
| 409 | 478 | .unreach, |
| 410 | 479 | .dead, |
| 411 | 480 | .undef, |
| 412 | .elementwise_regs_then_frame, | |
| 481 | .elementwise_args, | |
| 413 | 482 | .reserved_frame, |
| 414 | 483 | .air_ref, |
| 415 | 484 | => unreachable, // not valid |
| ... | ... | @@ -463,7 +532,7 @@ pub const MCValue = union(enum) { |
| 463 | 532 | .load_got, |
| 464 | 533 | .lea_got, |
| 465 | 534 | .lea_frame, |
| 466 | .elementwise_regs_then_frame, | |
| 535 | .elementwise_args, | |
| 467 | 536 | .reserved_frame, |
| 468 | 537 | .lea_symbol, |
| 469 | 538 | => unreachable, |
| ... | ... | @@ -547,7 +616,7 @@ pub const MCValue = union(enum) { |
| 547 | 616 | .load_got => |pl| try writer.print("[got:{d}]", .{pl}), |
| 548 | 617 | .lea_got => |pl| try writer.print("got:{d}", .{pl}), |
| 549 | 618 | .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }), |
| 550 | .elementwise_regs_then_frame => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{ | |
| 619 | .elementwise_args => |pl| try writer.print("elementwise:{d}:[{} + 0x{x}]", .{ | |
| 551 | 620 | pl.regs, pl.frame_index, pl.frame_off, |
| 552 | 621 | }), |
| 553 | 622 | .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }), |
| ... | ... | @@ -580,7 +649,7 @@ const InstTracking = struct { |
| 580 | 649 | .lea_symbol, |
| 581 | 650 | => result, |
| 582 | 651 | .dead, |
| 583 | .elementwise_regs_then_frame, | |
| 652 | .elementwise_args, | |
| 584 | 653 | .reserved_frame, |
| 585 | 654 | .air_ref, |
| 586 | 655 | => unreachable, |
| ... | ... | @@ -689,7 +758,7 @@ const InstTracking = struct { |
| 689 | 758 | .register_overflow, |
| 690 | 759 | .register_mask, |
| 691 | 760 | .indirect, |
| 692 | .elementwise_regs_then_frame, | |
| 761 | .elementwise_args, | |
| 693 | 762 | .air_ref, |
| 694 | 763 | => unreachable, |
| 695 | 764 | } |
| ... | ... | @@ -2239,11 +2308,17 @@ fn gen(self: *CodeGen) InnerError!void { |
| 2239 | 2308 | try self.genBody(self.air.getMainBody()); |
| 2240 | 2309 | |
| 2241 | 2310 | const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: { |
| 2242 | const epilogue_relocs_last_index = self.epilogue_relocs.items.len - 1; | |
| 2243 | for (if (self.epilogue_relocs.items[epilogue_relocs_last_index] == self.mir_instructions.len - 1) epilogue_relocs: { | |
| 2244 | _ = self.mir_instructions.pop(); | |
| 2245 | break :epilogue_relocs self.epilogue_relocs.items[0..epilogue_relocs_last_index]; | |
| 2246 | } else self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc); | |
| 2311 | var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1); | |
| 2312 | while (self.epilogue_relocs.getLastOrNull() == last_inst) { | |
| 2313 | self.epilogue_relocs.items.len -= 1; | |
| 2314 | self.mir_instructions.set(last_inst, .{ | |
| 2315 | .tag = .pseudo, | |
| 2316 | .ops = .pseudo_dead_none, | |
| 2317 | .data = undefined, | |
| 2318 | }); | |
| 2319 | last_inst -= 1; | |
| 2320 | } | |
| 2321 | for (self.epilogue_relocs.items) |epilogue_reloc| self.performReloc(epilogue_reloc); | |
| 2247 | 2322 | |
| 2248 | 2323 | if (self.debug_output != .none) try self.asmPseudo(.pseudo_dbg_epilogue_begin_none); |
| 2249 | 2324 | const backpatch_stack_dealloc = try self.asmPlaceholder(); |
| ... | ... | @@ -2430,7 +2505,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 2430 | 2505 | switch (air_tags[@intFromEnum(inst)]) { |
| 2431 | 2506 | // zig fmt: off |
| 2432 | 2507 | .select => try cg.airSelect(inst), |
| 2433 | .shuffle => try cg.airShuffle(inst), | |
| 2508 | .shuffle_one, .shuffle_two => @panic("x86_64 TODO: shuffle_one/shuffle_two"), | |
| 2434 | 2509 | // zig fmt: on |
| 2435 | 2510 | |
| 2436 | 2511 | .arg => if (cg.debug_output != .none) { |
| ... | ... | @@ -5714,7 +5789,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 5714 | 5789 | }, |
| 5715 | 5790 | .extra_temps = .{ |
| 5716 | 5791 | .{ .type = .i64, .kind = .{ .rc = .general_purpose } }, |
| 5717 | .{ .type = .i64, .kind = .{ .mut_rc = .{ .ref = .src1, .rc = .general_purpose } } }, | |
| 5792 | .{ .type = .i64, .kind = .{ .rc = .general_purpose } }, | |
| 5718 | 5793 | .unused, |
| 5719 | 5794 | .unused, |
| 5720 | 5795 | .unused, |
| ... | ... | @@ -63352,14 +63427,14 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 63352 | 63427 | defer assert(cg.loops.remove(inst)); |
| 63353 | 63428 | try cg.genBodyBlock(@ptrCast(cg.air.extra.items[block.end..][0..block.data.body_len])); |
| 63354 | 63429 | }, |
| 63355 | .repeat => if (use_old) try cg.airRepeat(inst) else { | |
| 63430 | .repeat => { | |
| 63356 | 63431 | const repeat = air_datas[@intFromEnum(inst)].repeat; |
| 63357 | 63432 | const loop = cg.loops.get(repeat.loop_inst).?; |
| 63358 | 63433 | try cg.restoreState(loop.state, &.{}, .{ |
| 63359 | 63434 | .emit_instructions = true, |
| 63360 | 63435 | .update_tracking = false, |
| 63361 | 63436 | .resurrect = false, |
| 63362 | .close_scope = true, | |
| 63437 | .close_scope = false, | |
| 63363 | 63438 | }); |
| 63364 | 63439 | _ = try cg.asmJmpReloc(loop.target); |
| 63365 | 63440 | }, |
| ... | ... | @@ -77234,11 +77309,27 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77234 | 77309 | }, |
| 77235 | 77310 | } |
| 77236 | 77311 | }, |
| 77237 | .int => res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err, | |
| 77312 | .int => { | |
| 77313 | switch (ty.zigTypeTag(zcu)) { | |
| 77314 | else => {}, | |
| 77315 | .@"struct", .@"union" => { | |
| 77316 | assert(ty.containerLayout(zcu) == .@"packed"); | |
| 77317 | for (&ops) |*op| op.wrapInt(cg) catch |err| switch (err) { | |
| 77318 | error.SelectFailed => return cg.fail("failed to select {s} wrap {} {}", .{ | |
| 77319 | @tagName(air_tag), | |
| 77320 | ty.fmt(pt), | |
| 77321 | op.tracking(cg), | |
| 77322 | }), | |
| 77323 | else => |e| return e, | |
| 77324 | }; | |
| 77325 | }, | |
| 77326 | } | |
| 77327 | res[0] = ops[0].cmpInts(cmp_op, &ops[1], cg) catch |err| break :err err; | |
| 77328 | }, | |
| 77238 | 77329 | }) catch |err| switch (err) { |
| 77239 | 77330 | error.SelectFailed => return cg.fail("failed to select {s} {} {} {}", .{ |
| 77240 | 77331 | @tagName(air_tag), |
| 77241 | cg.typeOf(bin_op.lhs).fmt(pt), | |
| 77332 | ty.fmt(pt), | |
| 77242 | 77333 | ops[0].tracking(cg), |
| 77243 | 77334 | ops[1].tracking(cg), |
| 77244 | 77335 | }), |
| ... | ... | @@ -92468,7 +92559,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 92468 | 92559 | .{ ._, ._, .lea, .tmp1p, .mem(.dst0), ._, ._ }, |
| 92469 | 92560 | .{ ._, ._, .mov, .tmp2d, .sia(-2, .dst0, .add_size_div_8), ._, ._ }, |
| 92470 | 92561 | .{ ._, .@"rep _sq", .mov, ._, ._, ._, ._ }, |
| 92471 | .{ ._, ._, .mov, .tmp0q, .memad(.src0q, .add_size, -16), ._, ._ }, | |
| 92562 | .{ ._, ._, .mov, .tmp0q, .memad(.src0q, .add_dst0_size, -16), ._, ._ }, | |
| 92472 | 92563 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -16), .tmp0q, ._, ._ }, |
| 92473 | 92564 | .{ ._, ._r, .sa, .tmp0q, .ui(63), ._, ._ }, |
| 92474 | 92565 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp0q, ._, ._ }, |
| ... | ... | @@ -92500,7 +92591,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 92500 | 92591 | .{ ._, ._, .lea, .tmp1p, .mem(.dst0), ._, ._ }, |
| 92501 | 92592 | .{ ._, ._, .mov, .tmp2d, .sia(-2, .dst0, .add_size_div_8), ._, ._ }, |
| 92502 | 92593 | .{ ._, .@"rep _sq", .mov, ._, ._, ._, ._ }, |
| 92503 | .{ ._, ._, .mov, .tmp0q, .memad(.src0q, .add_size, -16), ._, ._ }, | |
| 92594 | .{ ._, ._, .mov, .tmp0q, .memad(.src0q, .add_dst0_size, -16), ._, ._ }, | |
| 92504 | 92595 | .{ ._, ._l, .sa, .tmp0q, .uia(64, .dst0, .sub_bit_size_rem_64), ._, ._ }, |
| 92505 | 92596 | .{ ._, ._r, .sa, .tmp0q, .uia(64, .dst0, .sub_bit_size_rem_64), ._, ._ }, |
| 92506 | 92597 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -16), .tmp0q, ._, ._ }, |
| ... | ... | @@ -92534,7 +92625,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 92534 | 92625 | .{ ._, ._, .lea, .tmp1p, .mem(.dst0), ._, ._ }, |
| 92535 | 92626 | .{ ._, ._, .mov, .tmp2d, .sia(-1, .dst0, .add_size_div_8), ._, ._ }, |
| 92536 | 92627 | .{ ._, .@"rep _sq", .mov, ._, ._, ._, ._ }, |
| 92537 | .{ ._, ._, .mov, .tmp0q, .memad(.src0q, .add_size, -8), ._, ._ }, | |
| 92628 | .{ ._, ._, .mov, .tmp0q, .memad(.src0q, .add_dst0_size, -8), ._, ._ }, | |
| 92538 | 92629 | .{ ._, ._l, .sa, .tmp0q, .uia(64, .dst0, .sub_bit_size_rem_64), ._, ._ }, |
| 92539 | 92630 | .{ ._, ._r, .sa, .tmp0q, .uia(64, .dst0, .sub_bit_size_rem_64), ._, ._ }, |
| 92540 | 92631 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp0q, ._, ._ }, |
| ... | ... | @@ -92595,7 +92686,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 92595 | 92686 | .{ ._, ._, .mov, .tmp2d, .sia(-2, .dst0, .add_size_div_8), ._, ._ }, |
| 92596 | 92687 | .{ ._, .@"rep _sq", .mov, ._, ._, ._, ._ }, |
| 92597 | 92688 | .{ ._, ._, .mov, .tmp2d, .sa(.dst0, .add_bit_size_rem_64), ._, ._ }, |
| 92598 | .{ ._, ._, .bzhi, .tmp2q, .memad(.src0q, .add_size, -16), .tmp2q, ._ }, | |
| 92689 | .{ ._, ._, .bzhi, .tmp2q, .memad(.src0q, .add_dst0_size, -16), .tmp2q, ._ }, | |
| 92599 | 92690 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -16), .tmp2q, ._, ._ }, |
| 92600 | 92691 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .si(0), ._, ._ }, |
| 92601 | 92692 | } }, |
| ... | ... | @@ -92627,7 +92718,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 92627 | 92718 | .{ ._, ._, .mov, .tmp2d, .sia(-1, .dst0, .add_size_div_8), ._, ._ }, |
| 92628 | 92719 | .{ ._, .@"rep _sq", .mov, ._, ._, ._, ._ }, |
| 92629 | 92720 | .{ ._, ._, .mov, .tmp2d, .sa(.dst0, .add_bit_size_rem_64), ._, ._ }, |
| 92630 | .{ ._, ._, .bzhi, .tmp2q, .memad(.src0q, .add_size, -8), .tmp2q, ._ }, | |
| 92721 | .{ ._, ._, .bzhi, .tmp2q, .memad(.src0q, .add_dst0_size, -8), .tmp2q, ._ }, | |
| 92631 | 92722 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp2q, ._, ._ }, |
| 92632 | 92723 | } }, |
| 92633 | 92724 | }, .{ |
| ... | ... | @@ -92658,7 +92749,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 92658 | 92749 | .{ ._, ._, .mov, .tmp2d, .sia(-2, .dst0, .add_size_div_8), ._, ._ }, |
| 92659 | 92750 | .{ ._, .@"rep _sq", .mov, ._, ._, ._, ._ }, |
| 92660 | 92751 | .{ ._, ._, .mov, .tmp0q, .ua(.dst0, .add_umax), ._, ._ }, |
| 92661 | .{ ._, ._, .@"and", .tmp0q, .memad(.src0q, .add_size, -16), ._, ._ }, | |
| 92752 | .{ ._, ._, .@"and", .tmp0q, .memad(.src0q, .add_dst0_size, -16), ._, ._ }, | |
| 92662 | 92753 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -16), .tmp0q, ._, ._ }, |
| 92663 | 92754 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .si(0), ._, ._ }, |
| 92664 | 92755 | } }, |
| ... | ... | @@ -92690,7 +92781,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 92690 | 92781 | .{ ._, ._, .mov, .tmp2d, .sia(-1, .dst0, .add_size_div_8), ._, ._ }, |
| 92691 | 92782 | .{ ._, .@"rep _sq", .mov, ._, ._, ._, ._ }, |
| 92692 | 92783 | .{ ._, ._, .mov, .tmp0q, .ua(.dst0, .add_umax), ._, ._ }, |
| 92693 | .{ ._, ._, .@"and", .tmp0q, .memad(.src0q, .add_size, -8), ._, ._ }, | |
| 92784 | .{ ._, ._, .@"and", .tmp0q, .memad(.src0q, .add_dst0_size, -8), ._, ._ }, | |
| 92694 | 92785 | .{ ._, ._, .mov, .memad(.dst0q, .add_size, -8), .tmp0q, ._, ._ }, |
| 92695 | 92786 | } }, |
| 92696 | 92787 | }, .{ |
| ... | ... | @@ -162356,6 +162447,136 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 162356 | 162447 | .each = .{ .once = &.{ |
| 162357 | 162448 | .{ ._, ._, .mov, .leasi(.src0w, .@"2", .src1), .src2w, ._, ._ }, |
| 162358 | 162449 | } }, |
| 162450 | }, .{ | |
| 162451 | .required_features = .{ .avx, null, null, null }, | |
| 162452 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162453 | .patterns = &.{ | |
| 162454 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162455 | }, | |
| 162456 | .each = .{ .once = &.{ | |
| 162457 | .{ ._, .vp_w, .extr, .leaa(.src0w, .add_src0_elem_size_mul_src1), .src2x, .ui(0), ._ }, | |
| 162458 | } }, | |
| 162459 | }, .{ | |
| 162460 | .required_features = .{ .sse4_1, null, null, null }, | |
| 162461 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162462 | .patterns = &.{ | |
| 162463 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162464 | }, | |
| 162465 | .each = .{ .once = &.{ | |
| 162466 | .{ ._, .p_w, .extr, .leaa(.src0w, .add_src0_elem_size_mul_src1), .src2x, .ui(0), ._ }, | |
| 162467 | } }, | |
| 162468 | }, .{ | |
| 162469 | .required_features = .{ .sse2, null, null, null }, | |
| 162470 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162471 | .patterns = &.{ | |
| 162472 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162473 | }, | |
| 162474 | .extra_temps = .{ | |
| 162475 | .{ .type = .f16, .kind = .{ .rc = .general_purpose } }, | |
| 162476 | .unused, | |
| 162477 | .unused, | |
| 162478 | .unused, | |
| 162479 | .unused, | |
| 162480 | .unused, | |
| 162481 | .unused, | |
| 162482 | .unused, | |
| 162483 | .unused, | |
| 162484 | .unused, | |
| 162485 | .unused, | |
| 162486 | }, | |
| 162487 | .each = .{ .once = &.{ | |
| 162488 | .{ ._, .p_w, .extr, .tmp0d, .src2x, .ui(0), ._ }, | |
| 162489 | .{ ._, ._, .mov, .leaa(.src0w, .add_src0_elem_size_mul_src1), .tmp0w, ._, ._ }, | |
| 162490 | } }, | |
| 162491 | }, .{ | |
| 162492 | .required_features = .{ .sse, null, null, null }, | |
| 162493 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162494 | .patterns = &.{ | |
| 162495 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162496 | }, | |
| 162497 | .extra_temps = .{ | |
| 162498 | .{ .type = .f32, .kind = .mem }, | |
| 162499 | .{ .type = .f16, .kind = .{ .rc = .general_purpose } }, | |
| 162500 | .unused, | |
| 162501 | .unused, | |
| 162502 | .unused, | |
| 162503 | .unused, | |
| 162504 | .unused, | |
| 162505 | .unused, | |
| 162506 | .unused, | |
| 162507 | .unused, | |
| 162508 | .unused, | |
| 162509 | }, | |
| 162510 | .each = .{ .once = &.{ | |
| 162511 | .{ ._, ._ss, .mov, .mem(.tmp1d), .src2x, ._, ._ }, | |
| 162512 | .{ ._, ._, .mov, .tmp1d, .mem(.tmp1d), ._, ._ }, | |
| 162513 | .{ ._, ._, .mov, .leaa(.src0w, .add_src0_elem_size_mul_src1), .tmp1w, ._, ._ }, | |
| 162514 | } }, | |
| 162515 | }, .{ | |
| 162516 | .required_features = .{ .avx, null, null, null }, | |
| 162517 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162518 | .patterns = &.{ | |
| 162519 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162520 | }, | |
| 162521 | .each = .{ .once = &.{ | |
| 162522 | .{ ._, .vp_w, .extr, .leasi(.src0w, .@"2", .src1), .src2x, .ui(0), ._ }, | |
| 162523 | } }, | |
| 162524 | }, .{ | |
| 162525 | .required_features = .{ .sse4_1, null, null, null }, | |
| 162526 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162527 | .patterns = &.{ | |
| 162528 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162529 | }, | |
| 162530 | .each = .{ .once = &.{ | |
| 162531 | .{ ._, .p_w, .extr, .leasi(.src0w, .@"2", .src1), .src2x, .ui(0), ._ }, | |
| 162532 | } }, | |
| 162533 | }, .{ | |
| 162534 | .required_features = .{ .sse2, null, null, null }, | |
| 162535 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162536 | .patterns = &.{ | |
| 162537 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162538 | }, | |
| 162539 | .extra_temps = .{ | |
| 162540 | .{ .type = .f16, .kind = .{ .rc = .general_purpose } }, | |
| 162541 | .unused, | |
| 162542 | .unused, | |
| 162543 | .unused, | |
| 162544 | .unused, | |
| 162545 | .unused, | |
| 162546 | .unused, | |
| 162547 | .unused, | |
| 162548 | .unused, | |
| 162549 | .unused, | |
| 162550 | .unused, | |
| 162551 | }, | |
| 162552 | .each = .{ .once = &.{ | |
| 162553 | .{ ._, .p_w, .extr, .tmp0d, .src2x, .ui(0), ._ }, | |
| 162554 | .{ ._, ._, .mov, .leasi(.src0w, .@"2", .src1), .tmp0w, ._, ._ }, | |
| 162555 | } }, | |
| 162556 | }, .{ | |
| 162557 | .required_features = .{ .sse, null, null, null }, | |
| 162558 | .src_constraints = .{ .any, .any, .{ .float = .word } }, | |
| 162559 | .patterns = &.{ | |
| 162560 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162561 | }, | |
| 162562 | .extra_temps = .{ | |
| 162563 | .{ .type = .f32, .kind = .mem }, | |
| 162564 | .{ .type = .f16, .kind = .{ .rc = .general_purpose } }, | |
| 162565 | .unused, | |
| 162566 | .unused, | |
| 162567 | .unused, | |
| 162568 | .unused, | |
| 162569 | .unused, | |
| 162570 | .unused, | |
| 162571 | .unused, | |
| 162572 | .unused, | |
| 162573 | .unused, | |
| 162574 | }, | |
| 162575 | .each = .{ .once = &.{ | |
| 162576 | .{ ._, ._ss, .mov, .mem(.tmp1d), .src2x, ._, ._ }, | |
| 162577 | .{ ._, ._, .mov, .tmp1d, .mem(.tmp1d), ._, ._ }, | |
| 162578 | .{ ._, ._, .mov, .leasi(.src0w, .@"2", .src1), .tmp1w, ._, ._ }, | |
| 162579 | } }, | |
| 162359 | 162580 | }, .{ |
| 162360 | 162581 | .src_constraints = .{ .any, .any, .{ .int = .dword } }, |
| 162361 | 162582 | .patterns = &.{ |
| ... | ... | @@ -162374,30 +162595,120 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 162374 | 162595 | .each = .{ .once = &.{ |
| 162375 | 162596 | .{ ._, ._, .mov, .leasi(.src0d, .@"4", .src1), .src2d, ._, ._ }, |
| 162376 | 162597 | } }, |
| 162598 | }, .{ | |
| 162599 | .required_features = .{ .avx, null, null, null }, | |
| 162600 | .src_constraints = .{ .any, .any, .{ .float = .dword } }, | |
| 162601 | .patterns = &.{ | |
| 162602 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162603 | }, | |
| 162604 | .each = .{ .once = &.{ | |
| 162605 | .{ ._, .v_ss, .mov, .leaa(.src0d, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162606 | } }, | |
| 162607 | }, .{ | |
| 162608 | .required_features = .{ .sse, null, null, null }, | |
| 162609 | .src_constraints = .{ .any, .any, .{ .float = .dword } }, | |
| 162610 | .patterns = &.{ | |
| 162611 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162612 | }, | |
| 162613 | .each = .{ .once = &.{ | |
| 162614 | .{ ._, ._ss, .mov, .leaa(.src0d, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162615 | } }, | |
| 162616 | }, .{ | |
| 162617 | .required_features = .{ .avx, null, null, null }, | |
| 162618 | .src_constraints = .{ .any, .any, .{ .float = .dword } }, | |
| 162619 | .patterns = &.{ | |
| 162620 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162621 | }, | |
| 162622 | .each = .{ .once = &.{ | |
| 162623 | .{ ._, .v_ss, .mov, .leasi(.src0d, .@"4", .src1), .src2x, ._, ._ }, | |
| 162624 | } }, | |
| 162625 | }, .{ | |
| 162626 | .required_features = .{ .sse, null, null, null }, | |
| 162627 | .src_constraints = .{ .any, .any, .{ .float = .dword } }, | |
| 162628 | .patterns = &.{ | |
| 162629 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162630 | }, | |
| 162631 | .each = .{ .once = &.{ | |
| 162632 | .{ ._, ._ss, .mov, .leasi(.src0d, .@"4", .src1), .src2x, ._, ._ }, | |
| 162633 | } }, | |
| 162377 | 162634 | }, .{ |
| 162378 | 162635 | .required_features = .{ .@"64bit", null, null, null }, |
| 162379 | .dst_constraints = .{ .{ .int = .qword }, .any }, | |
| 162636 | .src_constraints = .{ .any, .any, .{ .int = .qword } }, | |
| 162380 | 162637 | .patterns = &.{ |
| 162381 | .{ .src = .{ .to_mem, .simm32, .simm32 } }, | |
| 162382 | .{ .src = .{ .to_mem, .simm32, .to_gpr } }, | |
| 162638 | .{ .src = .{ .to_gpr, .simm32, .simm32 } }, | |
| 162639 | .{ .src = .{ .to_gpr, .simm32, .to_gpr } }, | |
| 162383 | 162640 | }, |
| 162384 | 162641 | .each = .{ .once = &.{ |
| 162385 | 162642 | .{ ._, ._, .mov, .leaa(.src0q, .add_src0_elem_size_mul_src1), .src2q, ._, ._ }, |
| 162386 | 162643 | } }, |
| 162387 | 162644 | }, .{ |
| 162388 | 162645 | .required_features = .{ .@"64bit", null, null, null }, |
| 162389 | .dst_constraints = .{ .{ .int = .qword }, .any }, | |
| 162646 | .src_constraints = .{ .any, .any, .{ .int = .qword } }, | |
| 162390 | 162647 | .patterns = &.{ |
| 162391 | .{ .src = .{ .to_mem, .to_gpr, .simm32 } }, | |
| 162392 | .{ .src = .{ .to_mem, .to_gpr, .to_gpr } }, | |
| 162648 | .{ .src = .{ .to_gpr, .to_gpr, .simm32 } }, | |
| 162649 | .{ .src = .{ .to_gpr, .to_gpr, .to_gpr } }, | |
| 162393 | 162650 | }, |
| 162394 | 162651 | .each = .{ .once = &.{ |
| 162395 | 162652 | .{ ._, ._, .mov, .leasi(.src0q, .@"8", .src1), .src2q, ._, ._ }, |
| 162396 | 162653 | } }, |
| 162654 | }, .{ | |
| 162655 | .required_features = .{ .avx, null, null, null }, | |
| 162656 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162657 | .patterns = &.{ | |
| 162658 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162659 | }, | |
| 162660 | .each = .{ .once = &.{ | |
| 162661 | .{ ._, .v_sd, .mov, .leaa(.src0q, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162662 | } }, | |
| 162663 | }, .{ | |
| 162664 | .required_features = .{ .sse2, null, null, null }, | |
| 162665 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162666 | .patterns = &.{ | |
| 162667 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162668 | }, | |
| 162669 | .each = .{ .once = &.{ | |
| 162670 | .{ ._, ._sd, .mov, .leaa(.src0q, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162671 | } }, | |
| 162672 | }, .{ | |
| 162673 | .required_features = .{ .sse, null, null, null }, | |
| 162674 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162675 | .patterns = &.{ | |
| 162676 | .{ .src = .{ .to_gpr, .simm32, .to_sse } }, | |
| 162677 | }, | |
| 162678 | .each = .{ .once = &.{ | |
| 162679 | .{ ._, ._ps, .movl, .leaa(.src0q, .add_src0_elem_size_mul_src1), .src2x, ._, ._ }, | |
| 162680 | } }, | |
| 162681 | }, .{ | |
| 162682 | .required_features = .{ .avx, null, null, null }, | |
| 162683 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162684 | .patterns = &.{ | |
| 162685 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162686 | }, | |
| 162687 | .each = .{ .once = &.{ | |
| 162688 | .{ ._, .v_sd, .mov, .leasi(.src0q, .@"8", .src1), .src2x, ._, ._ }, | |
| 162689 | } }, | |
| 162690 | }, .{ | |
| 162691 | .required_features = .{ .sse2, null, null, null }, | |
| 162692 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162693 | .patterns = &.{ | |
| 162694 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162695 | }, | |
| 162696 | .each = .{ .once = &.{ | |
| 162697 | .{ ._, ._sd, .mov, .leasi(.src0q, .@"8", .src1), .src2x, ._, ._ }, | |
| 162698 | } }, | |
| 162699 | }, .{ | |
| 162700 | .required_features = .{ .sse, null, null, null }, | |
| 162701 | .src_constraints = .{ .any, .any, .{ .float = .qword } }, | |
| 162702 | .patterns = &.{ | |
| 162703 | .{ .src = .{ .to_gpr, .to_gpr, .to_sse } }, | |
| 162704 | }, | |
| 162705 | .each = .{ .once = &.{ | |
| 162706 | .{ ._, ._ps, .movl, .leasi(.src0q, .@"8", .src1), .src2x, ._, ._ }, | |
| 162707 | } }, | |
| 162397 | 162708 | } }) catch |err| switch (err) { |
| 162398 | 162709 | error.SelectFailed => { |
| 162399 | 162710 | const elem_size = cg.typeOf(bin_op.rhs).abiSize(zcu); |
| 162400 | while (try ops[0].toBase(false, cg) or | |
| 162711 | while (try ops[0].toRegClass(true, .general_purpose, cg) or | |
| 162401 | 162712 | try ops[1].toRegClass(true, .general_purpose, cg)) |
| 162402 | 162713 | {} |
| 162403 | 162714 | const base_reg = ops[0].tracking(cg).short.register.to64(); |
| ... | ... | @@ -162410,11 +162721,10 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 162410 | 162721 | rhs_reg, |
| 162411 | 162722 | .u(elem_size), |
| 162412 | 162723 | ); |
| 162413 | try cg.asmRegisterMemory( | |
| 162414 | .{ ._, .lea }, | |
| 162415 | base_reg, | |
| 162416 | try ops[0].tracking(cg).short.mem(cg, .{ .index = rhs_reg }), | |
| 162417 | ); | |
| 162724 | try cg.asmRegisterMemory(.{ ._, .lea }, base_reg, .{ | |
| 162725 | .base = .{ .reg = base_reg }, | |
| 162726 | .mod = .{ .rm = .{ .index = rhs_reg } }, | |
| 162727 | }); | |
| 162418 | 162728 | } else if (elem_size > 8) { |
| 162419 | 162729 | try cg.spillEflagsIfOccupied(); |
| 162420 | 162730 | try cg.asmRegisterImmediate( |
| ... | ... | @@ -162422,20 +162732,18 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 162422 | 162732 | rhs_reg, |
| 162423 | 162733 | .u(std.math.log2_int(u64, elem_size)), |
| 162424 | 162734 | ); |
| 162425 | try cg.asmRegisterMemory( | |
| 162426 | .{ ._, .lea }, | |
| 162427 | base_reg, | |
| 162428 | try ops[0].tracking(cg).short.mem(cg, .{ .index = rhs_reg }), | |
| 162429 | ); | |
| 162430 | } else try cg.asmRegisterMemory( | |
| 162431 | .{ ._, .lea }, | |
| 162432 | base_reg, | |
| 162433 | try ops[0].tracking(cg).short.mem(cg, .{ | |
| 162735 | try cg.asmRegisterMemory(.{ ._, .lea }, base_reg, .{ | |
| 162736 | .base = .{ .reg = base_reg }, | |
| 162737 | .mod = .{ .rm = .{ .index = rhs_reg } }, | |
| 162738 | }); | |
| 162739 | } else try cg.asmRegisterMemory(.{ ._, .lea }, base_reg, .{ | |
| 162740 | .base = .{ .reg = base_reg }, | |
| 162741 | .mod = .{ .rm = .{ | |
| 162434 | 162742 | .index = rhs_reg, |
| 162435 | 162743 | .scale = .fromFactor(@intCast(elem_size)), |
| 162436 | }), | |
| 162437 | ); | |
| 162438 | try ops[0].store(&ops[1], .{}, cg); | |
| 162744 | } }, | |
| 162745 | }); | |
| 162746 | try ops[0].store(&ops[2], .{}, cg); | |
| 162439 | 162747 | }, |
| 162440 | 162748 | else => |e| return e, |
| 162441 | 162749 | }; |
| ... | ... | @@ -165315,9 +165623,7 @@ fn airShlShrBinOp(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 165315 | 165623 | .ty = mask_ty.toIntern(), |
| 165316 | 165624 | .storage = .{ .elems = &([1]InternPool.Index{ |
| 165317 | 165625 | (try rhs_ty.childType(zcu).maxIntScalar(pt, .u8)).toIntern(), |
| 165318 | } ++ [1]InternPool.Index{ | |
| 165319 | (try pt.intValue(.u8, 0)).toIntern(), | |
| 165320 | } ** 15) }, | |
| 165626 | } ++ [1]InternPool.Index{.zero_u8} ** 15) }, | |
| 165321 | 165627 | } }))); |
| 165322 | 165628 | const mask_addr_reg = try self.copyToTmpRegister(.usize, mask_mcv.address()); |
| 165323 | 165629 | const mask_addr_lock = self.register_manager.lockRegAssumeUnused(mask_addr_reg); |
| ... | ... | @@ -168138,7 +168444,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE |
| 168138 | 168444 | .register_quadruple, |
| 168139 | 168445 | .register_overflow, |
| 168140 | 168446 | .register_mask, |
| 168141 | .elementwise_regs_then_frame, | |
| 168447 | .elementwise_args, | |
| 168142 | 168448 | .reserved_frame, |
| 168143 | 168449 | => unreachable, // not a valid pointer |
| 168144 | 168450 | .immediate, |
| ... | ... | @@ -168356,7 +168662,7 @@ fn store( |
| 168356 | 168662 | .register_quadruple, |
| 168357 | 168663 | .register_overflow, |
| 168358 | 168664 | .register_mask, |
| 168359 | .elementwise_regs_then_frame, | |
| 168665 | .elementwise_args, | |
| 168360 | 168666 | .reserved_frame, |
| 168361 | 168667 | => unreachable, // not a valid pointer |
| 168362 | 168668 | .immediate, |
| ... | ... | @@ -168842,7 +169148,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: |
| 168842 | 169148 | .lea_direct, |
| 168843 | 169149 | .lea_got, |
| 168844 | 169150 | .lea_frame, |
| 168845 | .elementwise_regs_then_frame, | |
| 169151 | .elementwise_args, | |
| 168846 | 169152 | .reserved_frame, |
| 168847 | 169153 | .air_ref, |
| 168848 | 169154 | => unreachable, // unmodifiable destination |
| ... | ... | @@ -170513,7 +170819,7 @@ fn genBinOp( |
| 170513 | 170819 | .load_got, |
| 170514 | 170820 | .lea_got, |
| 170515 | 170821 | .lea_frame, |
| 170516 | .elementwise_regs_then_frame, | |
| 170822 | .elementwise_args, | |
| 170517 | 170823 | .reserved_frame, |
| 170518 | 170824 | .air_ref, |
| 170519 | 170825 | => unreachable, |
| ... | ... | @@ -171696,7 +172002,7 @@ fn genBinOpMir( |
| 171696 | 172002 | .lea_got, |
| 171697 | 172003 | .lea_frame, |
| 171698 | 172004 | .lea_symbol, |
| 171699 | .elementwise_regs_then_frame, | |
| 172005 | .elementwise_args, | |
| 171700 | 172006 | .reserved_frame, |
| 171701 | 172007 | .air_ref, |
| 171702 | 172008 | => unreachable, // unmodifiable destination |
| ... | ... | @@ -171732,7 +172038,7 @@ fn genBinOpMir( |
| 171732 | 172038 | .undef, |
| 171733 | 172039 | .register_overflow, |
| 171734 | 172040 | .register_mask, |
| 171735 | .elementwise_regs_then_frame, | |
| 172041 | .elementwise_args, | |
| 171736 | 172042 | .reserved_frame, |
| 171737 | 172043 | => unreachable, |
| 171738 | 172044 | .register, |
| ... | ... | @@ -171892,7 +172198,7 @@ fn genBinOpMir( |
| 171892 | 172198 | .undef, |
| 171893 | 172199 | .register_overflow, |
| 171894 | 172200 | .register_mask, |
| 171895 | .elementwise_regs_then_frame, | |
| 172201 | .elementwise_args, | |
| 171896 | 172202 | .reserved_frame, |
| 171897 | 172203 | .air_ref, |
| 171898 | 172204 | => unreachable, |
| ... | ... | @@ -171988,7 +172294,7 @@ fn genBinOpMir( |
| 171988 | 172294 | .undef, |
| 171989 | 172295 | .register_overflow, |
| 171990 | 172296 | .register_mask, |
| 171991 | .elementwise_regs_then_frame, | |
| 172297 | .elementwise_args, | |
| 171992 | 172298 | .reserved_frame, |
| 171993 | 172299 | .air_ref, |
| 171994 | 172300 | => unreachable, |
| ... | ... | @@ -172119,7 +172425,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 172119 | 172425 | .lea_direct, |
| 172120 | 172426 | .lea_got, |
| 172121 | 172427 | .lea_frame, |
| 172122 | .elementwise_regs_then_frame, | |
| 172428 | .elementwise_args, | |
| 172123 | 172429 | .reserved_frame, |
| 172124 | 172430 | .air_ref, |
| 172125 | 172431 | => unreachable, // unmodifiable destination |
| ... | ... | @@ -172151,7 +172457,7 @@ fn genIntMulComplexOpMir(self: *CodeGen, dst_ty: Type, dst_mcv: MCValue, src_mcv |
| 172151 | 172457 | .register_quadruple, |
| 172152 | 172458 | .register_overflow, |
| 172153 | 172459 | .register_mask, |
| 172154 | .elementwise_regs_then_frame, | |
| 172460 | .elementwise_args, | |
| 172155 | 172461 | .reserved_frame, |
| 172156 | 172462 | .air_ref, |
| 172157 | 172463 | => unreachable, |
| ... | ... | @@ -172271,7 +172577,7 @@ fn airArg(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 172271 | 172577 | try self.genCopy(arg_ty, dst_mcv, src_mcv, .{}); |
| 172272 | 172578 | break :result dst_mcv; |
| 172273 | 172579 | }, |
| 172274 | .elementwise_regs_then_frame => |regs_frame_addr| { | |
| 172580 | .elementwise_args => |regs_frame_addr| { | |
| 172275 | 172581 | try self.spillEflagsIfOccupied(); |
| 172276 | 172582 | |
| 172277 | 172583 | const fn_info = zcu.typeToFunc(self.fn_type).?; |
| ... | ... | @@ -172375,7 +172681,7 @@ fn genLocalDebugInfo( |
| 172375 | 172681 | .arg, .dbg_arg_inline, .dbg_var_val => |tag| { |
| 172376 | 172682 | switch (mcv) { |
| 172377 | 172683 | .none => try self.asmAir(.dbg_local, inst), |
| 172378 | .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable, | |
| 172684 | .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable, | |
| 172379 | 172685 | .immediate => |imm| try self.asmAirImmediate(.dbg_local, inst, .u(imm)), |
| 172380 | 172686 | .lea_frame => |frame_addr| try self.asmAirFrameAddress(.dbg_local, inst, frame_addr), |
| 172381 | 172687 | .lea_symbol => |sym_off| try self.asmAirImmediate(.dbg_local, inst, .rel(sym_off)), |
| ... | ... | @@ -172398,7 +172704,7 @@ fn genLocalDebugInfo( |
| 172398 | 172704 | }, |
| 172399 | 172705 | .dbg_var_ptr => switch (mcv) { |
| 172400 | 172706 | else => unreachable, |
| 172401 | .unreach, .dead, .elementwise_regs_then_frame, .reserved_frame, .air_ref => unreachable, | |
| 172707 | .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable, | |
| 172402 | 172708 | .lea_frame => |frame_addr| try self.asmAirMemory(.dbg_local, inst, .{ |
| 172403 | 172709 | .base = .{ .frame = frame_addr.index }, |
| 172404 | 172710 | .mod = .{ .rm = .{ |
| ... | ... | @@ -172567,7 +172873,7 @@ fn genCall(self: *CodeGen, info: union(enum) { |
| 172567 | 172873 | try self.genCopy(arg_ty, dst_arg, src_arg, opts); |
| 172568 | 172874 | try self.freeValue(src_arg); |
| 172569 | 172875 | }, |
| 172570 | .elementwise_regs_then_frame => |regs_frame_addr| { | |
| 172876 | .elementwise_args => |regs_frame_addr| { | |
| 172571 | 172877 | const index_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 172572 | 172878 | const index_lock = self.register_manager.lockRegAssumeUnused(index_reg); |
| 172573 | 172879 | defer self.register_manager.unlockReg(index_lock); |
| ... | ... | @@ -172676,7 +172982,7 @@ fn genCall(self: *CodeGen, info: union(enum) { |
| 172676 | 172982 | .indirect => |reg_off| try self.genSetReg(reg_off.reg, .usize, .{ |
| 172677 | 172983 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| 172678 | 172984 | }, .{}), |
| 172679 | .elementwise_regs_then_frame => |regs_frame_addr| { | |
| 172985 | .elementwise_args => |regs_frame_addr| { | |
| 172680 | 172986 | const src_mem: Memory = if (src_arg.isBase()) try src_arg.mem(self, .{ .size = .dword }) else .{ |
| 172681 | 172987 | .base = .{ .reg = try self.copyToTmpRegister( |
| 172682 | 172988 | .usize, |
| ... | ... | @@ -173064,7 +173370,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 173064 | 173370 | .lea_got, |
| 173065 | 173371 | .lea_frame, |
| 173066 | 173372 | .lea_symbol, |
| 173067 | .elementwise_regs_then_frame, | |
| 173373 | .elementwise_args, | |
| 173068 | 173374 | .reserved_frame, |
| 173069 | 173375 | .air_ref, |
| 173070 | 173376 | => unreachable, |
| ... | ... | @@ -173119,7 +173425,7 @@ fn airCmp(self: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) !v |
| 173119 | 173425 | .lea_direct, |
| 173120 | 173426 | .lea_got, |
| 173121 | 173427 | .lea_frame, |
| 173122 | .elementwise_regs_then_frame, | |
| 173428 | .elementwise_args, | |
| 173123 | 173429 | .reserved_frame, |
| 173124 | 173430 | .air_ref, |
| 173125 | 173431 | => unreachable, |
| ... | ... | @@ -173524,7 +173830,7 @@ fn isNull(self: *CodeGen, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) |
| 173524 | 173830 | .lea_direct, |
| 173525 | 173831 | .lea_got, |
| 173526 | 173832 | .lea_symbol, |
| 173527 | .elementwise_regs_then_frame, | |
| 173833 | .elementwise_args, | |
| 173528 | 173834 | .reserved_frame, |
| 173529 | 173835 | .air_ref, |
| 173530 | 173836 | => unreachable, |
| ... | ... | @@ -173868,17 +174174,23 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index |
| 173868 | 174174 | var block_data = self.blocks.fetchRemove(inst).?; |
| 173869 | 174175 | defer block_data.value.deinit(self.gpa); |
| 173870 | 174176 | if (block_data.value.relocs.items.len > 0) { |
| 174177 | var last_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len - 1); | |
| 174178 | while (block_data.value.relocs.getLastOrNull() == last_inst) { | |
| 174179 | block_data.value.relocs.items.len -= 1; | |
| 174180 | self.mir_instructions.set(last_inst, .{ | |
| 174181 | .tag = .pseudo, | |
| 174182 | .ops = .pseudo_dead_none, | |
| 174183 | .data = undefined, | |
| 174184 | }); | |
| 174185 | last_inst -= 1; | |
| 174186 | } | |
| 174187 | for (block_data.value.relocs.items) |block_reloc| self.performReloc(block_reloc); | |
| 173871 | 174188 | try self.restoreState(block_data.value.state, liveness.deaths, .{ |
| 173872 | 174189 | .emit_instructions = false, |
| 173873 | 174190 | .update_tracking = true, |
| 173874 | 174191 | .resurrect = true, |
| 173875 | 174192 | .close_scope = true, |
| 173876 | 174193 | }); |
| 173877 | const block_relocs_last_index = block_data.value.relocs.items.len - 1; | |
| 173878 | for (if (block_data.value.relocs.items[block_relocs_last_index] == self.mir_instructions.len - 1) block_relocs: { | |
| 173879 | _ = self.mir_instructions.pop(); | |
| 173880 | break :block_relocs block_data.value.relocs.items[0..block_relocs_last_index]; | |
| 173881 | } else block_data.value.relocs.items) |block_reloc| self.performReloc(block_reloc); | |
| 173882 | 174194 | } |
| 173883 | 174195 | |
| 173884 | 174196 | if (std.debug.runtime_safety) assert(self.inst_tracking.getIndex(inst).? == inst_tracking_i); |
| ... | ... | @@ -174453,18 +174765,6 @@ fn airBr(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 174453 | 174765 | try self.freeValue(block_tracking.short); |
| 174454 | 174766 | } |
| 174455 | 174767 | |
| 174456 | fn airRepeat(self: *CodeGen, inst: Air.Inst.Index) !void { | |
| 174457 | const loop_inst = self.air.instructions.items(.data)[@intFromEnum(inst)].repeat.loop_inst; | |
| 174458 | const repeat_info = self.loops.get(loop_inst).?; | |
| 174459 | try self.restoreState(repeat_info.state, &.{}, .{ | |
| 174460 | .emit_instructions = true, | |
| 174461 | .update_tracking = false, | |
| 174462 | .resurrect = false, | |
| 174463 | .close_scope = true, | |
| 174464 | }); | |
| 174465 | _ = try self.asmJmpReloc(repeat_info.target); | |
| 174466 | } | |
| 174467 | ||
| 174468 | 174768 | fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 174469 | 174769 | @setEvalBranchQuota(1_100); |
| 174470 | 174770 | const pt = self.pt; |
| ... | ... | @@ -175587,7 +175887,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 175587 | 175887 | .lea_got, |
| 175588 | 175888 | .lea_frame, |
| 175589 | 175889 | .lea_symbol, |
| 175590 | .elementwise_regs_then_frame, | |
| 175890 | .elementwise_args, | |
| 175591 | 175891 | .reserved_frame, |
| 175592 | 175892 | .air_ref, |
| 175593 | 175893 | => unreachable, // unmodifiable destination |
| ... | ... | @@ -175598,7 +175898,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 175598 | 175898 | .dead, |
| 175599 | 175899 | .undef, |
| 175600 | 175900 | .register_overflow, |
| 175601 | .elementwise_regs_then_frame, | |
| 175901 | .elementwise_args, | |
| 175602 | 175902 | .reserved_frame, |
| 175603 | 175903 | => unreachable, |
| 175604 | 175904 | .immediate, |
| ... | ... | @@ -175776,7 +176076,7 @@ fn genSetReg( |
| 175776 | 176076 | .none, |
| 175777 | 176077 | .unreach, |
| 175778 | 176078 | .dead, |
| 175779 | .elementwise_regs_then_frame, | |
| 176079 | .elementwise_args, | |
| 175780 | 176080 | .reserved_frame, |
| 175781 | 176081 | => unreachable, |
| 175782 | 176082 | .undef => if (opts.safety) switch (dst_reg.class()) { |
| ... | ... | @@ -176313,7 +176613,7 @@ fn genSetMem( |
| 176313 | 176613 | .none, |
| 176314 | 176614 | .unreach, |
| 176315 | 176615 | .dead, |
| 176316 | .elementwise_regs_then_frame, | |
| 176616 | .elementwise_args, | |
| 176317 | 176617 | .reserved_frame, |
| 176318 | 176618 | => unreachable, |
| 176319 | 176619 | .undef => if (opts.safety) try self.genInlineMemset( |
| ... | ... | @@ -178566,10 +178866,10 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 178566 | 178866 | const mask_ty = try pt.vectorType(.{ .len = vec_len, .child = mask_elem_ty.toIntern() }); |
| 178567 | 178867 | var mask_elems_buf: [32]InternPool.Index = undefined; |
| 178568 | 178868 | const mask_elems = mask_elems_buf[0..vec_len]; |
| 178569 | for (mask_elems, 0..) |*elem, bit| elem.* = try pt.intern(.{ .int = .{ | |
| 178570 | .ty = mask_elem_ty.toIntern(), | |
| 178571 | .storage = .{ .u64 = @as(u64, 1) << @intCast(bit) }, | |
| 178572 | } }); | |
| 178869 | for (mask_elems, 0..) |*elem, bit| elem.* = (try pt.intValue( | |
| 178870 | mask_elem_ty, | |
| 178871 | @as(u8, 1) << @truncate(bit), | |
| 178872 | )).toIntern(); | |
| 178573 | 178873 | const mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| 178574 | 178874 | .ty = mask_ty.toIntern(), |
| 178575 | 178875 | .storage = .{ .elems = mask_elems }, |
| ... | ... | @@ -179437,16 +179737,13 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 179437 | 179737 | var lhs_mask_elems: [16]InternPool.Index = undefined; |
| 179438 | 179738 | for (lhs_mask_elems[0..max_abi_size], 0..) |*lhs_mask_elem, byte_index| { |
| 179439 | 179739 | const elem_index = byte_index / elem_abi_size; |
| 179440 | lhs_mask_elem.* = try pt.intern(.{ .int = .{ | |
| 179441 | .ty = .u8_type, | |
| 179442 | .storage = .{ .u64 = if (elem_index >= mask_elems.len) 0b1_00_00000 else elem: { | |
| 179443 | const mask_elem = mask_elems[elem_index] orelse break :elem 0b1_00_00000; | |
| 179444 | if (mask_elem < 0) break :elem 0b1_00_00000; | |
| 179445 | const mask_elem_index: u31 = @intCast(mask_elem); | |
| 179446 | const byte_off: u32 = @intCast(byte_index % elem_abi_size); | |
| 179447 | break :elem @intCast(mask_elem_index * elem_abi_size + byte_off); | |
| 179448 | } }, | |
| 179449 | } }); | |
| 179740 | lhs_mask_elem.* = (try pt.intValue(.u8, if (elem_index >= mask_elems.len) 0b1_00_00000 else elem: { | |
| 179741 | const mask_elem = mask_elems[elem_index] orelse break :elem 0b1_00_00000; | |
| 179742 | if (mask_elem < 0) break :elem 0b1_00_00000; | |
| 179743 | const mask_elem_index: u31 = @intCast(mask_elem); | |
| 179744 | const byte_off: u32 = @intCast(byte_index % elem_abi_size); | |
| 179745 | break :elem mask_elem_index * elem_abi_size + byte_off; | |
| 179746 | })).toIntern(); | |
| 179450 | 179747 | } |
| 179451 | 179748 | const lhs_mask_ty = try pt.vectorType(.{ .len = max_abi_size, .child = .u8_type }); |
| 179452 | 179749 | const lhs_mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| ... | ... | @@ -179471,16 +179768,13 @@ fn airShuffle(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 179471 | 179768 | var rhs_mask_elems: [16]InternPool.Index = undefined; |
| 179472 | 179769 | for (rhs_mask_elems[0..max_abi_size], 0..) |*rhs_mask_elem, byte_index| { |
| 179473 | 179770 | const elem_index = byte_index / elem_abi_size; |
| 179474 | rhs_mask_elem.* = try pt.intern(.{ .int = .{ | |
| 179475 | .ty = .u8_type, | |
| 179476 | .storage = .{ .u64 = if (elem_index >= mask_elems.len) 0b1_00_00000 else elem: { | |
| 179477 | const mask_elem = mask_elems[elem_index] orelse break :elem 0b1_00_00000; | |
| 179478 | if (mask_elem >= 0) break :elem 0b1_00_00000; | |
| 179479 | const mask_elem_index: u31 = @intCast(~mask_elem); | |
| 179480 | const byte_off: u32 = @intCast(byte_index % elem_abi_size); | |
| 179481 | break :elem @intCast(mask_elem_index * elem_abi_size + byte_off); | |
| 179482 | } }, | |
| 179483 | } }); | |
| 179771 | rhs_mask_elem.* = (try pt.intValue(.u8, if (elem_index >= mask_elems.len) 0b1_00_00000 else elem: { | |
| 179772 | const mask_elem = mask_elems[elem_index] orelse break :elem 0b1_00_00000; | |
| 179773 | if (mask_elem >= 0) break :elem 0b1_00_00000; | |
| 179774 | const mask_elem_index: u31 = @intCast(~mask_elem); | |
| 179775 | const byte_off: u32 = @intCast(byte_index % elem_abi_size); | |
| 179776 | break :elem mask_elem_index * elem_abi_size + byte_off; | |
| 179777 | })).toIntern(); | |
| 179484 | 179778 | } |
| 179485 | 179779 | const rhs_mask_ty = try pt.vectorType(.{ .len = max_abi_size, .child = .u8_type }); |
| 179486 | 179780 | const rhs_mask_mcv = try self.genTypedValue(.fromInterned(try pt.intern(.{ .aggregate = .{ |
| ... | ... | @@ -180611,7 +180905,7 @@ fn resolveCallingConventionValues( |
| 180611 | 180905 | |
| 180612 | 180906 | result.stack_byte_count = |
| 180613 | 180907 | std.mem.alignForward(u31, result.stack_byte_count, frame_elem_align); |
| 180614 | arg_mcv[arg_mcv_i] = .{ .elementwise_regs_then_frame = .{ | |
| 180908 | arg_mcv[arg_mcv_i] = .{ .elementwise_args = .{ | |
| 180615 | 180909 | .regs = remaining_param_int_regs, |
| 180616 | 180910 | .frame_off = @intCast(result.stack_byte_count), |
| 180617 | 180911 | .frame_index = stack_frame_base, |
| ... | ... | @@ -181236,7 +181530,7 @@ const Temp = struct { |
| 181236 | 181530 | .load_got, |
| 181237 | 181531 | .lea_got, |
| 181238 | 181532 | .lea_frame, |
| 181239 | .elementwise_regs_then_frame, | |
| 181533 | .elementwise_args, | |
| 181240 | 181534 | .reserved_frame, |
| 181241 | 181535 | .air_ref, |
| 181242 | 181536 | => false, |
| ... | ... | @@ -181671,7 +181965,7 @@ const Temp = struct { |
| 181671 | 181965 | .register_quadruple, |
| 181672 | 181966 | .register_overflow, |
| 181673 | 181967 | .register_mask, |
| 181674 | .elementwise_regs_then_frame, | |
| 181968 | .elementwise_args, | |
| 181675 | 181969 | .reserved_frame, |
| 181676 | 181970 | .air_ref, |
| 181677 | 181971 | => unreachable, // not a valid pointer |
| ... | ... | @@ -186395,19 +186689,46 @@ const Temp = struct { |
| 186395 | 186689 | if (cg.reused_operands.isSet(op_index)) continue; |
| 186396 | 186690 | try cg.processDeath(op_ref.toIndexAllowNone() orelse continue); |
| 186397 | 186691 | } |
| 186398 | if (cg.liveness.isUnused(inst)) try temp.die(cg) else switch (temp.unwrap(cg)) { | |
| 186399 | .ref, .err_ret_trace => { | |
| 186400 | const result = try cg.allocRegOrMem(inst, true); | |
| 186401 | try cg.genCopy(cg.typeOfIndex(inst), result, temp.tracking(cg).short, .{}); | |
| 186402 | tracking_log.debug("{} => {} (birth)", .{ inst, result }); | |
| 186403 | cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result)); | |
| 186404 | }, | |
| 186405 | .temp => |temp_index| { | |
| 186406 | const temp_tracking = temp_index.tracking(cg); | |
| 186407 | tracking_log.debug("{} => {} (birth)", .{ inst, temp_tracking.short }); | |
| 186408 | cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(temp_tracking.short)); | |
| 186409 | assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking)); | |
| 186410 | }, | |
| 186692 | if (cg.liveness.isUnused(inst)) try temp.die(cg) else { | |
| 186693 | switch (temp.unwrap(cg)) { | |
| 186694 | .ref, .err_ret_trace => { | |
| 186695 | const temp_mcv = temp.tracking(cg).short; | |
| 186696 | const result = result: switch (temp_mcv) { | |
| 186697 | .none, .unreach, .dead, .elementwise_args, .reserved_frame, .air_ref => unreachable, | |
| 186698 | .undef, .immediate, .lea_frame => temp_mcv, | |
| 186699 | .eflags, | |
| 186700 | .register, | |
| 186701 | .register_pair, | |
| 186702 | .register_triple, | |
| 186703 | .register_quadruple, | |
| 186704 | .register_offset, | |
| 186705 | .register_overflow, | |
| 186706 | .register_mask, | |
| 186707 | .memory, | |
| 186708 | .load_symbol, | |
| 186709 | .lea_symbol, | |
| 186710 | .indirect, | |
| 186711 | .load_direct, | |
| 186712 | .lea_direct, | |
| 186713 | .load_got, | |
| 186714 | .lea_got, | |
| 186715 | .load_frame, | |
| 186716 | => { | |
| 186717 | const result = try cg.allocRegOrMem(inst, true); | |
| 186718 | try cg.genCopy(cg.typeOfIndex(inst), result, temp_mcv, .{}); | |
| 186719 | break :result result; | |
| 186720 | }, | |
| 186721 | }; | |
| 186722 | tracking_log.debug("{} => {} (birth)", .{ inst, result }); | |
| 186723 | cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(result)); | |
| 186724 | }, | |
| 186725 | .temp => |temp_index| { | |
| 186726 | const temp_tracking = temp_index.tracking(cg); | |
| 186727 | tracking_log.debug("{} => {} (birth)", .{ inst, temp_tracking.short }); | |
| 186728 | cg.inst_tracking.putAssumeCapacityNoClobber(inst, .init(temp_tracking.short)); | |
| 186729 | assert(cg.reuseTemp(inst, temp_index.toIndex(), temp_tracking)); | |
| 186730 | }, | |
| 186731 | } | |
| 186411 | 186732 | } |
| 186412 | 186733 | for (0.., op_refs, op_temps) |op_index, op_ref, op_temp| { |
| 186413 | 186734 | if (op_temp.index != temp.index) continue; |
| ... | ... | @@ -187950,6 +188271,7 @@ const Select = struct { |
| 187950 | 188271 | ptr_bit_size, |
| 187951 | 188272 | size, |
| 187952 | 188273 | src0_size, |
| 188274 | dst0_size, | |
| 187953 | 188275 | delta_size, |
| 187954 | 188276 | delta_elem_size, |
| 187955 | 188277 | unaligned_size, |
| ... | ... | @@ -187993,6 +188315,7 @@ const Select = struct { |
| 187993 | 188315 | const sub_src0_size: Adjust = .{ .sign = .neg, .lhs = .src0_size, .op = .mul, .rhs = .@"1" }; |
| 187994 | 188316 | const add_src0_size: Adjust = .{ .sign = .pos, .lhs = .src0_size, .op = .mul, .rhs = .@"1" }; |
| 187995 | 188317 | const add_8_src0_size: Adjust = .{ .sign = .pos, .lhs = .src0_size, .op = .mul, .rhs = .@"8" }; |
| 188318 | const add_dst0_size: Adjust = .{ .sign = .pos, .lhs = .dst0_size, .op = .mul, .rhs = .@"1" }; | |
| 187996 | 188319 | const add_delta_size_div_8: Adjust = .{ .sign = .pos, .lhs = .delta_size, .op = .div, .rhs = .@"8" }; |
| 187997 | 188320 | const add_delta_elem_size: Adjust = .{ .sign = .pos, .lhs = .delta_elem_size, .op = .mul, .rhs = .@"1" }; |
| 187998 | 188321 | const add_delta_elem_size_div_8: Adjust = .{ .sign = .pos, .lhs = .delta_elem_size, .op = .div, .rhs = .@"8" }; |
| ... | ... | @@ -188788,6 +189111,7 @@ const Select = struct { |
| 188788 | 189111 | .ptr_bit_size => s.cg.target.ptrBitWidth(), |
| 188789 | 189112 | .size => @intCast(op.flags.base.ref.typeOf(s).abiSize(s.cg.pt.zcu)), |
| 188790 | 189113 | .src0_size => @intCast(Select.Operand.Ref.src0.typeOf(s).abiSize(s.cg.pt.zcu)), |
| 189114 | .dst0_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).abiSize(s.cg.pt.zcu)), | |
| 188791 | 189115 | .delta_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).abiSize(s.cg.pt.zcu))) - |
| 188792 | 189116 | @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).abiSize(s.cg.pt.zcu)))), |
| 188793 | 189117 | .delta_elem_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))) - |
src/codegen.zig+48-10| ... | ... | @@ -27,13 +27,27 @@ pub const CodeGenError = GenerateSymbolError || error{ |
| 27 | 27 | CodegenFail, |
| 28 | 28 | }; |
| 29 | 29 | |
| 30 | fn devFeatureForBackend(comptime backend: std.builtin.CompilerBackend) dev.Feature { | |
| 31 | comptime assert(mem.startsWith(u8, @tagName(backend), "stage2_")); | |
| 32 | return @field(dev.Feature, @tagName(backend)["stage2_".len..] ++ "_backend"); | |
| 30 | fn devFeatureForBackend(backend: std.builtin.CompilerBackend) dev.Feature { | |
| 31 | return switch (backend) { | |
| 32 | .other, .stage1 => unreachable, | |
| 33 | .stage2_aarch64 => .aarch64_backend, | |
| 34 | .stage2_arm => .arm_backend, | |
| 35 | .stage2_c => .c_backend, | |
| 36 | .stage2_llvm => .llvm_backend, | |
| 37 | .stage2_powerpc => .powerpc_backend, | |
| 38 | .stage2_riscv64 => .riscv64_backend, | |
| 39 | .stage2_sparc64 => .sparc64_backend, | |
| 40 | .stage2_spirv64 => .spirv64_backend, | |
| 41 | .stage2_wasm => .wasm_backend, | |
| 42 | .stage2_x86 => .x86_backend, | |
| 43 | .stage2_x86_64 => .x86_64_backend, | |
| 44 | _ => unreachable, | |
| 45 | }; | |
| 33 | 46 | } |
| 34 | 47 | |
| 35 | pub fn importBackend(comptime backend: std.builtin.CompilerBackend) ?type { | |
| 48 | fn importBackend(comptime backend: std.builtin.CompilerBackend) type { | |
| 36 | 49 | return switch (backend) { |
| 50 | .other, .stage1 => unreachable, | |
| 37 | 51 | .stage2_aarch64 => @import("arch/aarch64/CodeGen.zig"), |
| 38 | 52 | .stage2_arm => @import("arch/arm/CodeGen.zig"), |
| 39 | 53 | .stage2_c => @import("codegen/c.zig"), |
| ... | ... | @@ -42,11 +56,35 @@ pub fn importBackend(comptime backend: std.builtin.CompilerBackend) ?type { |
| 42 | 56 | .stage2_riscv64 => @import("arch/riscv64/CodeGen.zig"), |
| 43 | 57 | .stage2_sparc64 => @import("arch/sparc64/CodeGen.zig"), |
| 44 | 58 | .stage2_spirv64 => @import("codegen/spirv.zig"), |
| 45 | .stage2_x86_64 => @import("arch/x86_64/CodeGen.zig"), | |
| 46 | else => null, | |
| 59 | .stage2_wasm => @import("arch/wasm/CodeGen.zig"), | |
| 60 | .stage2_x86, .stage2_x86_64 => @import("arch/x86_64/CodeGen.zig"), | |
| 61 | _ => unreachable, | |
| 47 | 62 | }; |
| 48 | 63 | } |
| 49 | 64 | |
| 65 | pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*const Air.Legalize.Features { | |
| 66 | const zcu = pt.zcu; | |
| 67 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; | |
| 68 | switch (target_util.zigBackend(target.*, zcu.comp.config.use_llvm)) { | |
| 69 | else => unreachable, | |
| 70 | inline .stage2_llvm, | |
| 71 | .stage2_c, | |
| 72 | .stage2_wasm, | |
| 73 | .stage2_arm, | |
| 74 | .stage2_x86_64, | |
| 75 | .stage2_aarch64, | |
| 76 | .stage2_x86, | |
| 77 | .stage2_riscv64, | |
| 78 | .stage2_sparc64, | |
| 79 | .stage2_spirv64, | |
| 80 | .stage2_powerpc, | |
| 81 | => |backend| { | |
| 82 | dev.check(devFeatureForBackend(backend)); | |
| 83 | return importBackend(backend).legalizeFeatures(target); | |
| 84 | }, | |
| 85 | } | |
| 86 | } | |
| 87 | ||
| 50 | 88 | pub fn generateFunction( |
| 51 | 89 | lf: *link.File, |
| 52 | 90 | pt: Zcu.PerThread, |
| ... | ... | @@ -60,7 +98,7 @@ pub fn generateFunction( |
| 60 | 98 | const zcu = pt.zcu; |
| 61 | 99 | const func = zcu.funcInfo(func_index); |
| 62 | 100 | const target = zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result; |
| 63 | switch (target_util.zigBackend(target, false)) { | |
| 101 | switch (target_util.zigBackend(target, zcu.comp.config.use_llvm)) { | |
| 64 | 102 | else => unreachable, |
| 65 | 103 | inline .stage2_aarch64, |
| 66 | 104 | .stage2_arm, |
| ... | ... | @@ -70,7 +108,7 @@ pub fn generateFunction( |
| 70 | 108 | .stage2_x86_64, |
| 71 | 109 | => |backend| { |
| 72 | 110 | dev.check(devFeatureForBackend(backend)); |
| 73 | return importBackend(backend).?.generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output); | |
| 111 | return importBackend(backend).generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output); | |
| 74 | 112 | }, |
| 75 | 113 | } |
| 76 | 114 | } |
| ... | ... | @@ -88,14 +126,14 @@ pub fn generateLazyFunction( |
| 88 | 126 | zcu.fileByIndex(inst_index.resolveFile(&zcu.intern_pool)).mod.?.resolved_target.result |
| 89 | 127 | else |
| 90 | 128 | zcu.getTarget(); |
| 91 | switch (target_util.zigBackend(target, false)) { | |
| 129 | switch (target_util.zigBackend(target, zcu.comp.config.use_llvm)) { | |
| 92 | 130 | else => unreachable, |
| 93 | 131 | inline .stage2_powerpc, |
| 94 | 132 | .stage2_riscv64, |
| 95 | 133 | .stage2_x86_64, |
| 96 | 134 | => |backend| { |
| 97 | 135 | dev.check(devFeatureForBackend(backend)); |
| 98 | return importBackend(backend).?.generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output); | |
| 136 | return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output); | |
| 99 | 137 | }, |
| 100 | 138 | } |
| 101 | 139 | } |
src/codegen/c.zig+80-26| ... | ... | @@ -4,6 +4,7 @@ const assert = std.debug.assert; |
| 4 | 4 | const mem = std.mem; |
| 5 | 5 | const log = std.log.scoped(.c); |
| 6 | 6 | |
| 7 | const dev = @import("../dev.zig"); | |
| 7 | 8 | const link = @import("../link.zig"); |
| 8 | 9 | const Zcu = @import("../Zcu.zig"); |
| 9 | 10 | const Module = @import("../Package/Module.zig"); |
| ... | ... | @@ -20,6 +21,15 @@ const Alignment = InternPool.Alignment; |
| 20 | 21 | const BigIntLimb = std.math.big.Limb; |
| 21 | 22 | const BigInt = std.math.big.int; |
| 22 | 23 | |
| 24 | pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { | |
| 25 | return if (dev.env.supports(.legalize)) comptime &.initMany(&.{ | |
| 26 | .expand_intcast_safe, | |
| 27 | .expand_add_safe, | |
| 28 | .expand_sub_safe, | |
| 29 | .expand_mul_safe, | |
| 30 | }) else null; // we don't currently ask zig1 to use safe optimization modes | |
| 31 | } | |
| 32 | ||
| 23 | 33 | pub const CType = @import("c/Type.zig"); |
| 24 | 34 | |
| 25 | 35 | pub const CValue = union(enum) { |
| ... | ... | @@ -206,7 +216,6 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ |
| 206 | 216 | .{ "atomic_ushort", {} }, |
| 207 | 217 | .{ "atomic_wchar_t", {} }, |
| 208 | 218 | .{ "auto", {} }, |
| 209 | .{ "bool", {} }, | |
| 210 | 219 | .{ "break", {} }, |
| 211 | 220 | .{ "case", {} }, |
| 212 | 221 | .{ "char", {} }, |
| ... | ... | @@ -266,6 +275,11 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ |
| 266 | 275 | .{ "va_end", {} }, |
| 267 | 276 | .{ "va_copy", {} }, |
| 268 | 277 | |
| 278 | // stdbool.h | |
| 279 | .{ "bool", {} }, | |
| 280 | .{ "false", {} }, | |
| 281 | .{ "true", {} }, | |
| 282 | ||
| 269 | 283 | // stddef.h |
| 270 | 284 | .{ "offsetof", {} }, |
| 271 | 285 | |
| ... | ... | @@ -1591,7 +1605,7 @@ pub const DeclGen = struct { |
| 1591 | 1605 | try writer.writeAll("(("); |
| 1592 | 1606 | try dg.renderCType(writer, ctype); |
| 1593 | 1607 | return writer.print("){x})", .{ |
| 1594 | try dg.fmtIntLiteral(try pt.undefValue(.usize), .Other), | |
| 1608 | try dg.fmtIntLiteral(.undef_usize, .Other), | |
| 1595 | 1609 | }); |
| 1596 | 1610 | }, |
| 1597 | 1611 | .slice => { |
| ... | ... | @@ -1605,7 +1619,7 @@ pub const DeclGen = struct { |
| 1605 | 1619 | const ptr_ty = ty.slicePtrFieldType(zcu); |
| 1606 | 1620 | try dg.renderType(writer, ptr_ty); |
| 1607 | 1621 | return writer.print("){x}, {0x}}}", .{ |
| 1608 | try dg.fmtIntLiteral(try dg.pt.undefValue(.usize), .Other), | |
| 1622 | try dg.fmtIntLiteral(.undef_usize, .Other), | |
| 1609 | 1623 | }); |
| 1610 | 1624 | }, |
| 1611 | 1625 | }, |
| ... | ... | @@ -3360,7 +3374,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3360 | 3374 | .error_name => try airErrorName(f, inst), |
| 3361 | 3375 | .splat => try airSplat(f, inst), |
| 3362 | 3376 | .select => try airSelect(f, inst), |
| 3363 | .shuffle => try airShuffle(f, inst), | |
| 3377 | .shuffle_one => try airShuffleOne(f, inst), | |
| 3378 | .shuffle_two => try airShuffleTwo(f, inst), | |
| 3364 | 3379 | .reduce => try airReduce(f, inst), |
| 3365 | 3380 | .aggregate_init => try airAggregateInit(f, inst), |
| 3366 | 3381 | .union_init => try airUnionInit(f, inst), |
| ... | ... | @@ -4179,7 +4194,7 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 4179 | 4194 | try v.elem(f, w); |
| 4180 | 4195 | try w.writeAll(", "); |
| 4181 | 4196 | try f.writeCValue(w, rhs, .FunctionArgument); |
| 4182 | try v.elem(f, w); | |
| 4197 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); | |
| 4183 | 4198 | try f.object.dg.renderBuiltinInfo(w, scalar_ty, info); |
| 4184 | 4199 | try w.writeAll(");\n"); |
| 4185 | 4200 | try v.end(f, inst, w); |
| ... | ... | @@ -6376,7 +6391,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6376 | 6391 | if (operand_child_ctype.info(ctype_pool) == .array) { |
| 6377 | 6392 | try writer.writeByte('&'); |
| 6378 | 6393 | try f.writeCValueDeref(writer, operand); |
| 6379 | try writer.print("[{}]", .{try f.fmtIntLiteral(try pt.intValue(.usize, 0))}); | |
| 6394 | try writer.print("[{}]", .{try f.fmtIntLiteral(.zero_usize)}); | |
| 6380 | 6395 | } else try f.writeCValue(writer, operand, .Other); |
| 6381 | 6396 | } |
| 6382 | 6397 | try a.end(f, writer); |
| ... | ... | @@ -6536,7 +6551,7 @@ fn airBinBuiltinCall( |
| 6536 | 6551 | try v.elem(f, writer); |
| 6537 | 6552 | try writer.writeAll(", "); |
| 6538 | 6553 | try f.writeCValue(writer, rhs, .FunctionArgument); |
| 6539 | try v.elem(f, writer); | |
| 6554 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, writer); | |
| 6540 | 6555 | try f.object.dg.renderBuiltinInfo(writer, scalar_ty, info); |
| 6541 | 6556 | try writer.writeAll(");\n"); |
| 6542 | 6557 | try v.end(f, inst, writer); |
| ... | ... | @@ -6907,7 +6922,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6907 | 6922 | try writer.writeAll("for ("); |
| 6908 | 6923 | try f.writeCValue(writer, index, .Other); |
| 6909 | 6924 | try writer.writeAll(" = "); |
| 6910 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, 0), .Other); | |
| 6925 | try f.object.dg.renderValue(writer, .zero_usize, .Other); | |
| 6911 | 6926 | try writer.writeAll("; "); |
| 6912 | 6927 | try f.writeCValue(writer, index, .Other); |
| 6913 | 6928 | try writer.writeAll(" != "); |
| ... | ... | @@ -7149,34 +7164,73 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7149 | 7164 | return local; |
| 7150 | 7165 | } |
| 7151 | 7166 | |
| 7152 | fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { | |
| 7167 | fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { | |
| 7153 | 7168 | const pt = f.object.dg.pt; |
| 7154 | 7169 | const zcu = pt.zcu; |
| 7155 | const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 7156 | const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; | |
| 7157 | 7170 | |
| 7158 | const mask = Value.fromInterned(extra.mask); | |
| 7159 | const lhs = try f.resolveInst(extra.a); | |
| 7160 | const rhs = try f.resolveInst(extra.b); | |
| 7161 | ||
| 7162 | const inst_ty = f.typeOfIndex(inst); | |
| 7171 | const unwrapped = f.air.unwrapShuffleOne(zcu, inst); | |
| 7172 | const mask = unwrapped.mask; | |
| 7173 | const operand = try f.resolveInst(unwrapped.operand); | |
| 7174 | const inst_ty = unwrapped.result_ty; | |
| 7163 | 7175 | |
| 7164 | 7176 | const writer = f.object.writer(); |
| 7165 | 7177 | const local = try f.allocLocal(inst, inst_ty); |
| 7166 | try reap(f, inst, &.{ extra.a, extra.b }); // local cannot alias operands | |
| 7167 | for (0..extra.mask_len) |index| { | |
| 7178 | try reap(f, inst, &.{unwrapped.operand}); // local cannot alias operand | |
| 7179 | for (mask, 0..) |mask_elem, out_idx| { | |
| 7168 | 7180 | try f.writeCValue(writer, local, .Other); |
| 7169 | 7181 | try writer.writeByte('['); |
| 7170 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, index), .Other); | |
| 7182 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other); | |
| 7171 | 7183 | try writer.writeAll("] = "); |
| 7184 | switch (mask_elem.unwrap()) { | |
| 7185 | .elem => |src_idx| { | |
| 7186 | try f.writeCValue(writer, operand, .Other); | |
| 7187 | try writer.writeByte('['); | |
| 7188 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other); | |
| 7189 | try writer.writeByte(']'); | |
| 7190 | }, | |
| 7191 | .value => |val| try f.object.dg.renderValue(writer, .fromInterned(val), .Other), | |
| 7192 | } | |
| 7193 | try writer.writeAll(";\n"); | |
| 7194 | } | |
| 7172 | 7195 | |
| 7173 | const mask_elem = (try mask.elemValue(pt, index)).toSignedInt(zcu); | |
| 7174 | const src_val = try pt.intValue(.usize, @as(u64, @intCast(mask_elem ^ mask_elem >> 63))); | |
| 7196 | return local; | |
| 7197 | } | |
| 7198 | ||
| 7199 | fn airShuffleTwo(f: *Function, inst: Air.Inst.Index) !CValue { | |
| 7200 | const pt = f.object.dg.pt; | |
| 7201 | const zcu = pt.zcu; | |
| 7202 | ||
| 7203 | const unwrapped = f.air.unwrapShuffleTwo(zcu, inst); | |
| 7204 | const mask = unwrapped.mask; | |
| 7205 | const operand_a = try f.resolveInst(unwrapped.operand_a); | |
| 7206 | const operand_b = try f.resolveInst(unwrapped.operand_b); | |
| 7207 | const inst_ty = unwrapped.result_ty; | |
| 7208 | const elem_ty = inst_ty.childType(zcu); | |
| 7175 | 7209 | |
| 7176 | try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other); | |
| 7210 | const writer = f.object.writer(); | |
| 7211 | const local = try f.allocLocal(inst, inst_ty); | |
| 7212 | try reap(f, inst, &.{ unwrapped.operand_a, unwrapped.operand_b }); // local cannot alias operands | |
| 7213 | for (mask, 0..) |mask_elem, out_idx| { | |
| 7214 | try f.writeCValue(writer, local, .Other); | |
| 7177 | 7215 | try writer.writeByte('['); |
| 7178 | try f.object.dg.renderValue(writer, src_val, .Other); | |
| 7179 | try writer.writeAll("];\n"); | |
| 7216 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, out_idx), .Other); | |
| 7217 | try writer.writeAll("] = "); | |
| 7218 | switch (mask_elem.unwrap()) { | |
| 7219 | .a_elem => |src_idx| { | |
| 7220 | try f.writeCValue(writer, operand_a, .Other); | |
| 7221 | try writer.writeByte('['); | |
| 7222 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other); | |
| 7223 | try writer.writeByte(']'); | |
| 7224 | }, | |
| 7225 | .b_elem => |src_idx| { | |
| 7226 | try f.writeCValue(writer, operand_b, .Other); | |
| 7227 | try writer.writeByte('['); | |
| 7228 | try f.object.dg.renderValue(writer, try pt.intValue(.usize, src_idx), .Other); | |
| 7229 | try writer.writeByte(']'); | |
| 7230 | }, | |
| 7231 | .undef => try f.object.dg.renderUndefValue(writer, elem_ty, .Other), | |
| 7232 | } | |
| 7233 | try writer.writeAll(";\n"); | |
| 7180 | 7234 | } |
| 7181 | 7235 | |
| 7182 | 7236 | return local; |
| ... | ... | @@ -8311,11 +8365,11 @@ const Vectorize = struct { |
| 8311 | 8365 | |
| 8312 | 8366 | try writer.writeAll("for ("); |
| 8313 | 8367 | try f.writeCValue(writer, local, .Other); |
| 8314 | try writer.print(" = {d}; ", .{try f.fmtIntLiteral(try pt.intValue(.usize, 0))}); | |
| 8368 | try writer.print(" = {d}; ", .{try f.fmtIntLiteral(.zero_usize)}); | |
| 8315 | 8369 | try f.writeCValue(writer, local, .Other); |
| 8316 | 8370 | try writer.print(" < {d}; ", .{try f.fmtIntLiteral(try pt.intValue(.usize, ty.vectorLen(zcu)))}); |
| 8317 | 8371 | try f.writeCValue(writer, local, .Other); |
| 8318 | try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(try pt.intValue(.usize, 1))}); | |
| 8372 | try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(.one_usize)}); | |
| 8319 | 8373 | f.object.indent_writer.pushIndent(); |
| 8320 | 8374 | |
| 8321 | 8375 | break :index .{ .index = local }; |
src/codegen/c/Type.zig+15-6| ... | ... | @@ -1408,6 +1408,15 @@ pub const Pool = struct { |
| 1408 | 1408 | .bits = pt.zcu.errorSetBits(), |
| 1409 | 1409 | }, mod, kind), |
| 1410 | 1410 | |
| 1411 | .ptr_usize_type, | |
| 1412 | => return pool.getPointer(allocator, .{ | |
| 1413 | .elem_ctype = .usize, | |
| 1414 | }), | |
| 1415 | .ptr_const_comptime_int_type, | |
| 1416 | => return pool.getPointer(allocator, .{ | |
| 1417 | .elem_ctype = .void, | |
| 1418 | .@"const" = true, | |
| 1419 | }), | |
| 1411 | 1420 | .manyptr_u8_type, |
| 1412 | 1421 | => return pool.getPointer(allocator, .{ |
| 1413 | 1422 | .elem_ctype = .u8, |
| ... | ... | @@ -1418,11 +1427,6 @@ pub const Pool = struct { |
| 1418 | 1427 | .elem_ctype = .u8, |
| 1419 | 1428 | .@"const" = true, |
| 1420 | 1429 | }), |
| 1421 | .single_const_pointer_to_comptime_int_type, | |
| 1422 | => return pool.getPointer(allocator, .{ | |
| 1423 | .elem_ctype = .void, | |
| 1424 | .@"const" = true, | |
| 1425 | }), | |
| 1426 | 1430 | .slice_const_u8_type, |
| 1427 | 1431 | .slice_const_u8_sentinel_0_type, |
| 1428 | 1432 | => { |
| ... | ... | @@ -2157,11 +2161,16 @@ pub const Pool = struct { |
| 2157 | 2161 | }, |
| 2158 | 2162 | |
| 2159 | 2163 | .undef, |
| 2164 | .undef_bool, | |
| 2165 | .undef_usize, | |
| 2166 | .undef_u1, | |
| 2160 | 2167 | .zero, |
| 2161 | 2168 | .zero_usize, |
| 2169 | .zero_u1, | |
| 2162 | 2170 | .zero_u8, |
| 2163 | 2171 | .one, |
| 2164 | 2172 | .one_usize, |
| 2173 | .one_u1, | |
| 2165 | 2174 | .one_u8, |
| 2166 | 2175 | .four_u8, |
| 2167 | 2176 | .negative_one, |
| ... | ... | @@ -2172,7 +2181,7 @@ pub const Pool = struct { |
| 2172 | 2181 | .bool_false, |
| 2173 | 2182 | .empty_tuple, |
| 2174 | 2183 | .none, |
| 2175 | => unreachable, | |
| 2184 | => unreachable, // values, not types | |
| 2176 | 2185 | |
| 2177 | 2186 | _ => |ip_index| switch (ip.indexToKey(ip_index)) { |
| 2178 | 2187 | .int_type => |int_info| return pool.fromIntInfo(allocator, int_info, mod, kind), |
src/codegen/llvm.zig+216-47| ... | ... | @@ -36,6 +36,10 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; |
| 36 | 36 | |
| 37 | 37 | const Error = error{ OutOfMemory, CodegenFail }; |
| 38 | 38 | |
| 39 | pub fn legalizeFeatures(_: *const std.Target) ?*const Air.Legalize.Features { | |
| 40 | return null; | |
| 41 | } | |
| 42 | ||
| 39 | 43 | fn subArchName(features: std.Target.Cpu.Feature.Set, arch: anytype, mappings: anytype) ?[]const u8 { |
| 40 | 44 | inline for (mappings) |mapping| { |
| 41 | 45 | if (arch.featureSetHas(features, mapping[0])) return mapping[1]; |
| ... | ... | @@ -3081,10 +3085,11 @@ pub const Object = struct { |
| 3081 | 3085 | .undefined_type, |
| 3082 | 3086 | .enum_literal_type, |
| 3083 | 3087 | => unreachable, |
| 3088 | .ptr_usize_type, | |
| 3089 | .ptr_const_comptime_int_type, | |
| 3084 | 3090 | .manyptr_u8_type, |
| 3085 | 3091 | .manyptr_const_u8_type, |
| 3086 | 3092 | .manyptr_const_u8_sentinel_0_type, |
| 3087 | .single_const_pointer_to_comptime_int_type, | |
| 3088 | 3093 | => .ptr, |
| 3089 | 3094 | .slice_const_u8_type, |
| 3090 | 3095 | .slice_const_u8_sentinel_0_type, |
| ... | ... | @@ -3098,11 +3103,16 @@ pub const Object = struct { |
| 3098 | 3103 | => unreachable, |
| 3099 | 3104 | // values, not types |
| 3100 | 3105 | .undef, |
| 3106 | .undef_bool, | |
| 3107 | .undef_usize, | |
| 3108 | .undef_u1, | |
| 3101 | 3109 | .zero, |
| 3102 | 3110 | .zero_usize, |
| 3111 | .zero_u1, | |
| 3103 | 3112 | .zero_u8, |
| 3104 | 3113 | .one, |
| 3105 | 3114 | .one_usize, |
| 3115 | .one_u1, | |
| 3106 | 3116 | .one_u8, |
| 3107 | 3117 | .four_u8, |
| 3108 | 3118 | .negative_one, |
| ... | ... | @@ -4959,7 +4969,8 @@ pub const FuncGen = struct { |
| 4959 | 4969 | .error_name => try self.airErrorName(inst), |
| 4960 | 4970 | .splat => try self.airSplat(inst), |
| 4961 | 4971 | .select => try self.airSelect(inst), |
| 4962 | .shuffle => try self.airShuffle(inst), | |
| 4972 | .shuffle_one => try self.airShuffleOne(inst), | |
| 4973 | .shuffle_two => try self.airShuffleTwo(inst), | |
| 4963 | 4974 | .aggregate_init => try self.airAggregateInit(inst), |
| 4964 | 4975 | .union_init => try self.airUnionInit(inst), |
| 4965 | 4976 | .prefetch => try self.airPrefetch(inst), |
| ... | ... | @@ -8917,6 +8928,8 @@ pub const FuncGen = struct { |
| 8917 | 8928 | const rhs = try self.resolveInst(extra.rhs); |
| 8918 | 8929 | |
| 8919 | 8930 | const lhs_ty = self.typeOf(extra.lhs); |
| 8931 | if (lhs_ty.isVector(zcu) and !self.typeOf(extra.rhs).isVector(zcu)) | |
| 8932 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 8920 | 8933 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 8921 | 8934 | |
| 8922 | 8935 | const dest_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -8986,6 +8999,8 @@ pub const FuncGen = struct { |
| 8986 | 8999 | const rhs = try self.resolveInst(bin_op.rhs); |
| 8987 | 9000 | |
| 8988 | 9001 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 9002 | if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 9003 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 8989 | 9004 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 8990 | 9005 | |
| 8991 | 9006 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); |
| ... | ... | @@ -8997,14 +9012,17 @@ pub const FuncGen = struct { |
| 8997 | 9012 | |
| 8998 | 9013 | fn airShl(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { |
| 8999 | 9014 | const o = self.ng.object; |
| 9015 | const zcu = o.pt.zcu; | |
| 9000 | 9016 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 9001 | 9017 | |
| 9002 | 9018 | const lhs = try self.resolveInst(bin_op.lhs); |
| 9003 | 9019 | const rhs = try self.resolveInst(bin_op.rhs); |
| 9004 | 9020 | |
| 9005 | const lhs_type = self.typeOf(bin_op.lhs); | |
| 9021 | const lhs_ty = self.typeOf(bin_op.lhs); | |
| 9022 | if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 9023 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 9006 | 9024 | |
| 9007 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_type), ""); | |
| 9025 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); | |
| 9008 | 9026 | return self.wip.bin(.shl, lhs, casted_rhs, ""); |
| 9009 | 9027 | } |
| 9010 | 9028 | |
| ... | ... | @@ -9023,6 +9041,8 @@ pub const FuncGen = struct { |
| 9023 | 9041 | const llvm_lhs_scalar_ty = llvm_lhs_ty.scalarType(&o.builder); |
| 9024 | 9042 | |
| 9025 | 9043 | const rhs_ty = self.typeOf(bin_op.rhs); |
| 9044 | if (lhs_ty.isVector(zcu) and !rhs_ty.isVector(zcu)) | |
| 9045 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 9026 | 9046 | const rhs_info = rhs_ty.intInfo(zcu); |
| 9027 | 9047 | assert(rhs_info.signedness == .unsigned); |
| 9028 | 9048 | const llvm_rhs_ty = try o.lowerType(rhs_ty); |
| ... | ... | @@ -9095,6 +9115,8 @@ pub const FuncGen = struct { |
| 9095 | 9115 | const rhs = try self.resolveInst(bin_op.rhs); |
| 9096 | 9116 | |
| 9097 | 9117 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 9118 | if (lhs_ty.isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) | |
| 9119 | return self.ng.todo("implement vector shifts with scalar rhs", .{}); | |
| 9098 | 9120 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 9099 | 9121 | |
| 9100 | 9122 | const casted_rhs = try self.wip.conv(.unsigned, rhs, try o.lowerType(lhs_ty), ""); |
| ... | ... | @@ -9167,11 +9189,7 @@ pub const FuncGen = struct { |
| 9167 | 9189 | const is_vector = operand_ty.zigTypeTag(zcu) == .vector; |
| 9168 | 9190 | assert(is_vector == (dest_ty.zigTypeTag(zcu) == .vector)); |
| 9169 | 9191 | |
| 9170 | const min_panic_id: Zcu.SimplePanicId, const max_panic_id: Zcu.SimplePanicId = id: { | |
| 9171 | if (dest_is_enum) break :id .{ .invalid_enum_value, .invalid_enum_value }; | |
| 9172 | if (dest_info.signedness == .unsigned) break :id .{ .negative_to_unsigned, .cast_truncated_data }; | |
| 9173 | break :id .{ .cast_truncated_data, .cast_truncated_data }; | |
| 9174 | }; | |
| 9192 | const panic_id: Zcu.SimplePanicId = if (dest_is_enum) .invalid_enum_value else .integer_out_of_bounds; | |
| 9175 | 9193 | |
| 9176 | 9194 | if (have_min_check) { |
| 9177 | 9195 | const min_const_scalar = try minIntConst(&o.builder, dest_scalar, operand_scalar_llvm_ty, zcu); |
| ... | ... | @@ -9185,7 +9203,7 @@ pub const FuncGen = struct { |
| 9185 | 9203 | const ok_block = try fg.wip.block(1, "IntMinOk"); |
| 9186 | 9204 | _ = try fg.wip.brCond(ok, ok_block, fail_block, .none); |
| 9187 | 9205 | fg.wip.cursor = .{ .block = fail_block }; |
| 9188 | try fg.buildSimplePanic(min_panic_id); | |
| 9206 | try fg.buildSimplePanic(panic_id); | |
| 9189 | 9207 | fg.wip.cursor = .{ .block = ok_block }; |
| 9190 | 9208 | } |
| 9191 | 9209 | |
| ... | ... | @@ -9201,7 +9219,7 @@ pub const FuncGen = struct { |
| 9201 | 9219 | const ok_block = try fg.wip.block(1, "IntMaxOk"); |
| 9202 | 9220 | _ = try fg.wip.brCond(ok, ok_block, fail_block, .none); |
| 9203 | 9221 | fg.wip.cursor = .{ .block = fail_block }; |
| 9204 | try fg.buildSimplePanic(max_panic_id); | |
| 9222 | try fg.buildSimplePanic(panic_id); | |
| 9205 | 9223 | fg.wip.cursor = .{ .block = ok_block }; |
| 9206 | 9224 | } |
| 9207 | 9225 | } |
| ... | ... | @@ -9249,8 +9267,6 @@ pub const FuncGen = struct { |
| 9249 | 9267 | const operand_ty = self.typeOf(ty_op.operand); |
| 9250 | 9268 | const dest_ty = self.typeOfIndex(inst); |
| 9251 | 9269 | const target = zcu.getTarget(); |
| 9252 | const dest_bits = dest_ty.floatBits(target); | |
| 9253 | const src_bits = operand_ty.floatBits(target); | |
| 9254 | 9270 | |
| 9255 | 9271 | if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { |
| 9256 | 9272 | return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty), ""); |
| ... | ... | @@ -9258,6 +9274,8 @@ pub const FuncGen = struct { |
| 9258 | 9274 | const operand_llvm_ty = try o.lowerType(operand_ty); |
| 9259 | 9275 | const dest_llvm_ty = try o.lowerType(dest_ty); |
| 9260 | 9276 | |
| 9277 | const dest_bits = dest_ty.floatBits(target); | |
| 9278 | const src_bits = operand_ty.floatBits(target); | |
| 9261 | 9279 | const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ |
| 9262 | 9280 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), |
| 9263 | 9281 | }); |
| ... | ... | @@ -9342,11 +9360,12 @@ pub const FuncGen = struct { |
| 9342 | 9360 | return self.wip.conv(.unsigned, operand, llvm_dest_ty, ""); |
| 9343 | 9361 | } |
| 9344 | 9362 | |
| 9345 | if (operand_ty.zigTypeTag(zcu) == .int and inst_ty.isPtrAtRuntime(zcu)) { | |
| 9363 | const operand_scalar_ty = operand_ty.scalarType(zcu); | |
| 9364 | const inst_scalar_ty = inst_ty.scalarType(zcu); | |
| 9365 | if (operand_scalar_ty.zigTypeTag(zcu) == .int and inst_scalar_ty.isPtrAtRuntime(zcu)) { | |
| 9346 | 9366 | return self.wip.cast(.inttoptr, operand, llvm_dest_ty, ""); |
| 9347 | 9367 | } |
| 9348 | ||
| 9349 | if (operand_ty.isPtrAtRuntime(zcu) and inst_ty.zigTypeTag(zcu) == .int) { | |
| 9368 | if (operand_scalar_ty.isPtrAtRuntime(zcu) and inst_scalar_ty.zigTypeTag(zcu) == .int) { | |
| 9350 | 9369 | return self.wip.cast(.ptrtoint, operand, llvm_dest_ty, ""); |
| 9351 | 9370 | } |
| 9352 | 9371 | |
| ... | ... | @@ -9644,7 +9663,7 @@ pub const FuncGen = struct { |
| 9644 | 9663 | const zcu = o.pt.zcu; |
| 9645 | 9664 | const ip = &zcu.intern_pool; |
| 9646 | 9665 | for (body_tail[1..]) |body_inst| { |
| 9647 | switch (fg.liveness.categorizeOperand(fg.air, body_inst, body_tail[0], ip)) { | |
| 9666 | switch (fg.liveness.categorizeOperand(fg.air, zcu, body_inst, body_tail[0], ip)) { | |
| 9648 | 9667 | .none => continue, |
| 9649 | 9668 | .write, .noret, .complex => return false, |
| 9650 | 9669 | .tomb => return true, |
| ... | ... | @@ -10399,42 +10418,192 @@ pub const FuncGen = struct { |
| 10399 | 10418 | return self.wip.select(.normal, pred, a, b, ""); |
| 10400 | 10419 | } |
| 10401 | 10420 | |
| 10402 | fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | |
| 10403 | const o = self.ng.object; | |
| 10421 | fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | |
| 10422 | const o = fg.ng.object; | |
| 10404 | 10423 | const pt = o.pt; |
| 10405 | 10424 | const zcu = pt.zcu; |
| 10406 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 10407 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; | |
| 10408 | const a = try self.resolveInst(extra.a); | |
| 10409 | const b = try self.resolveInst(extra.b); | |
| 10410 | const mask = Value.fromInterned(extra.mask); | |
| 10411 | const mask_len = extra.mask_len; | |
| 10412 | const a_len = self.typeOf(extra.a).vectorLen(zcu); | |
| 10413 | ||
| 10414 | // LLVM uses integers larger than the length of the first array to | |
| 10415 | // index into the second array. This was deemed unnecessarily fragile | |
| 10416 | // when changing code, so Zig uses negative numbers to index the | |
| 10417 | // second vector. These start at -1 and go down, and are easiest to use | |
| 10418 | // with the ~ operator. Here we convert between the two formats. | |
| 10419 | const values = try self.gpa.alloc(Builder.Constant, mask_len); | |
| 10420 | defer self.gpa.free(values); | |
| 10421 | ||
| 10422 | for (values, 0..) |*val, i| { | |
| 10423 | const elem = try mask.elemValue(pt, i); | |
| 10424 | if (elem.isUndef(zcu)) { | |
| 10425 | val.* = try o.builder.undefConst(.i32); | |
| 10426 | } else { | |
| 10427 | const int = elem.toSignedInt(zcu); | |
| 10428 | const unsigned: u32 = @intCast(if (int >= 0) int else ~int + a_len); | |
| 10429 | val.* = try o.builder.intConst(.i32, unsigned); | |
| 10425 | const gpa = zcu.gpa; | |
| 10426 | ||
| 10427 | const unwrapped = fg.air.unwrapShuffleOne(zcu, inst); | |
| 10428 | ||
| 10429 | const operand = try fg.resolveInst(unwrapped.operand); | |
| 10430 | const mask = unwrapped.mask; | |
| 10431 | const operand_ty = fg.typeOf(unwrapped.operand); | |
| 10432 | const llvm_operand_ty = try o.lowerType(operand_ty); | |
| 10433 | const llvm_result_ty = try o.lowerType(unwrapped.result_ty); | |
| 10434 | const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu)); | |
| 10435 | const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty); | |
| 10436 | const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); | |
| 10437 | const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); | |
| 10438 | ||
| 10439 | // LLVM requires that the two input vectors have the same length, so lowering isn't trivial. | |
| 10440 | // And, in the words of jacobly0: "llvm sucks at shuffles so we do have to hold its hand at | |
| 10441 | // least a bit". So, there are two cases here. | |
| 10442 | // | |
| 10443 | // If the operand length equals the mask length, we do just the one `shufflevector`, where | |
| 10444 | // the second operand is a constant vector with comptime-known elements at the right indices | |
| 10445 | // and poison values elsewhere (in the indices which won't be selected). | |
| 10446 | // | |
| 10447 | // Otherwise, we lower to *two* `shufflevector` instructions. The first shuffles the runtime | |
| 10448 | // operand with an all-poison vector to extract and correctly position all of the runtime | |
| 10449 | // elements. We also make a constant vector with all of the comptime elements correctly | |
| 10450 | // positioned. Then, our second instruction selects elements from those "runtime-or-poison" | |
| 10451 | // and "comptime-or-poison" vectors to compute the result. | |
| 10452 | ||
| 10453 | // This buffer is used primarily for the mask constants. | |
| 10454 | const llvm_elem_buf = try gpa.alloc(Builder.Constant, mask.len); | |
| 10455 | defer gpa.free(llvm_elem_buf); | |
| 10456 | ||
| 10457 | // ...but first, we'll collect all of the comptime-known values. | |
| 10458 | var any_defined_comptime_value = false; | |
| 10459 | for (mask, llvm_elem_buf) |mask_elem, *llvm_elem| { | |
| 10460 | llvm_elem.* = switch (mask_elem.unwrap()) { | |
| 10461 | .elem => llvm_poison_elem, | |
| 10462 | .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: { | |
| 10463 | any_defined_comptime_value = true; | |
| 10464 | break :elem try o.lowerValue(val); | |
| 10465 | } else llvm_poison_elem, | |
| 10466 | }; | |
| 10467 | } | |
| 10468 | // This vector is like the result, but runtime elements are replaced with poison. | |
| 10469 | const comptime_and_poison: Builder.Value = if (any_defined_comptime_value) vec: { | |
| 10470 | break :vec try o.builder.vectorValue(llvm_result_ty, llvm_elem_buf); | |
| 10471 | } else try o.builder.poisonValue(llvm_result_ty); | |
| 10472 | ||
| 10473 | if (operand_ty.vectorLen(zcu) == mask.len) { | |
| 10474 | // input length equals mask/output length, so we lower to one instruction | |
| 10475 | for (mask, llvm_elem_buf, 0..) |mask_elem, *llvm_elem, elem_idx| { | |
| 10476 | llvm_elem.* = switch (mask_elem.unwrap()) { | |
| 10477 | .elem => |idx| try o.builder.intConst(.i32, idx), | |
| 10478 | .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) mask_val: { | |
| 10479 | break :mask_val try o.builder.intConst(.i32, mask.len + elem_idx); | |
| 10480 | } else llvm_poison_mask_elem, | |
| 10481 | }; | |
| 10430 | 10482 | } |
| 10483 | return fg.wip.shuffleVector( | |
| 10484 | operand, | |
| 10485 | comptime_and_poison, | |
| 10486 | try o.builder.vectorValue(llvm_mask_ty, llvm_elem_buf), | |
| 10487 | "", | |
| 10488 | ); | |
| 10489 | } | |
| 10490 | ||
| 10491 | for (mask, llvm_elem_buf) |mask_elem, *llvm_elem| { | |
| 10492 | llvm_elem.* = switch (mask_elem.unwrap()) { | |
| 10493 | .elem => |idx| try o.builder.intConst(.i32, idx), | |
| 10494 | .value => llvm_poison_mask_elem, | |
| 10495 | }; | |
| 10431 | 10496 | } |
| 10497 | // This vector is like our result, but all comptime-known elements are poison. | |
| 10498 | const runtime_and_poison = try fg.wip.shuffleVector( | |
| 10499 | operand, | |
| 10500 | try o.builder.poisonValue(llvm_operand_ty), | |
| 10501 | try o.builder.vectorValue(llvm_mask_ty, llvm_elem_buf), | |
| 10502 | "", | |
| 10503 | ); | |
| 10432 | 10504 | |
| 10433 | const llvm_mask_value = try o.builder.vectorValue( | |
| 10434 | try o.builder.vectorType(.normal, mask_len, .i32), | |
| 10435 | values, | |
| 10505 | if (!any_defined_comptime_value) { | |
| 10506 | // `comptime_and_poison` is just poison; a second shuffle would be a nop. | |
| 10507 | return runtime_and_poison; | |
| 10508 | } | |
| 10509 | ||
| 10510 | // In this second shuffle, the inputs, the mask, and the output all have the same length. | |
| 10511 | for (mask, llvm_elem_buf, 0..) |mask_elem, *llvm_elem, elem_idx| { | |
| 10512 | llvm_elem.* = switch (mask_elem.unwrap()) { | |
| 10513 | .elem => try o.builder.intConst(.i32, elem_idx), | |
| 10514 | .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) mask_val: { | |
| 10515 | break :mask_val try o.builder.intConst(.i32, mask.len + elem_idx); | |
| 10516 | } else llvm_poison_mask_elem, | |
| 10517 | }; | |
| 10518 | } | |
| 10519 | // Merge the runtime and comptime elements with the mask we just built. | |
| 10520 | return fg.wip.shuffleVector( | |
| 10521 | runtime_and_poison, | |
| 10522 | comptime_and_poison, | |
| 10523 | try o.builder.vectorValue(llvm_mask_ty, llvm_elem_buf), | |
| 10524 | "", | |
| 10525 | ); | |
| 10526 | } | |
| 10527 | ||
| 10528 | fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) !Builder.Value { | |
| 10529 | const o = fg.ng.object; | |
| 10530 | const pt = o.pt; | |
| 10531 | const zcu = pt.zcu; | |
| 10532 | const gpa = zcu.gpa; | |
| 10533 | ||
| 10534 | const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst); | |
| 10535 | ||
| 10536 | const mask = unwrapped.mask; | |
| 10537 | const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu)); | |
| 10538 | const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); | |
| 10539 | const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); | |
| 10540 | ||
| 10541 | // This is kind of simpler than in `airShuffleOne`. We extend the shorter vector to the | |
| 10542 | // length of the longer one with an initial `shufflevector` if necessary, and then do the | |
| 10543 | // actual computation with a second `shufflevector`. | |
| 10544 | ||
| 10545 | const operand_a_len = fg.typeOf(unwrapped.operand_a).vectorLen(zcu); | |
| 10546 | const operand_b_len = fg.typeOf(unwrapped.operand_b).vectorLen(zcu); | |
| 10547 | const operand_len: u32 = @max(operand_a_len, operand_b_len); | |
| 10548 | ||
| 10549 | // If we need to extend an operand, this is the type that mask will have. | |
| 10550 | const llvm_operand_mask_ty = try o.builder.vectorType(.normal, operand_len, .i32); | |
| 10551 | ||
| 10552 | const llvm_elem_buf = try gpa.alloc(Builder.Constant, @max(mask.len, operand_len)); | |
| 10553 | defer gpa.free(llvm_elem_buf); | |
| 10554 | ||
| 10555 | const operand_a: Builder.Value = extend: { | |
| 10556 | const raw = try fg.resolveInst(unwrapped.operand_a); | |
| 10557 | if (operand_a_len == operand_len) break :extend raw; | |
| 10558 | // Extend with a `shufflevector`, with a mask `<0, 1, ..., n, poison, poison, ..., poison>` | |
| 10559 | const mask_elems = llvm_elem_buf[0..operand_len]; | |
| 10560 | for (mask_elems[0..operand_a_len], 0..) |*llvm_elem, elem_idx| { | |
| 10561 | llvm_elem.* = try o.builder.intConst(.i32, elem_idx); | |
| 10562 | } | |
| 10563 | @memset(mask_elems[operand_a_len..], llvm_poison_mask_elem); | |
| 10564 | const llvm_this_operand_ty = try o.builder.vectorType(.normal, operand_a_len, llvm_elem_ty); | |
| 10565 | break :extend try fg.wip.shuffleVector( | |
| 10566 | raw, | |
| 10567 | try o.builder.poisonValue(llvm_this_operand_ty), | |
| 10568 | try o.builder.vectorValue(llvm_operand_mask_ty, mask_elems), | |
| 10569 | "", | |
| 10570 | ); | |
| 10571 | }; | |
| 10572 | const operand_b: Builder.Value = extend: { | |
| 10573 | const raw = try fg.resolveInst(unwrapped.operand_b); | |
| 10574 | if (operand_b_len == operand_len) break :extend raw; | |
| 10575 | // Extend with a `shufflevector`, with a mask `<0, 1, ..., n, poison, poison, ..., poison>` | |
| 10576 | const mask_elems = llvm_elem_buf[0..operand_len]; | |
| 10577 | for (mask_elems[0..operand_b_len], 0..) |*llvm_elem, elem_idx| { | |
| 10578 | llvm_elem.* = try o.builder.intConst(.i32, elem_idx); | |
| 10579 | } | |
| 10580 | @memset(mask_elems[operand_b_len..], llvm_poison_mask_elem); | |
| 10581 | const llvm_this_operand_ty = try o.builder.vectorType(.normal, operand_b_len, llvm_elem_ty); | |
| 10582 | break :extend try fg.wip.shuffleVector( | |
| 10583 | raw, | |
| 10584 | try o.builder.poisonValue(llvm_this_operand_ty), | |
| 10585 | try o.builder.vectorValue(llvm_operand_mask_ty, mask_elems), | |
| 10586 | "", | |
| 10587 | ); | |
| 10588 | }; | |
| 10589 | ||
| 10590 | // `operand_a` and `operand_b` now have the same length (we've extended the shorter one with | |
| 10591 | // an initial shuffle if necessary). Now for the easy bit. | |
| 10592 | ||
| 10593 | const mask_elems = llvm_elem_buf[0..mask.len]; | |
| 10594 | for (mask, mask_elems) |mask_elem, *llvm_mask_elem| { | |
| 10595 | llvm_mask_elem.* = switch (mask_elem.unwrap()) { | |
| 10596 | .a_elem => |idx| try o.builder.intConst(.i32, idx), | |
| 10597 | .b_elem => |idx| try o.builder.intConst(.i32, operand_len + idx), | |
| 10598 | .undef => llvm_poison_mask_elem, | |
| 10599 | }; | |
| 10600 | } | |
| 10601 | return fg.wip.shuffleVector( | |
| 10602 | operand_a, | |
| 10603 | operand_b, | |
| 10604 | try o.builder.vectorValue(llvm_mask_ty, mask_elems), | |
| 10605 | "", | |
| 10436 | 10606 | ); |
| 10437 | return self.wip.shuffleVector(a, b, llvm_mask_value, ""); | |
| 10438 | 10607 | } |
| 10439 | 10608 | |
| 10440 | 10609 | /// Reduce a vector by repeatedly applying `llvm_fn` to produce an accumulated result. |
src/codegen/spirv.zig+63-28| ... | ... | @@ -28,6 +28,15 @@ const SpvAssembler = @import("spirv/Assembler.zig"); |
| 28 | 28 | |
| 29 | 29 | const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef); |
| 30 | 30 | |
| 31 | pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { | |
| 32 | return comptime &.initMany(&.{ | |
| 33 | .expand_intcast_safe, | |
| 34 | .expand_add_safe, | |
| 35 | .expand_sub_safe, | |
| 36 | .expand_mul_safe, | |
| 37 | }); | |
| 38 | } | |
| 39 | ||
| 31 | 40 | pub const zig_call_abi_ver = 3; |
| 32 | 41 | pub const big_int_bits = 32; |
| 33 | 42 | |
| ... | ... | @@ -3243,7 +3252,8 @@ const NavGen = struct { |
| 3243 | 3252 | |
| 3244 | 3253 | .splat => try self.airSplat(inst), |
| 3245 | 3254 | .reduce, .reduce_optimized => try self.airReduce(inst), |
| 3246 | .shuffle => try self.airShuffle(inst), | |
| 3255 | .shuffle_one => try self.airShuffleOne(inst), | |
| 3256 | .shuffle_two => try self.airShuffleTwo(inst), | |
| 3247 | 3257 | |
| 3248 | 3258 | .ptr_add => try self.airPtrAdd(inst), |
| 3249 | 3259 | .ptr_sub => try self.airPtrSub(inst), |
| ... | ... | @@ -3380,6 +3390,10 @@ const NavGen = struct { |
| 3380 | 3390 | const zcu = self.pt.zcu; |
| 3381 | 3391 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 3382 | 3392 | |
| 3393 | if (self.typeOf(bin_op.lhs).isVector(zcu) and !self.typeOf(bin_op.rhs).isVector(zcu)) { | |
| 3394 | return self.fail("vector shift with scalar rhs", .{}); | |
| 3395 | } | |
| 3396 | ||
| 3383 | 3397 | const base = try self.temporary(bin_op.lhs); |
| 3384 | 3398 | const shift = try self.temporary(bin_op.rhs); |
| 3385 | 3399 | |
| ... | ... | @@ -3866,6 +3880,10 @@ const NavGen = struct { |
| 3866 | 3880 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 3867 | 3881 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3868 | 3882 | |
| 3883 | if (self.typeOf(extra.lhs).isVector(zcu) and !self.typeOf(extra.rhs).isVector(zcu)) { | |
| 3884 | return self.fail("vector shift with scalar rhs", .{}); | |
| 3885 | } | |
| 3886 | ||
| 3869 | 3887 | const base = try self.temporary(extra.lhs); |
| 3870 | 3888 | const shift = try self.temporary(extra.rhs); |
| 3871 | 3889 | |
| ... | ... | @@ -4030,40 +4048,57 @@ const NavGen = struct { |
| 4030 | 4048 | return result_id; |
| 4031 | 4049 | } |
| 4032 | 4050 | |
| 4033 | fn airShuffle(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4034 | const pt = self.pt; | |
| 4051 | fn airShuffleOne(ng: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4052 | const pt = ng.pt; | |
| 4035 | 4053 | const zcu = pt.zcu; |
| 4036 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 4037 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; | |
| 4038 | const a = try self.resolve(extra.a); | |
| 4039 | const b = try self.resolve(extra.b); | |
| 4040 | const mask = Value.fromInterned(extra.mask); | |
| 4054 | const gpa = zcu.gpa; | |
| 4041 | 4055 | |
| 4042 | // Note: number of components in the result, a, and b may differ. | |
| 4043 | const result_ty = self.typeOfIndex(inst); | |
| 4044 | const scalar_ty = result_ty.scalarType(zcu); | |
| 4045 | const scalar_ty_id = try self.resolveType(scalar_ty, .direct); | |
| 4056 | const unwrapped = ng.air.unwrapShuffleOne(zcu, inst); | |
| 4057 | const mask = unwrapped.mask; | |
| 4058 | const result_ty = unwrapped.result_ty; | |
| 4059 | const elem_ty = result_ty.childType(zcu); | |
| 4060 | const operand = try ng.resolve(unwrapped.operand); | |
| 4046 | 4061 | |
| 4047 | const constituents = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu)); | |
| 4048 | defer self.gpa.free(constituents); | |
| 4062 | const constituents = try gpa.alloc(IdRef, mask.len); | |
| 4063 | defer gpa.free(constituents); | |
| 4049 | 4064 | |
| 4050 | for (constituents, 0..) |*id, i| { | |
| 4051 | const elem = try mask.elemValue(pt, i); | |
| 4052 | if (elem.isUndef(zcu)) { | |
| 4053 | id.* = try self.spv.constUndef(scalar_ty_id); | |
| 4054 | continue; | |
| 4055 | } | |
| 4065 | for (constituents, mask) |*id, mask_elem| { | |
| 4066 | id.* = switch (mask_elem.unwrap()) { | |
| 4067 | .elem => |idx| try ng.extractVectorComponent(elem_ty, operand, idx), | |
| 4068 | .value => |val| try ng.constant(elem_ty, .fromInterned(val), .direct), | |
| 4069 | }; | |
| 4070 | } | |
| 4056 | 4071 | |
| 4057 | const index = elem.toSignedInt(zcu); | |
| 4058 | if (index >= 0) { | |
| 4059 | id.* = try self.extractVectorComponent(scalar_ty, a, @intCast(index)); | |
| 4060 | } else { | |
| 4061 | id.* = try self.extractVectorComponent(scalar_ty, b, @intCast(~index)); | |
| 4062 | } | |
| 4072 | const result_ty_id = try ng.resolveType(result_ty, .direct); | |
| 4073 | return try ng.constructComposite(result_ty_id, constituents); | |
| 4074 | } | |
| 4075 | ||
| 4076 | fn airShuffleTwo(ng: *NavGen, inst: Air.Inst.Index) !?IdRef { | |
| 4077 | const pt = ng.pt; | |
| 4078 | const zcu = pt.zcu; | |
| 4079 | const gpa = zcu.gpa; | |
| 4080 | ||
| 4081 | const unwrapped = ng.air.unwrapShuffleTwo(zcu, inst); | |
| 4082 | const mask = unwrapped.mask; | |
| 4083 | const result_ty = unwrapped.result_ty; | |
| 4084 | const elem_ty = result_ty.childType(zcu); | |
| 4085 | const elem_ty_id = try ng.resolveType(elem_ty, .direct); | |
| 4086 | const operand_a = try ng.resolve(unwrapped.operand_a); | |
| 4087 | const operand_b = try ng.resolve(unwrapped.operand_b); | |
| 4088 | ||
| 4089 | const constituents = try gpa.alloc(IdRef, mask.len); | |
| 4090 | defer gpa.free(constituents); | |
| 4091 | ||
| 4092 | for (constituents, mask) |*id, mask_elem| { | |
| 4093 | id.* = switch (mask_elem.unwrap()) { | |
| 4094 | .a_elem => |idx| try ng.extractVectorComponent(elem_ty, operand_a, idx), | |
| 4095 | .b_elem => |idx| try ng.extractVectorComponent(elem_ty, operand_b, idx), | |
| 4096 | .undef => try ng.spv.constUndef(elem_ty_id), | |
| 4097 | }; | |
| 4063 | 4098 | } |
| 4064 | 4099 | |
| 4065 | const result_ty_id = try self.resolveType(result_ty, .direct); | |
| 4066 | return try self.constructComposite(result_ty_id, constituents); | |
| 4100 | const result_ty_id = try ng.resolveType(result_ty, .direct); | |
| 4101 | return try ng.constructComposite(result_ty_id, constituents); | |
| 4067 | 4102 | } |
| 4068 | 4103 | |
| 4069 | 4104 | fn indicesToIds(self: *NavGen, indices: []const u32) ![]IdRef { |
src/dev.zig+6| ... | ... | @@ -1,5 +1,8 @@ |
| 1 | 1 | pub const Env = enum { |
| 2 | 2 | /// zig1 features |
| 3 | /// - `-ofmt=c` only | |
| 4 | /// - `-OReleaseFast` or `-OReleaseSmall` only | |
| 5 | /// - no `@setRuntimeSafety(true)` | |
| 3 | 6 | bootstrap, |
| 4 | 7 | |
| 5 | 8 | /// zig2 features |
| ... | ... | @@ -67,6 +70,7 @@ pub const Env = enum { |
| 67 | 70 | .incremental, |
| 68 | 71 | .ast_gen, |
| 69 | 72 | .sema, |
| 73 | .legalize, | |
| 70 | 74 | .llvm_backend, |
| 71 | 75 | .c_backend, |
| 72 | 76 | .wasm_backend, |
| ... | ... | @@ -144,6 +148,7 @@ pub const Env = enum { |
| 144 | 148 | .build_command, |
| 145 | 149 | .stdio_listen, |
| 146 | 150 | .incremental, |
| 151 | .legalize, | |
| 147 | 152 | .x86_64_backend, |
| 148 | 153 | .elf_linker, |
| 149 | 154 | => true, |
| ... | ... | @@ -222,6 +227,7 @@ pub const Feature = enum { |
| 222 | 227 | incremental, |
| 223 | 228 | ast_gen, |
| 224 | 229 | sema, |
| 230 | legalize, | |
| 225 | 231 | |
| 226 | 232 | llvm_backend, |
| 227 | 233 | c_backend, |
src/mutable_value.zig+2-2| ... | ... | @@ -260,7 +260,7 @@ pub const MutableValue = union(enum) { |
| 260 | 260 | const ptr = try arena.create(MutableValue); |
| 261 | 261 | const len = try arena.create(MutableValue); |
| 262 | 262 | ptr.* = .{ .interned = try pt.intern(.{ .undef = ip.slicePtrType(ty_ip) }) }; |
| 263 | len.* = .{ .interned = try pt.intern(.{ .undef = .usize_type }) }; | |
| 263 | len.* = .{ .interned = .undef_usize }; | |
| 264 | 264 | mv.* = .{ .slice = .{ |
| 265 | 265 | .ty = ty_ip, |
| 266 | 266 | .ptr = ptr, |
| ... | ... | @@ -464,7 +464,7 @@ pub const MutableValue = union(enum) { |
| 464 | 464 | return switch (field_idx) { |
| 465 | 465 | Value.slice_ptr_index => .{ .interned = Value.fromInterned(ip_index).slicePtr(pt.zcu).toIntern() }, |
| 466 | 466 | Value.slice_len_index => .{ .interned = switch (pt.zcu.intern_pool.indexToKey(ip_index)) { |
| 467 | .undef => try pt.intern(.{ .undef = .usize_type }), | |
| 467 | .undef => .undef_usize, | |
| 468 | 468 | .slice => |s| s.len, |
| 469 | 469 | else => unreachable, |
| 470 | 470 | } }, |
src/print_air.zig+33-7| ... | ... | @@ -315,7 +315,8 @@ const Writer = struct { |
| 315 | 315 | .wasm_memory_grow => try w.writeWasmMemoryGrow(s, inst), |
| 316 | 316 | .mul_add => try w.writeMulAdd(s, inst), |
| 317 | 317 | .select => try w.writeSelect(s, inst), |
| 318 | .shuffle => try w.writeShuffle(s, inst), | |
| 318 | .shuffle_one => try w.writeShuffleOne(s, inst), | |
| 319 | .shuffle_two => try w.writeShuffleTwo(s, inst), | |
| 319 | 320 | .reduce, .reduce_optimized => try w.writeReduce(s, inst), |
| 320 | 321 | .cmp_vector, .cmp_vector_optimized => try w.writeCmpVector(s, inst), |
| 321 | 322 | .vector_store_elem => try w.writeVectorStoreElem(s, inst), |
| ... | ... | @@ -499,14 +500,39 @@ const Writer = struct { |
| 499 | 500 | try w.writeOperand(s, inst, 2, pl_op.operand); |
| 500 | 501 | } |
| 501 | 502 | |
| 502 | fn writeShuffle(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | |
| 503 | const ty_pl = w.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | |
| 504 | const extra = w.air.extraData(Air.Shuffle, ty_pl.payload).data; | |
| 503 | fn writeShuffleOne(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | |
| 504 | const unwrapped = w.air.unwrapShuffleOne(w.pt.zcu, inst); | |
| 505 | try w.writeType(s, unwrapped.result_ty); | |
| 506 | try s.writeAll(", "); | |
| 507 | try w.writeOperand(s, inst, 0, unwrapped.operand); | |
| 508 | try s.writeAll(", ["); | |
| 509 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | |
| 510 | if (mask_idx > 0) try s.writeAll(", "); | |
| 511 | switch (mask_elem.unwrap()) { | |
| 512 | .elem => |idx| try s.print("elem {d}", .{idx}), | |
| 513 | .value => |val| try s.print("val {}", .{Value.fromInterned(val).fmtValue(w.pt)}), | |
| 514 | } | |
| 515 | } | |
| 516 | try s.writeByte(']'); | |
| 517 | } | |
| 505 | 518 | |
| 506 | try w.writeOperand(s, inst, 0, extra.a); | |
| 519 | fn writeShuffleTwo(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | |
| 520 | const unwrapped = w.air.unwrapShuffleTwo(w.pt.zcu, inst); | |
| 521 | try w.writeType(s, unwrapped.result_ty); | |
| 522 | try s.writeAll(", "); | |
| 523 | try w.writeOperand(s, inst, 0, unwrapped.operand_a); | |
| 507 | 524 | try s.writeAll(", "); |
| 508 | try w.writeOperand(s, inst, 1, extra.b); | |
| 509 | try s.print(", mask {d}, len {d}", .{ extra.mask, extra.mask_len }); | |
| 525 | try w.writeOperand(s, inst, 1, unwrapped.operand_b); | |
| 526 | try s.writeAll(", ["); | |
| 527 | for (unwrapped.mask, 0..) |mask_elem, mask_idx| { | |
| 528 | if (mask_idx > 0) try s.writeAll(", "); | |
| 529 | switch (mask_elem.unwrap()) { | |
| 530 | .a_elem => |idx| try s.print("a_elem {d}", .{idx}), | |
| 531 | .b_elem => |idx| try s.print("b_elem {d}", .{idx}), | |
| 532 | .undef => try s.writeAll("undef"), | |
| 533 | } | |
| 534 | } | |
| 535 | try s.writeByte(']'); | |
| 510 | 536 | } |
| 511 | 537 | |
| 512 | 538 | fn writeSelect(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
src/target.zig-8| ... | ... | @@ -842,17 +842,9 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt |
| 842 | 842 | .stage2_c, .stage2_llvm, .stage2_x86_64 => true, |
| 843 | 843 | else => false, |
| 844 | 844 | }, |
| 845 | .safety_checked_instructions => switch (backend) { | |
| 846 | .stage2_llvm => true, | |
| 847 | else => false, | |
| 848 | }, | |
| 849 | 845 | .separate_thread => switch (backend) { |
| 850 | 846 | .stage2_llvm => false, |
| 851 | 847 | else => true, |
| 852 | 848 | }, |
| 853 | .all_vector_instructions => switch (backend) { | |
| 854 | .stage2_x86_64 => true, | |
| 855 | else => false, | |
| 856 | }, | |
| 857 | 849 | }; |
| 858 | 850 | } |
stage1/zig.h+21-11| ... | ... | @@ -481,6 +481,7 @@ |
| 481 | 481 | |
| 482 | 482 | zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t); |
| 483 | 483 | zig_extern void *memset (void *, int, size_t); |
| 484 | zig_extern void *memmove (void *, void const *, size_t); | |
| 484 | 485 | |
| 485 | 486 | /* ================ Bool and 8/16/32/64-bit Integer Support ================= */ |
| 486 | 487 | |
| ... | ... | @@ -1114,14 +1115,15 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t |
| 1114 | 1115 | \ |
| 1115 | 1116 | static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ |
| 1116 | 1117 | uint##w##_t res; \ |
| 1117 | if (rhs >= bits) return lhs != UINT##w##_C(0) ? zig_maxInt_u(w, bits) : lhs; \ | |
| 1118 | return zig_shlo_u##w(&res, lhs, (uint8_t)rhs, bits) ? zig_maxInt_u(w, bits) : res; \ | |
| 1118 | if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \ | |
| 1119 | return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \ | |
| 1119 | 1120 | } \ |
| 1120 | 1121 | \ |
| 1121 | static inline int##w##_t zig_shls_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ | |
| 1122 | static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ | |
| 1122 | 1123 | int##w##_t res; \ |
| 1123 | if ((uint##w##_t)rhs < (uint##w##_t)bits && !zig_shlo_i##w(&res, lhs, (uint8_t)rhs, bits)) return res; \ | |
| 1124 | return lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ | |
| 1124 | if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \ | |
| 1125 | return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ | |
| 1126 | lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ | |
| 1125 | 1127 | } \ |
| 1126 | 1128 | \ |
| 1127 | 1129 | static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ |
| ... | ... | @@ -1850,15 +1852,23 @@ static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8 |
| 1850 | 1852 | |
| 1851 | 1853 | static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
| 1852 | 1854 | zig_u128 res; |
| 1853 | if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) >= INT32_C(0)) | |
| 1854 | return zig_cmp_u128(lhs, zig_make_u128(0, 0)) != INT32_C(0) ? zig_maxInt_u(128, bits) : lhs; | |
| 1855 | return zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits) ? zig_maxInt_u(128, bits) : res; | |
| 1855 | if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; | |
| 1856 | switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) { | |
| 1857 | case 0: return zig_make_u128(0, 0); | |
| 1858 | case 1: return zig_maxInt_u(128, bits); | |
| 1859 | default: zig_unreachable(); | |
| 1860 | } | |
| 1856 | 1861 | } |
| 1857 | 1862 | |
| 1858 | static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { | |
| 1863 | static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { | |
| 1859 | 1864 | zig_i128 res; |
| 1860 | if (zig_cmp_u128(zig_bitCast_u128(rhs), zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_i128(rhs), bits)) return res; | |
| 1861 | return zig_cmp_i128(lhs, zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits); | |
| 1865 | if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; | |
| 1866 | switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) { | |
| 1867 | case -1: return zig_minInt_i(128, bits); | |
| 1868 | case 0: return zig_make_i128(0, 0); | |
| 1869 | case 1: return zig_maxInt_i(128, bits); | |
| 1870 | default: zig_unreachable(); | |
| 1871 | } | |
| 1862 | 1872 | } |
| 1863 | 1873 | |
| 1864 | 1874 | static inline zig_u128 zig_adds_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
stage1/zig1.wasm| Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ |
test/behavior/abs.zig-2| ... | ... | @@ -96,7 +96,6 @@ test "@abs big int <= 128 bits" { |
| 96 | 96 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 97 | 97 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO |
| 98 | 98 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 99 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 100 | 99 | |
| 101 | 100 | try comptime testAbsSignedBigInt(); |
| 102 | 101 | try testAbsSignedBigInt(); |
| ... | ... | @@ -211,7 +210,6 @@ fn testAbsFloats(comptime T: type) !void { |
| 211 | 210 | test "@abs int vectors" { |
| 212 | 211 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 213 | 212 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 214 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 215 | 213 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 216 | 214 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 217 | 215 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/basic.zig-1| ... | ... | @@ -837,7 +837,6 @@ test "extern variable with non-pointer opaque type" { |
| 837 | 837 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 838 | 838 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 839 | 839 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 840 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 841 | 840 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO |
| 842 | 841 | |
| 843 | 842 | @export(&var_to_export, .{ .name = "opaque_extern_var" }); |
test/behavior/bitcast.zig-1| ... | ... | @@ -384,7 +384,6 @@ test "comptime bitcast with fields following f80" { |
| 384 | 384 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 385 | 385 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 386 | 386 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 387 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 388 | 387 | |
| 389 | 388 | const FloatT = extern struct { f: f80, x: u128 align(16) }; |
| 390 | 389 | const x: FloatT = .{ .f = 0.5, .x = 123 }; |
test/behavior/bitreverse.zig-4| ... | ... | @@ -12,7 +12,6 @@ test "@bitReverse" { |
| 12 | 12 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 13 | 13 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 14 | 14 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 15 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 16 | 15 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 17 | 16 | |
| 18 | 17 | try comptime testBitReverse(); |
| ... | ... | @@ -123,7 +122,6 @@ fn vector8() !void { |
| 123 | 122 | |
| 124 | 123 | test "bitReverse vectors u8" { |
| 125 | 124 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 126 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 127 | 125 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 128 | 126 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 129 | 127 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -144,7 +142,6 @@ fn vector16() !void { |
| 144 | 142 | |
| 145 | 143 | test "bitReverse vectors u16" { |
| 146 | 144 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 147 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 148 | 145 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 149 | 146 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 150 | 147 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -165,7 +162,6 @@ fn vector24() !void { |
| 165 | 162 | |
| 166 | 163 | test "bitReverse vectors u24" { |
| 167 | 164 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 168 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 169 | 165 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 170 | 166 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 171 | 167 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/byteswap.zig-4| ... | ... | @@ -39,7 +39,6 @@ test "@byteSwap integers" { |
| 39 | 39 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 40 | 40 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 41 | 41 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 42 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 43 | 42 | |
| 44 | 43 | const ByteSwapIntTest = struct { |
| 45 | 44 | fn run() !void { |
| ... | ... | @@ -95,7 +94,6 @@ fn vector8() !void { |
| 95 | 94 | |
| 96 | 95 | test "@byteSwap vectors u8" { |
| 97 | 96 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 98 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 99 | 97 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 100 | 98 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 101 | 99 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -116,7 +114,6 @@ fn vector16() !void { |
| 116 | 114 | |
| 117 | 115 | test "@byteSwap vectors u16" { |
| 118 | 116 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 119 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 120 | 117 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 121 | 118 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 122 | 119 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -137,7 +134,6 @@ fn vector24() !void { |
| 137 | 134 | |
| 138 | 135 | test "@byteSwap vectors u24" { |
| 139 | 136 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 140 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 141 | 137 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 142 | 138 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 143 | 139 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/cast.zig-4| ... | ... | @@ -617,7 +617,6 @@ test "@intCast on vector" { |
| 617 | 617 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 618 | 618 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 619 | 619 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 620 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 621 | 620 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 622 | 621 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 623 | 622 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| ... | ... | @@ -2520,7 +2519,6 @@ test "@ptrFromInt on vector" { |
| 2520 | 2519 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2521 | 2520 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2522 | 2521 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 2523 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 2524 | 2522 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 2525 | 2523 | |
| 2526 | 2524 | const S = struct { |
| ... | ... | @@ -2592,7 +2590,6 @@ test "@intFromFloat on vector" { |
| 2592 | 2590 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2593 | 2591 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2594 | 2592 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 2595 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 2596 | 2593 | |
| 2597 | 2594 | const S = struct { |
| 2598 | 2595 | fn doTheTest() !void { |
| ... | ... | @@ -2693,7 +2690,6 @@ test "@intCast vector of signed integer" { |
| 2693 | 2690 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2694 | 2691 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 2695 | 2692 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2696 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 2697 | 2693 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 2698 | 2694 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 2699 | 2695 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
test/behavior/extern.zig-1| ... | ... | @@ -5,7 +5,6 @@ const expect = std.testing.expect; |
| 5 | 5 | test "anyopaque extern symbol" { |
| 6 | 6 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 7 | 7 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 8 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 9 | 8 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 10 | 9 | |
| 11 | 10 | const a = @extern(*anyopaque, .{ .name = "a_mystery_symbol" }); |
test/behavior/floatop.zig+36-15| ... | ... | @@ -14,9 +14,11 @@ fn epsForType(comptime T: type) T { |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | test "add f16" { |
| 17 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 18 | 17 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 19 | 18 | |
| 19 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 20 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest; | |
| 21 | ||
| 20 | 22 | try testAdd(f16); |
| 21 | 23 | try comptime testAdd(f16); |
| 22 | 24 | } |
| ... | ... | @@ -123,10 +125,12 @@ fn testMul(comptime T: type) !void { |
| 123 | 125 | |
| 124 | 126 | test "cmp f16" { |
| 125 | 127 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 126 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 127 | 128 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 128 | 129 | if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 |
| 129 | 130 | |
| 131 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 132 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest; | |
| 133 | ||
| 130 | 134 | try testCmp(f16); |
| 131 | 135 | try comptime testCmp(f16); |
| 132 | 136 | } |
| ... | ... | @@ -135,7 +139,6 @@ test "cmp f32" { |
| 135 | 139 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 136 | 140 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 137 | 141 | if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 |
| 138 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 139 | 142 | |
| 140 | 143 | try testCmp(f32); |
| 141 | 144 | try comptime testCmp(f32); |
| ... | ... | @@ -144,7 +147,6 @@ test "cmp f32" { |
| 144 | 147 | test "cmp f64" { |
| 145 | 148 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 146 | 149 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 147 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 148 | 150 | if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 |
| 149 | 151 | |
| 150 | 152 | try testCmp(f64); |
| ... | ... | @@ -340,9 +342,11 @@ test "different sized float comparisons" { |
| 340 | 342 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 341 | 343 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 342 | 344 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 343 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 344 | 345 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 345 | 346 | |
| 347 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 348 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest; | |
| 349 | ||
| 346 | 350 | try testDifferentSizedFloatComparisons(); |
| 347 | 351 | try comptime testDifferentSizedFloatComparisons(); |
| 348 | 352 | } |
| ... | ... | @@ -388,10 +392,12 @@ test "@sqrt f16" { |
| 388 | 392 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 389 | 393 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 390 | 394 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 391 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 392 | 395 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 393 | 396 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 394 | 397 | |
| 398 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 399 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest; | |
| 400 | ||
| 395 | 401 | try testSqrt(f16); |
| 396 | 402 | try comptime testSqrt(f16); |
| 397 | 403 | } |
| ... | ... | @@ -400,7 +406,6 @@ test "@sqrt f32/f64" { |
| 400 | 406 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 401 | 407 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 402 | 408 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 403 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 404 | 409 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 405 | 410 | |
| 406 | 411 | try testSqrt(f32); |
| ... | ... | @@ -1132,9 +1137,11 @@ test "@abs f16" { |
| 1132 | 1137 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1133 | 1138 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1134 | 1139 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1135 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1136 | 1140 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1137 | 1141 | |
| 1142 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 1143 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest; | |
| 1144 | ||
| 1138 | 1145 | try testFabs(f16); |
| 1139 | 1146 | try comptime testFabs(f16); |
| 1140 | 1147 | } |
| ... | ... | @@ -1266,9 +1273,11 @@ test "@floor f32/f64" { |
| 1266 | 1273 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1267 | 1274 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1268 | 1275 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1269 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1270 | 1276 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1271 | 1277 | |
| 1278 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 1279 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | |
| 1280 | ||
| 1272 | 1281 | try testFloor(f32); |
| 1273 | 1282 | try comptime testFloor(f32); |
| 1274 | 1283 | try testFloor(f64); |
| ... | ... | @@ -1332,7 +1341,9 @@ test "@floor with vectors" { |
| 1332 | 1341 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1333 | 1342 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1334 | 1343 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1335 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1344 | ||
| 1345 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 1346 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | |
| 1336 | 1347 | |
| 1337 | 1348 | try testFloorWithVectors(); |
| 1338 | 1349 | try comptime testFloorWithVectors(); |
| ... | ... | @@ -1363,9 +1374,11 @@ test "@ceil f32/f64" { |
| 1363 | 1374 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1364 | 1375 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1365 | 1376 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1366 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1367 | 1377 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1368 | 1378 | |
| 1379 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 1380 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | |
| 1381 | ||
| 1369 | 1382 | try testCeil(f32); |
| 1370 | 1383 | try comptime testCeil(f32); |
| 1371 | 1384 | try testCeil(f64); |
| ... | ... | @@ -1429,7 +1442,9 @@ test "@ceil with vectors" { |
| 1429 | 1442 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1430 | 1443 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1431 | 1444 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1432 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1445 | ||
| 1446 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 1447 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | |
| 1433 | 1448 | |
| 1434 | 1449 | try testCeilWithVectors(); |
| 1435 | 1450 | try comptime testCeilWithVectors(); |
| ... | ... | @@ -1460,9 +1475,11 @@ test "@trunc f32/f64" { |
| 1460 | 1475 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1461 | 1476 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1462 | 1477 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1463 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1464 | 1478 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1465 | 1479 | |
| 1480 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 1481 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | |
| 1482 | ||
| 1466 | 1483 | try testTrunc(f32); |
| 1467 | 1484 | try comptime testTrunc(f32); |
| 1468 | 1485 | try testTrunc(f64); |
| ... | ... | @@ -1526,7 +1543,9 @@ test "@trunc with vectors" { |
| 1526 | 1543 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1527 | 1544 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1528 | 1545 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1529 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1546 | ||
| 1547 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 1548 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | |
| 1530 | 1549 | |
| 1531 | 1550 | try testTruncWithVectors(); |
| 1532 | 1551 | try comptime testTruncWithVectors(); |
| ... | ... | @@ -1546,9 +1565,11 @@ test "neg f16" { |
| 1546 | 1565 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1547 | 1566 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1548 | 1567 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1549 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1550 | 1568 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1551 | 1569 | |
| 1570 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 1571 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest; | |
| 1572 | ||
| 1552 | 1573 | if (builtin.os.tag == .freebsd) { |
| 1553 | 1574 | // TODO file issue to track this failure |
| 1554 | 1575 | return error.SkipZigTest; |
test/behavior/fn.zig-1| ... | ... | @@ -429,7 +429,6 @@ test "implicit cast function to function ptr" { |
| 429 | 429 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 430 | 430 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 431 | 431 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 432 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 433 | 432 | |
| 434 | 433 | const S1 = struct { |
| 435 | 434 | export fn someFunctionThatReturnsAValue() c_int { |
test/behavior/math.zig+7-13| ... | ... | @@ -85,7 +85,6 @@ test "@clz big ints" { |
| 85 | 85 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 86 | 86 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 87 | 87 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 88 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 89 | 88 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 90 | 89 | |
| 91 | 90 | try testClzBigInts(); |
| ... | ... | @@ -103,7 +102,6 @@ fn testOneClz(comptime T: type, x: T) u32 { |
| 103 | 102 | |
| 104 | 103 | test "@clz vectors" { |
| 105 | 104 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 106 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 107 | 105 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 108 | 106 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 109 | 107 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -173,7 +171,6 @@ fn testOneCtz(comptime T: type, x: T) u32 { |
| 173 | 171 | } |
| 174 | 172 | |
| 175 | 173 | test "@ctz 128-bit integers" { |
| 176 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 177 | 174 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 178 | 175 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 179 | 176 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -193,7 +190,6 @@ fn testCtz128() !void { |
| 193 | 190 | |
| 194 | 191 | test "@ctz vectors" { |
| 195 | 192 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 196 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 197 | 193 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 198 | 194 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 199 | 195 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -475,10 +471,12 @@ test "division" { |
| 475 | 471 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 476 | 472 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 477 | 473 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 478 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 479 | 474 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 480 | 475 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 481 | 476 | |
| 477 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 478 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest; | |
| 479 | ||
| 482 | 480 | try testIntDivision(); |
| 483 | 481 | try comptime testIntDivision(); |
| 484 | 482 | |
| ... | ... | @@ -1623,10 +1621,10 @@ test "vector integer addition" { |
| 1623 | 1621 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1624 | 1622 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1625 | 1623 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1626 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1627 | 1624 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1628 | 1625 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1629 | 1626 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1627 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1630 | 1628 | |
| 1631 | 1629 | const S = struct { |
| 1632 | 1630 | fn doTheTest() !void { |
| ... | ... | @@ -1694,9 +1692,6 @@ test "vector comparison" { |
| 1694 | 1692 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1695 | 1693 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1696 | 1694 | |
| 1697 | if (builtin.zig_backend == .stage2_x86_64 and | |
| 1698 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx2)) return error.SkipZigTest; | |
| 1699 | ||
| 1700 | 1695 | const S = struct { |
| 1701 | 1696 | fn doTheTest() !void { |
| 1702 | 1697 | var a: @Vector(6, i32) = [_]i32{ 1, 3, -1, 5, 7, 9 }; |
| ... | ... | @@ -1785,7 +1780,6 @@ test "mod lazy values" { |
| 1785 | 1780 | |
| 1786 | 1781 | test "@clz works on both vector and scalar inputs" { |
| 1787 | 1782 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1788 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1789 | 1783 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1790 | 1784 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1791 | 1785 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1807,7 +1801,6 @@ test "runtime comparison to NaN is comptime-known" { |
| 1807 | 1801 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1808 | 1802 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1809 | 1803 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1810 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1811 | 1804 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1812 | 1805 | if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 |
| 1813 | 1806 | |
| ... | ... | @@ -1838,7 +1831,6 @@ test "runtime int comparison to inf is comptime-known" { |
| 1838 | 1831 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1839 | 1832 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1840 | 1833 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1841 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1842 | 1834 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1843 | 1835 | if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 |
| 1844 | 1836 | |
| ... | ... | @@ -1936,7 +1928,9 @@ test "float vector division of comptime zero by runtime nan is nan" { |
| 1936 | 1928 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1937 | 1929 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1938 | 1930 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1939 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1931 | ||
| 1932 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 1933 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; | |
| 1940 | 1934 | |
| 1941 | 1935 | const ct_zero: @Vector(1, f32) = .{0}; |
| 1942 | 1936 | var rt_nan: @Vector(1, f32) = .{math.nan(f32)}; |
test/behavior/maximum_minimum.zig-6| ... | ... | @@ -34,7 +34,6 @@ test "@max on vectors" { |
| 34 | 34 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 35 | 35 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 36 | 36 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 37 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 38 | 37 | |
| 39 | 38 | const S = struct { |
| 40 | 39 | fn doTheTest() !void { |
| ... | ... | @@ -90,7 +89,6 @@ test "@min for vectors" { |
| 90 | 89 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 91 | 90 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 92 | 91 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 93 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 94 | 92 | |
| 95 | 93 | const S = struct { |
| 96 | 94 | fn doTheTest() !void { |
| ... | ... | @@ -206,7 +204,6 @@ test "@min/@max notices vector bounds" { |
| 206 | 204 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 207 | 205 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 208 | 206 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 209 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 210 | 207 | |
| 211 | 208 | var x: @Vector(2, u16) = .{ 140, 40 }; |
| 212 | 209 | const y: @Vector(2, u64) = .{ 5, 100 }; |
| ... | ... | @@ -260,7 +257,6 @@ test "@min/@max notices bounds from vector types" { |
| 260 | 257 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 261 | 258 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 262 | 259 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 263 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 264 | 260 | |
| 265 | 261 | var x: @Vector(2, u16) = .{ 30, 67 }; |
| 266 | 262 | var y: @Vector(2, u32) = .{ 20, 500 }; |
| ... | ... | @@ -303,7 +299,6 @@ test "@min/@max notices bounds from vector types when element of comptime-known |
| 303 | 299 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 304 | 300 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 305 | 301 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 306 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 307 | 302 | |
| 308 | 303 | var x: @Vector(2, u32) = .{ 1_000_000, 12345 }; |
| 309 | 304 | _ = &x; |
| ... | ... | @@ -375,7 +370,6 @@ test "@min/@max with runtime vectors of signed and unsigned integers of same siz |
| 375 | 370 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 376 | 371 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 377 | 372 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 378 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 379 | 373 | |
| 380 | 374 | const S = struct { |
| 381 | 375 | fn min(a: @Vector(2, i32), b: @Vector(2, u32)) @Vector(2, i32) { |
test/behavior/muladd.zig+9-3| ... | ... | @@ -6,10 +6,12 @@ test "@mulAdd" { |
| 6 | 6 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 7 | 7 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 8 | 8 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 10 | 9 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 11 | 10 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 12 | 11 | |
| 12 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 13 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .fma)) return error.SkipZigTest; | |
| 14 | ||
| 13 | 15 | try comptime testMulAdd(); |
| 14 | 16 | try testMulAdd(); |
| 15 | 17 | } |
| ... | ... | @@ -137,10 +139,12 @@ test "vector f32" { |
| 137 | 139 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 138 | 140 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 139 | 141 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 140 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 141 | 142 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 142 | 143 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 143 | 144 | |
| 145 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 146 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .fma)) return error.SkipZigTest; | |
| 147 | ||
| 144 | 148 | try comptime vector32(); |
| 145 | 149 | try vector32(); |
| 146 | 150 | } |
| ... | ... | @@ -163,10 +167,12 @@ test "vector f64" { |
| 163 | 167 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 164 | 168 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 165 | 169 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 166 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 167 | 170 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 168 | 171 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 169 | 172 | |
| 173 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 174 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .fma)) return error.SkipZigTest; | |
| 175 | ||
| 170 | 176 | try comptime vector64(); |
| 171 | 177 | try vector64(); |
| 172 | 178 | } |
test/behavior/packed-struct.zig+11| ... | ... | @@ -1307,6 +1307,17 @@ test "packed struct equality" { |
| 1307 | 1307 | comptime try S.doTest(x, y); |
| 1308 | 1308 | } |
| 1309 | 1309 | |
| 1310 | test "packed struct equality ignores padding bits" { | |
| 1311 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1312 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | |
| 1313 | ||
| 1314 | const S = packed struct { b: bool }; | |
| 1315 | var s: S = undefined; | |
| 1316 | s.b = true; | |
| 1317 | try std.testing.expect(s != S{ .b = false }); | |
| 1318 | try std.testing.expect(s == S{ .b = true }); | |
| 1319 | } | |
| 1320 | ||
| 1310 | 1321 | test "packed struct with signed field" { |
| 1311 | 1322 | var s: packed struct { |
| 1312 | 1323 | a: i2, |
test/behavior/popcount.zig-1| ... | ... | @@ -77,7 +77,6 @@ fn testPopCountIntegers() !void { |
| 77 | 77 | |
| 78 | 78 | test "@popCount vectors" { |
| 79 | 79 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 80 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 81 | 80 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 82 | 81 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 83 | 82 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/select.zig-3| ... | ... | @@ -41,8 +41,6 @@ test "@select arrays" { |
| 41 | 41 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 42 | 42 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 43 | 43 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 44 | if (builtin.zig_backend == .stage2_x86_64 and | |
| 45 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx2)) return error.SkipZigTest; | |
| 46 | 44 | |
| 47 | 45 | try comptime selectArrays(); |
| 48 | 46 | try selectArrays(); |
| ... | ... | @@ -70,7 +68,6 @@ fn selectArrays() !void { |
| 70 | 68 | test "@select compare result" { |
| 71 | 69 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 72 | 70 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 73 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 74 | 71 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 75 | 72 | |
| 76 | 73 | const S = struct { |
test/behavior/shuffle.zig-5| ... | ... | @@ -10,8 +10,6 @@ test "@shuffle int" { |
| 10 | 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 11 | 11 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 12 | 12 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 13 | if (builtin.zig_backend == .stage2_x86_64 and | |
| 14 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3)) return error.SkipZigTest; | |
| 15 | 13 | |
| 16 | 14 | const S = struct { |
| 17 | 15 | fn doTheTest() !void { |
| ... | ... | @@ -53,7 +51,6 @@ test "@shuffle int" { |
| 53 | 51 | |
| 54 | 52 | test "@shuffle int strange sizes" { |
| 55 | 53 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 56 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 57 | 54 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 58 | 55 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 59 | 56 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -136,7 +133,6 @@ fn testShuffle( |
| 136 | 133 | |
| 137 | 134 | test "@shuffle bool 1" { |
| 138 | 135 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 139 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 140 | 136 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 141 | 137 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 142 | 138 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -160,7 +156,6 @@ test "@shuffle bool 1" { |
| 160 | 156 | |
| 161 | 157 | test "@shuffle bool 2" { |
| 162 | 158 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 163 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 164 | 159 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 165 | 160 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 166 | 161 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
test/behavior/union.zig+1| ... | ... | @@ -282,6 +282,7 @@ test "cast union to tag type of union" { |
| 282 | 282 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 283 | 283 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 284 | 284 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 285 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 285 | 286 | |
| 286 | 287 | try testCastUnionToTag(); |
| 287 | 288 | try comptime testCastUnionToTag(); |
test/behavior/vector.zig+9-20| ... | ... | @@ -31,7 +31,6 @@ test "vector wrap operators" { |
| 31 | 31 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 32 | 32 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 33 | 33 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 34 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 35 | 34 | |
| 36 | 35 | const S = struct { |
| 37 | 36 | fn doTheTest() !void { |
| ... | ... | @@ -76,12 +75,12 @@ test "vector bin compares with mem.eql" { |
| 76 | 75 | |
| 77 | 76 | test "vector int operators" { |
| 78 | 77 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 79 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 80 | 78 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 81 | 79 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 82 | 80 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 83 | 81 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 84 | 82 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 83 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 85 | 84 | |
| 86 | 85 | const S = struct { |
| 87 | 86 | fn doTheTest() !void { |
| ... | ... | @@ -249,9 +248,11 @@ test "array to vector with element type coercion" { |
| 249 | 248 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 250 | 249 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 251 | 250 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 252 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 253 | 251 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 254 | 252 | |
| 253 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt == .coff and | |
| 254 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest; | |
| 255 | ||
| 255 | 256 | const S = struct { |
| 256 | 257 | fn doTheTest() !void { |
| 257 | 258 | var foo: f16 = 3.14; |
| ... | ... | @@ -286,11 +287,11 @@ test "peer type resolution with coercible element types" { |
| 286 | 287 | |
| 287 | 288 | test "tuple to vector" { |
| 288 | 289 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 289 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 290 | 290 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 291 | 291 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 292 | 292 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 293 | 293 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 294 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 294 | 295 | |
| 295 | 296 | const S = struct { |
| 296 | 297 | fn doTheTest() !void { |
| ... | ... | @@ -652,7 +653,6 @@ test "vector division operators" { |
| 652 | 653 | test "vector bitwise not operator" { |
| 653 | 654 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 654 | 655 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 655 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 656 | 656 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 657 | 657 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 658 | 658 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -684,12 +684,12 @@ test "vector bitwise not operator" { |
| 684 | 684 | |
| 685 | 685 | test "vector shift operators" { |
| 686 | 686 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 687 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 688 | 687 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 689 | 688 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 690 | 689 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 691 | 690 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 692 | 691 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 692 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 693 | 693 | |
| 694 | 694 | const S = struct { |
| 695 | 695 | fn doTheTestShift(x: anytype, y: anytype) !void { |
| ... | ... | @@ -908,8 +908,6 @@ test "mask parameter of @shuffle is comptime scope" { |
| 908 | 908 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 909 | 909 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 910 | 910 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 911 | if (builtin.zig_backend == .stage2_x86_64 and | |
| 912 | !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .ssse3)) return error.SkipZigTest; | |
| 913 | 911 | |
| 914 | 912 | const __v4hi = @Vector(4, i16); |
| 915 | 913 | var v4_a = __v4hi{ 1, 2, 3, 4 }; |
| ... | ... | @@ -934,7 +932,6 @@ test "saturating add" { |
| 934 | 932 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 935 | 933 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 936 | 934 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 937 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 938 | 935 | |
| 939 | 936 | const S = struct { |
| 940 | 937 | fn doTheTest() !void { |
| ... | ... | @@ -969,7 +966,6 @@ test "saturating subtraction" { |
| 969 | 966 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 970 | 967 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 971 | 968 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 972 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 973 | 969 | |
| 974 | 970 | const S = struct { |
| 975 | 971 | fn doTheTest() !void { |
| ... | ... | @@ -989,7 +985,6 @@ test "saturating subtraction" { |
| 989 | 985 | |
| 990 | 986 | test "saturating multiplication" { |
| 991 | 987 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 992 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 993 | 988 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 994 | 989 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 995 | 990 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1018,12 +1013,12 @@ test "saturating multiplication" { |
| 1018 | 1013 | |
| 1019 | 1014 | test "saturating shift-left" { |
| 1020 | 1015 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1021 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1022 | 1016 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1023 | 1017 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1024 | 1018 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1025 | 1019 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1026 | 1020 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1021 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1027 | 1022 | |
| 1028 | 1023 | const S = struct { |
| 1029 | 1024 | fn doTheTest() !void { |
| ... | ... | @@ -1043,12 +1038,12 @@ test "saturating shift-left" { |
| 1043 | 1038 | |
| 1044 | 1039 | test "multiplication-assignment operator with an array operand" { |
| 1045 | 1040 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1046 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1047 | 1041 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1048 | 1042 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1049 | 1043 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1050 | 1044 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1051 | 1045 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1046 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1052 | 1047 | |
| 1053 | 1048 | const S = struct { |
| 1054 | 1049 | fn doTheTest() !void { |
| ... | ... | @@ -1065,7 +1060,6 @@ test "multiplication-assignment operator with an array operand" { |
| 1065 | 1060 | |
| 1066 | 1061 | test "@addWithOverflow" { |
| 1067 | 1062 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1068 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1069 | 1063 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1070 | 1064 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1071 | 1065 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1116,7 +1110,6 @@ test "@addWithOverflow" { |
| 1116 | 1110 | |
| 1117 | 1111 | test "@subWithOverflow" { |
| 1118 | 1112 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1119 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1120 | 1113 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1121 | 1114 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1122 | 1115 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1151,7 +1144,6 @@ test "@subWithOverflow" { |
| 1151 | 1144 | |
| 1152 | 1145 | test "@mulWithOverflow" { |
| 1153 | 1146 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1154 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1155 | 1147 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1156 | 1148 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1157 | 1149 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1175,7 +1167,6 @@ test "@mulWithOverflow" { |
| 1175 | 1167 | |
| 1176 | 1168 | test "@shlWithOverflow" { |
| 1177 | 1169 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1178 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1179 | 1170 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1180 | 1171 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1181 | 1172 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1314,7 +1305,7 @@ test "zero multiplicand" { |
| 1314 | 1305 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1315 | 1306 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1316 | 1307 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 1317 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1308 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | |
| 1318 | 1309 | |
| 1319 | 1310 | const zeros = @Vector(2, u32){ 0.0, 0.0 }; |
| 1320 | 1311 | var ones = @Vector(2, u32){ 1.0, 1.0 }; |
| ... | ... | @@ -1362,7 +1353,6 @@ test "array operands to shuffle are coerced to vectors" { |
| 1362 | 1353 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1363 | 1354 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1364 | 1355 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1365 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 1366 | 1356 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1367 | 1357 | |
| 1368 | 1358 | const mask = [5]i32{ -1, 0, 1, 2, 3 }; |
| ... | ... | @@ -1469,7 +1459,6 @@ test "compare vectors with different element types" { |
| 1469 | 1459 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1470 | 1460 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1471 | 1461 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1472 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1473 | 1462 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1474 | 1463 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1475 | 1464 |
test/behavior/x86_64/binary.zig+40-16| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 1 | const AddOneBit = math.AddOneBit; |
| 2 | const AsSignedness = math.AsSignedness; | |
| 2 | 3 | const cast = math.cast; |
| 4 | const ChangeScalar = math.ChangeScalar; | |
| 3 | 5 | const checkExpected = math.checkExpected; |
| 4 | 6 | const Compare = math.Compare; |
| 5 | 7 | const DoubleBits = math.DoubleBits; |
| ... | ... | @@ -13,6 +15,7 @@ const math = @import("math.zig"); |
| 13 | 15 | const nan = math.nan; |
| 14 | 16 | const Scalar = math.Scalar; |
| 15 | 17 | const sign = math.sign; |
| 18 | const splat = math.splat; | |
| 16 | 19 | const Sse = math.Sse; |
| 17 | 20 | const tmin = math.tmin; |
| 18 | 21 | |
| ... | ... | @@ -5141,6 +5144,7 @@ inline fn mulSat(comptime Type: type, lhs: Type, rhs: Type) Type { |
| 5141 | 5144 | test mulSat { |
| 5142 | 5145 | const test_mul_sat = binary(mulSat, .{}); |
| 5143 | 5146 | try test_mul_sat.testInts(); |
| 5147 | try test_mul_sat.testIntVectors(); | |
| 5144 | 5148 | } |
| 5145 | 5149 | |
| 5146 | 5150 | inline fn multiply(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs * rhs) { |
| ... | ... | @@ -5240,38 +5244,42 @@ test min { |
| 5240 | 5244 | try test_min.testFloatVectors(); |
| 5241 | 5245 | } |
| 5242 | 5246 | |
| 5243 | inline fn addWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } { | |
| 5247 | inline fn addWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } { | |
| 5244 | 5248 | return @addWithOverflow(lhs, rhs); |
| 5245 | 5249 | } |
| 5246 | 5250 | test addWithOverflow { |
| 5247 | 5251 | const test_add_with_overflow = binary(addWithOverflow, .{}); |
| 5248 | 5252 | try test_add_with_overflow.testInts(); |
| 5253 | try test_add_with_overflow.testIntVectors(); | |
| 5249 | 5254 | } |
| 5250 | 5255 | |
| 5251 | inline fn subWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } { | |
| 5256 | inline fn subWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } { | |
| 5252 | 5257 | return @subWithOverflow(lhs, rhs); |
| 5253 | 5258 | } |
| 5254 | 5259 | test subWithOverflow { |
| 5255 | 5260 | const test_sub_with_overflow = binary(subWithOverflow, .{}); |
| 5256 | 5261 | try test_sub_with_overflow.testInts(); |
| 5262 | try test_sub_with_overflow.testIntVectors(); | |
| 5257 | 5263 | } |
| 5258 | 5264 | |
| 5259 | inline fn mulWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } { | |
| 5265 | inline fn mulWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } { | |
| 5260 | 5266 | return @mulWithOverflow(lhs, rhs); |
| 5261 | 5267 | } |
| 5262 | 5268 | test mulWithOverflow { |
| 5263 | 5269 | const test_mul_with_overflow = binary(mulWithOverflow, .{}); |
| 5264 | 5270 | try test_mul_with_overflow.testInts(); |
| 5271 | try test_mul_with_overflow.testIntVectors(); | |
| 5265 | 5272 | } |
| 5266 | 5273 | |
| 5267 | inline fn shlWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, u1 } { | |
| 5268 | const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs); | |
| 5274 | inline fn shlWithOverflow(comptime Type: type, lhs: Type, rhs: Type) struct { Type, ChangeScalar(Type, u1) } { | |
| 5275 | const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs); | |
| 5269 | 5276 | const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs); |
| 5270 | return @shlWithOverflow(lhs, if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs); | |
| 5277 | return @shlWithOverflow(lhs, if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs); | |
| 5271 | 5278 | } |
| 5272 | 5279 | test shlWithOverflow { |
| 5273 | 5280 | const test_shl_with_overflow = binary(shlWithOverflow, .{}); |
| 5274 | 5281 | try test_shl_with_overflow.testInts(); |
| 5282 | try test_shl_with_overflow.testIntVectors(); | |
| 5275 | 5283 | } |
| 5276 | 5284 | |
| 5277 | 5285 | inline fn equal(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs == rhs) { |
| ... | ... | @@ -5280,7 +5288,9 @@ inline fn equal(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs == rhs) { |
| 5280 | 5288 | test equal { |
| 5281 | 5289 | const test_equal = binary(equal, .{}); |
| 5282 | 5290 | try test_equal.testInts(); |
| 5291 | try test_equal.testIntVectors(); | |
| 5283 | 5292 | try test_equal.testFloats(); |
| 5293 | try test_equal.testFloatVectors(); | |
| 5284 | 5294 | } |
| 5285 | 5295 | |
| 5286 | 5296 | inline fn notEqual(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs != rhs) { |
| ... | ... | @@ -5289,7 +5299,9 @@ inline fn notEqual(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs != rhs |
| 5289 | 5299 | test notEqual { |
| 5290 | 5300 | const test_not_equal = binary(notEqual, .{}); |
| 5291 | 5301 | try test_not_equal.testInts(); |
| 5302 | try test_not_equal.testIntVectors(); | |
| 5292 | 5303 | try test_not_equal.testFloats(); |
| 5304 | try test_not_equal.testFloatVectors(); | |
| 5293 | 5305 | } |
| 5294 | 5306 | |
| 5295 | 5307 | inline fn lessThan(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs < rhs) { |
| ... | ... | @@ -5298,7 +5310,9 @@ inline fn lessThan(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs < rhs) |
| 5298 | 5310 | test lessThan { |
| 5299 | 5311 | const test_less_than = binary(lessThan, .{}); |
| 5300 | 5312 | try test_less_than.testInts(); |
| 5313 | try test_less_than.testIntVectors(); | |
| 5301 | 5314 | try test_less_than.testFloats(); |
| 5315 | try test_less_than.testFloatVectors(); | |
| 5302 | 5316 | } |
| 5303 | 5317 | |
| 5304 | 5318 | inline fn lessThanOrEqual(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs <= rhs) { |
| ... | ... | @@ -5307,7 +5321,9 @@ inline fn lessThanOrEqual(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs |
| 5307 | 5321 | test lessThanOrEqual { |
| 5308 | 5322 | const test_less_than_or_equal = binary(lessThanOrEqual, .{}); |
| 5309 | 5323 | try test_less_than_or_equal.testInts(); |
| 5324 | try test_less_than_or_equal.testIntVectors(); | |
| 5310 | 5325 | try test_less_than_or_equal.testFloats(); |
| 5326 | try test_less_than_or_equal.testFloatVectors(); | |
| 5311 | 5327 | } |
| 5312 | 5328 | |
| 5313 | 5329 | inline fn greaterThan(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs > rhs) { |
| ... | ... | @@ -5316,7 +5332,9 @@ inline fn greaterThan(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs > r |
| 5316 | 5332 | test greaterThan { |
| 5317 | 5333 | const test_greater_than = binary(greaterThan, .{}); |
| 5318 | 5334 | try test_greater_than.testInts(); |
| 5335 | try test_greater_than.testIntVectors(); | |
| 5319 | 5336 | try test_greater_than.testFloats(); |
| 5337 | try test_greater_than.testFloatVectors(); | |
| 5320 | 5338 | } |
| 5321 | 5339 | |
| 5322 | 5340 | inline fn greaterThanOrEqual(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs >= rhs) { |
| ... | ... | @@ -5325,7 +5343,9 @@ inline fn greaterThanOrEqual(comptime Type: type, lhs: Type, rhs: Type) @TypeOf( |
| 5325 | 5343 | test greaterThanOrEqual { |
| 5326 | 5344 | const test_greater_than_or_equal = binary(greaterThanOrEqual, .{}); |
| 5327 | 5345 | try test_greater_than_or_equal.testInts(); |
| 5346 | try test_greater_than_or_equal.testIntVectors(); | |
| 5328 | 5347 | try test_greater_than_or_equal.testFloats(); |
| 5348 | try test_greater_than_or_equal.testFloatVectors(); | |
| 5329 | 5349 | } |
| 5330 | 5350 | |
| 5331 | 5351 | inline fn bitAnd(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs & rhs) { |
| ... | ... | @@ -5347,54 +5367,57 @@ test bitOr { |
| 5347 | 5367 | } |
| 5348 | 5368 | |
| 5349 | 5369 | inline fn shr(comptime Type: type, lhs: Type, rhs: Type) Type { |
| 5350 | const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs); | |
| 5370 | const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs); | |
| 5351 | 5371 | const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs); |
| 5352 | return lhs >> if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs; | |
| 5372 | return lhs >> if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs; | |
| 5353 | 5373 | } |
| 5354 | 5374 | test shr { |
| 5355 | 5375 | const test_shr = binary(shr, .{}); |
| 5356 | 5376 | try test_shr.testInts(); |
| 5377 | try test_shr.testIntVectors(); | |
| 5357 | 5378 | } |
| 5358 | 5379 | |
| 5359 | 5380 | inline fn shrExact(comptime Type: type, lhs: Type, rhs: Type) Type { |
| 5360 | const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs); | |
| 5381 | const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs); | |
| 5361 | 5382 | const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs); |
| 5362 | const final_rhs = if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs; | |
| 5383 | const final_rhs = if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs; | |
| 5363 | 5384 | return @shrExact(lhs >> final_rhs << final_rhs, final_rhs); |
| 5364 | 5385 | } |
| 5365 | 5386 | test shrExact { |
| 5366 | 5387 | const test_shr_exact = binary(shrExact, .{}); |
| 5367 | 5388 | try test_shr_exact.testInts(); |
| 5389 | try test_shr_exact.testIntVectors(); | |
| 5368 | 5390 | } |
| 5369 | 5391 | |
| 5370 | 5392 | inline fn shl(comptime Type: type, lhs: Type, rhs: Type) Type { |
| 5371 | const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs); | |
| 5393 | const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs); | |
| 5372 | 5394 | const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs); |
| 5373 | return lhs << if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs; | |
| 5395 | return lhs << if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs; | |
| 5374 | 5396 | } |
| 5375 | 5397 | test shl { |
| 5376 | 5398 | const test_shl = binary(shl, .{}); |
| 5377 | 5399 | try test_shl.testInts(); |
| 5400 | try test_shl.testIntVectors(); | |
| 5378 | 5401 | } |
| 5379 | 5402 | |
| 5380 | 5403 | inline fn shlExactUnsafe(comptime Type: type, lhs: Type, rhs: Type) Type { |
| 5381 | 5404 | @setRuntimeSafety(false); |
| 5382 | const bit_cast_rhs: @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(Type) } }) = @bitCast(rhs); | |
| 5405 | const bit_cast_rhs: AsSignedness(Type, .unsigned) = @bitCast(rhs); | |
| 5383 | 5406 | const truncate_rhs: Log2Int(Type) = @truncate(bit_cast_rhs); |
| 5384 | const final_rhs = if (comptime cast(Log2Int(Type), @bitSizeOf(Type))) |bits| truncate_rhs % bits else truncate_rhs; | |
| 5407 | const final_rhs = if (comptime cast(Log2Int(Scalar(Type)), @bitSizeOf(Scalar(Type)))) |bits| truncate_rhs % splat(Log2Int(Type), bits) else truncate_rhs; | |
| 5385 | 5408 | return @shlExact(lhs << final_rhs >> final_rhs, final_rhs); |
| 5386 | 5409 | } |
| 5387 | 5410 | test shlExactUnsafe { |
| 5388 | 5411 | const test_shl_exact_unsafe = binary(shlExactUnsafe, .{}); |
| 5389 | 5412 | try test_shl_exact_unsafe.testInts(); |
| 5413 | try test_shl_exact_unsafe.testIntVectors(); | |
| 5390 | 5414 | } |
| 5391 | 5415 | |
| 5392 | 5416 | inline fn shlSat(comptime Type: type, lhs: Type, rhs: Type) Type { |
| 5393 | 5417 | // workaround https://github.com/ziglang/zig/issues/23034 |
| 5394 | 5418 | if (@inComptime()) { |
| 5395 | 5419 | // workaround https://github.com/ziglang/zig/issues/23139 |
| 5396 | //return lhs <<| @min(@abs(rhs), imax(u64)); | |
| 5397 | return lhs <<| @min(@abs(rhs), @as(u64, imax(u64))); | |
| 5420 | return lhs <<| @min(@abs(rhs), splat(ChangeScalar(Type, u64), imax(u64))); | |
| 5398 | 5421 | } |
| 5399 | 5422 | // workaround https://github.com/ziglang/zig/issues/23033 |
| 5400 | 5423 | @setRuntimeSafety(false); |
| ... | ... | @@ -5403,6 +5426,7 @@ inline fn shlSat(comptime Type: type, lhs: Type, rhs: Type) Type { |
| 5403 | 5426 | test shlSat { |
| 5404 | 5427 | const test_shl_sat = binary(shlSat, .{}); |
| 5405 | 5428 | try test_shl_sat.testInts(); |
| 5429 | try test_shl_sat.testIntVectors(); | |
| 5406 | 5430 | } |
| 5407 | 5431 | |
| 5408 | 5432 | inline fn bitXor(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs ^ rhs) { |
test/behavior/x86_64/math.zig+26-28| ... | ... | @@ -8,8 +8,6 @@ pub const fmin = math.floatMin; |
| 8 | 8 | pub const imax = math.maxInt; |
| 9 | 9 | pub const imin = math.minInt; |
| 10 | 10 | pub const inf = math.inf; |
| 11 | pub const Log2Int = math.Log2Int; | |
| 12 | pub const Log2IntCeil = math.Log2IntCeil; | |
| 13 | 11 | pub const nan = math.nan; |
| 14 | 12 | pub const next = math.nextAfter; |
| 15 | 13 | pub const tmin = math.floatTrueMin; |
| ... | ... | @@ -30,38 +28,44 @@ pub fn Scalar(comptime Type: type) type { |
| 30 | 28 | .vector => |info| info.child, |
| 31 | 29 | }; |
| 32 | 30 | } |
| 31 | pub fn ChangeScalar(comptime Type: type, comptime NewScalar: type) type { | |
| 32 | return switch (@typeInfo(Type)) { | |
| 33 | else => NewScalar, | |
| 34 | .vector => |vector| @Vector(vector.len, NewScalar), | |
| 35 | }; | |
| 36 | } | |
| 37 | pub fn AsSignedness(comptime Type: type, comptime signedness: std.builtin.Signedness) type { | |
| 38 | return ChangeScalar(Type, @Type(.{ .int = .{ | |
| 39 | .signedness = signedness, | |
| 40 | .bits = @typeInfo(Scalar(Type)).int.bits, | |
| 41 | } })); | |
| 42 | } | |
| 33 | 43 | pub fn AddOneBit(comptime Type: type) type { |
| 34 | const ResultScalar = switch (@typeInfo(Scalar(Type))) { | |
| 44 | return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) { | |
| 35 | 45 | .int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = 1 + int.bits } }), |
| 36 | 46 | .float => Scalar(Type), |
| 37 | 47 | else => @compileError(@typeName(Type)), |
| 38 | }; | |
| 39 | return switch (@typeInfo(Type)) { | |
| 40 | else => ResultScalar, | |
| 41 | .vector => |vector| @Vector(vector.len, ResultScalar), | |
| 42 | }; | |
| 48 | }); | |
| 43 | 49 | } |
| 44 | 50 | pub fn DoubleBits(comptime Type: type) type { |
| 45 | const ResultScalar = switch (@typeInfo(Scalar(Type))) { | |
| 51 | return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) { | |
| 46 | 52 | .int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = int.bits * 2 } }), |
| 47 | 53 | .float => Scalar(Type), |
| 48 | 54 | else => @compileError(@typeName(Type)), |
| 49 | }; | |
| 50 | return switch (@typeInfo(Type)) { | |
| 51 | else => ResultScalar, | |
| 52 | .vector => |vector| @Vector(vector.len, ResultScalar), | |
| 53 | }; | |
| 55 | }); | |
| 54 | 56 | } |
| 55 | 57 | pub fn RoundBitsUp(comptime Type: type, comptime multiple: u16) type { |
| 56 | const ResultScalar = switch (@typeInfo(Scalar(Type))) { | |
| 58 | return ChangeScalar(Type, switch (@typeInfo(Scalar(Type))) { | |
| 57 | 59 | .int => |int| @Type(.{ .int = .{ .signedness = int.signedness, .bits = std.mem.alignForward(u16, int.bits, multiple) } }), |
| 58 | 60 | .float => Scalar(Type), |
| 59 | 61 | else => @compileError(@typeName(Type)), |
| 60 | }; | |
| 61 | return switch (@typeInfo(Type)) { | |
| 62 | else => ResultScalar, | |
| 63 | .vector => |vector| @Vector(vector.len, ResultScalar), | |
| 64 | }; | |
| 62 | }); | |
| 63 | } | |
| 64 | pub fn Log2Int(comptime Type: type) type { | |
| 65 | return ChangeScalar(Type, math.Log2Int(Scalar(Type))); | |
| 66 | } | |
| 67 | pub fn Log2IntCeil(comptime Type: type) type { | |
| 68 | return ChangeScalar(Type, math.Log2IntCeil(Scalar(Type))); | |
| 65 | 69 | } |
| 66 | 70 | // inline to avoid a runtime `@splat` |
| 67 | 71 | pub inline fn splat(comptime Type: type, scalar: Scalar(Type)) Type { |
| ... | ... | @@ -78,18 +82,12 @@ inline fn select(cond: anytype, lhs: anytype, rhs: @TypeOf(lhs)) @TypeOf(lhs) { |
| 78 | 82 | else => @compileError(@typeName(@TypeOf(cond))), |
| 79 | 83 | }; |
| 80 | 84 | } |
| 81 | pub fn sign(rhs: anytype) switch (@typeInfo(@TypeOf(rhs))) { | |
| 82 | else => bool, | |
| 83 | .vector => |vector| @Vector(vector.len, bool), | |
| 84 | } { | |
| 85 | pub fn sign(rhs: anytype) ChangeScalar(@TypeOf(rhs), bool) { | |
| 85 | 86 | const ScalarInt = @Type(.{ .int = .{ |
| 86 | 87 | .signedness = .unsigned, |
| 87 | 88 | .bits = @bitSizeOf(Scalar(@TypeOf(rhs))), |
| 88 | 89 | } }); |
| 89 | const VectorInt = switch (@typeInfo(@TypeOf(rhs))) { | |
| 90 | else => ScalarInt, | |
| 91 | .vector => |vector| @Vector(vector.len, ScalarInt), | |
| 92 | }; | |
| 90 | const VectorInt = ChangeScalar(@TypeOf(rhs), ScalarInt); | |
| 93 | 91 | return @as(VectorInt, @bitCast(rhs)) & splat(VectorInt, @as(ScalarInt, 1) << @bitSizeOf(ScalarInt) - 1) != splat(VectorInt, 0); |
| 94 | 92 | } |
| 95 | 93 | fn boolAnd(lhs: anytype, rhs: @TypeOf(lhs)) @TypeOf(lhs) { |
test/behavior/x86_64/unary.zig+4| ... | ... | @@ -4828,6 +4828,7 @@ inline fn ctz(comptime Type: type, rhs: Type) @TypeOf(@ctz(rhs)) { |
| 4828 | 4828 | test ctz { |
| 4829 | 4829 | const test_ctz = unary(ctz, .{}); |
| 4830 | 4830 | try test_ctz.testInts(); |
| 4831 | try test_ctz.testIntVectors(); | |
| 4831 | 4832 | } |
| 4832 | 4833 | |
| 4833 | 4834 | inline fn popCount(comptime Type: type, rhs: Type) @TypeOf(@popCount(rhs)) { |
| ... | ... | @@ -4836,6 +4837,7 @@ inline fn popCount(comptime Type: type, rhs: Type) @TypeOf(@popCount(rhs)) { |
| 4836 | 4837 | test popCount { |
| 4837 | 4838 | const test_pop_count = unary(popCount, .{}); |
| 4838 | 4839 | try test_pop_count.testInts(); |
| 4840 | try test_pop_count.testIntVectors(); | |
| 4839 | 4841 | } |
| 4840 | 4842 | |
| 4841 | 4843 | inline fn byteSwap(comptime Type: type, rhs: Type) RoundBitsUp(Type, 8) { |
| ... | ... | @@ -4844,6 +4846,7 @@ inline fn byteSwap(comptime Type: type, rhs: Type) RoundBitsUp(Type, 8) { |
| 4844 | 4846 | test byteSwap { |
| 4845 | 4847 | const test_byte_swap = unary(byteSwap, .{}); |
| 4846 | 4848 | try test_byte_swap.testInts(); |
| 4849 | try test_byte_swap.testIntVectors(); | |
| 4847 | 4850 | } |
| 4848 | 4851 | |
| 4849 | 4852 | inline fn bitReverse(comptime Type: type, rhs: Type) @TypeOf(@bitReverse(rhs)) { |
| ... | ... | @@ -4852,6 +4855,7 @@ inline fn bitReverse(comptime Type: type, rhs: Type) @TypeOf(@bitReverse(rhs)) { |
| 4852 | 4855 | test bitReverse { |
| 4853 | 4856 | const test_bit_reverse = unary(bitReverse, .{}); |
| 4854 | 4857 | try test_bit_reverse.testInts(); |
| 4858 | try test_bit_reverse.testIntVectors(); | |
| 4855 | 4859 | } |
| 4856 | 4860 | |
| 4857 | 4861 | inline fn sqrt(comptime Type: type, rhs: Type) @TypeOf(@sqrt(rhs)) { |
test/cases/compile_errors/@import_zon_bad_type.zig+3-3| ... | ... | @@ -117,9 +117,9 @@ export fn testMutablePointer() void { |
| 117 | 117 | // tmp.zig:37:38: note: imported here |
| 118 | 118 | // neg_inf.zon:1:1: error: expected type '?u8' |
| 119 | 119 | // tmp.zig:57:28: note: imported here |
| 120 | // neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_518' | |
| 120 | // neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_522' | |
| 121 | 121 | // tmp.zig:62:39: note: imported here |
| 122 | // neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_520' | |
| 122 | // neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_524' | |
| 123 | 123 | // tmp.zig:67:44: note: imported here |
| 124 | // neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_523' | |
| 124 | // neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_527' | |
| 125 | 125 | // tmp.zig:72:50: note: imported here |
test/cases/compile_errors/anytype_param_requires_comptime.zig+1-1| ... | ... | @@ -15,6 +15,6 @@ pub export fn entry() void { |
| 15 | 15 | // error |
| 16 | 16 | // |
| 17 | 17 | // :7:25: error: unable to resolve comptime value |
| 18 | // :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_492.C' must be comptime-known | |
| 18 | // :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_496.C' must be comptime-known | |
| 19 | 19 | // :4:16: note: struct requires comptime because of this field |
| 20 | 20 | // :4:16: note: types are not available at runtime |
test/cases/compile_errors/bad_panic_call_signature.zig+1-4| ... | ... | @@ -15,8 +15,7 @@ pub const panic = struct { |
| 15 | 15 | pub const castToNull = simple_panic.castToNull; |
| 16 | 16 | pub const incorrectAlignment = simple_panic.incorrectAlignment; |
| 17 | 17 | pub const invalidErrorCode = simple_panic.invalidErrorCode; |
| 18 | pub const castTruncatedData = simple_panic.castTruncatedData; | |
| 19 | pub const negativeToUnsigned = simple_panic.negativeToUnsigned; | |
| 18 | pub const integerOutOfBounds = simple_panic.integerOutOfBounds; | |
| 20 | 19 | pub const integerOverflow = simple_panic.integerOverflow; |
| 21 | 20 | pub const shlOverflow = simple_panic.shlOverflow; |
| 22 | 21 | pub const shrOverflow = simple_panic.shrOverflow; |
| ... | ... | @@ -27,8 +26,6 @@ pub const panic = struct { |
| 27 | 26 | pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig; |
| 28 | 27 | pub const invalidEnumValue = simple_panic.invalidEnumValue; |
| 29 | 28 | pub const forLenMismatch = simple_panic.forLenMismatch; |
| 30 | /// Delete after next zig1.wasm update | |
| 31 | pub const memcpyLenMismatch = copyLenMismatch; | |
| 32 | 29 | pub const copyLenMismatch = simple_panic.copyLenMismatch; |
| 33 | 30 | pub const memcpyAlias = simple_panic.memcpyAlias; |
| 34 | 31 | pub const noreturnReturned = simple_panic.noreturnReturned; |
test/cases/compile_errors/bad_panic_generic_signature.zig+1-4| ... | ... | @@ -11,8 +11,7 @@ pub const panic = struct { |
| 11 | 11 | pub const castToNull = simple_panic.castToNull; |
| 12 | 12 | pub const incorrectAlignment = simple_panic.incorrectAlignment; |
| 13 | 13 | pub const invalidErrorCode = simple_panic.invalidErrorCode; |
| 14 | pub const castTruncatedData = simple_panic.castTruncatedData; | |
| 15 | pub const negativeToUnsigned = simple_panic.negativeToUnsigned; | |
| 14 | pub const integerOutOfBounds = simple_panic.integerOutOfBounds; | |
| 16 | 15 | pub const integerOverflow = simple_panic.integerOverflow; |
| 17 | 16 | pub const shlOverflow = simple_panic.shlOverflow; |
| 18 | 17 | pub const shrOverflow = simple_panic.shrOverflow; |
| ... | ... | @@ -23,8 +22,6 @@ pub const panic = struct { |
| 23 | 22 | pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig; |
| 24 | 23 | pub const invalidEnumValue = simple_panic.invalidEnumValue; |
| 25 | 24 | pub const forLenMismatch = simple_panic.forLenMismatch; |
| 26 | /// Delete after next zig1.wasm update | |
| 27 | pub const memcpyLenMismatch = copyLenMismatch; | |
| 28 | 25 | pub const copyLenMismatch = simple_panic.copyLenMismatch; |
| 29 | 26 | pub const memcpyAlias = simple_panic.memcpyAlias; |
| 30 | 27 | pub const noreturnReturned = simple_panic.noreturnReturned; |
test/cases/compile_errors/bogus_method_call_on_slice.zig+1-1| ... | ... | @@ -16,5 +16,5 @@ pub export fn entry2() void { |
| 16 | 16 | // |
| 17 | 17 | // :3:6: error: no field or member function named 'copy' in '[]const u8' |
| 18 | 18 | // :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})' |
| 19 | // :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_496' | |
| 19 | // :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_500' | |
| 20 | 20 | // :12:6: note: struct declared here |
test/cases/compile_errors/coerce_anon_struct.zig+1-1| ... | ... | @@ -6,6 +6,6 @@ export fn foo() void { |
| 6 | 6 | |
| 7 | 7 | // error |
| 8 | 8 | // |
| 9 | // :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_485' | |
| 9 | // :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_489' | |
| 10 | 10 | // :3:16: note: struct declared here |
| 11 | 11 | // :1:11: note: struct declared here |
test/cases/compile_errors/redundant_try.zig+2-2| ... | ... | @@ -44,9 +44,9 @@ comptime { |
| 44 | 44 | // |
| 45 | 45 | // :5:23: error: expected error union type, found 'comptime_int' |
| 46 | 46 | // :10:23: error: expected error union type, found '@TypeOf(.{})' |
| 47 | // :15:23: error: expected error union type, found 'tmp.test2__struct_522' | |
| 47 | // :15:23: error: expected error union type, found 'tmp.test2__struct_526' | |
| 48 | 48 | // :15:23: note: struct declared here |
| 49 | // :20:27: error: expected error union type, found 'tmp.test3__struct_524' | |
| 49 | // :20:27: error: expected error union type, found 'tmp.test3__struct_528' | |
| 50 | 50 | // :20:27: note: struct declared here |
| 51 | 51 | // :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }' |
| 52 | 52 | // :31:13: error: expected error union type, found 'u32' |
test/cases/compile_errors/shuffle_with_selected_index_past_first_vector_length.zig+16-10| ... | ... | @@ -1,14 +1,20 @@ |
| 1 | export fn entry() void { | |
| 2 | const v: @Vector(4, u32) = [4]u32{ 10, 11, 12, 13 }; | |
| 3 | const x: @Vector(4, u32) = [4]u32{ 14, 15, 16, 17 }; | |
| 4 | const z = @shuffle(u32, v, x, [8]i32{ 0, 1, 2, 3, 7, 6, 5, 4 }); | |
| 5 | _ = z; | |
| 1 | export fn foo() void { | |
| 2 | // Here, the bad index ('7') is not less than 'b.len', so the error shouldn't have a note suggesting a negative index. | |
| 3 | const a: @Vector(4, u32) = .{ 10, 11, 12, 13 }; | |
| 4 | const b: @Vector(4, u32) = .{ 14, 15, 16, 17 }; | |
| 5 | _ = @shuffle(u32, a, b, [8]i32{ 0, 1, 2, 3, 7, 6, 5, 4 }); | |
| 6 | } | |
| 7 | export fn bar() void { | |
| 8 | // Here, the bad index ('7') *is* less than 'b.len', so the error *should* have a note suggesting a negative index. | |
| 9 | const a: @Vector(4, u32) = .{ 10, 11, 12, 13 }; | |
| 10 | const b: @Vector(9, u32) = .{ 14, 15, 16, 17, 18, 19, 20, 21, 22 }; | |
| 11 | _ = @shuffle(u32, a, b, [8]i32{ 0, 1, 2, 3, 7, 6, 5, 4 }); | |
| 6 | 12 | } |
| 7 | 13 | |
| 8 | 14 | // error |
| 9 | // backend=stage2 | |
| 10 | // target=native | |
| 11 | 15 | // |
| 12 | // :4:41: error: mask index '4' has out-of-bounds selection | |
| 13 | // :4:29: note: selected index '7' out of bounds of '@Vector(4, u32)' | |
| 14 | // :4:32: note: selections from the second vector are specified with negative numbers | |
| 16 | // :5:35: error: mask element at index '4' selects out-of-bounds index | |
| 17 | // :5:23: note: index '7' exceeds bounds of '@Vector(4, u32)' given here | |
| 18 | // :11:35: error: mask element at index '4' selects out-of-bounds index | |
| 19 | // :11:23: note: index '7' exceeds bounds of '@Vector(4, u32)' given here | |
| 20 | // :11:26: note: use '~@as(u32, 7)' to index into second vector given here |
test/cases/safety/@intCast to u0.zig	+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "integer cast truncated bits")) { | |
| 5 | if (std.mem.eql(u8, message, "integer does not fit in destination type")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
test/cases/safety/memmove_len_mismatch.zig+1-1| ... | ... | @@ -15,5 +15,5 @@ pub fn main() !void { |
| 15 | 15 | return error.TestFailed; |
| 16 | 16 | } |
| 17 | 17 | // run |
| 18 | // backend=llvm | |
| 18 | // backend=stage2,llvm | |
| 19 | 19 | // target=native |
test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig	+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) { | |
| 5 | if (std.mem.eql(u8, message, "integer does not fit in destination type")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
test/cases/safety/signed integer not fitting in cast to unsigned integer.zig	+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) { | |
| 5 | if (std.mem.eql(u8, message, "integer does not fit in destination type")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
test/cases/safety/signed-unsigned vector cast.zig	+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) { | |
| 5 | if (std.mem.eql(u8, message, "integer does not fit in destination type")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
test/cases/safety/slice_cast_change_len_0.zig+2-1| ... | ... | @@ -23,4 +23,5 @@ pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noretu |
| 23 | 23 | const std = @import("std"); |
| 24 | 24 | |
| 25 | 25 | // run |
| 26 | // backend=llvm | |
| 26 | // backend=stage2,llvm | |
| 27 | // target=x86_64-linux |
test/cases/safety/slice_cast_change_len_1.zig+2-1| ... | ... | @@ -23,4 +23,5 @@ pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noretu |
| 23 | 23 | const std = @import("std"); |
| 24 | 24 | |
| 25 | 25 | // run |
| 26 | // backend=llvm | |
| 26 | // backend=stage2,llvm | |
| 27 | // target=x86_64-linux |
test/cases/safety/slice_cast_change_len_2.zig+2-1| ... | ... | @@ -23,4 +23,5 @@ pub fn panic(message: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noretu |
| 23 | 23 | const std = @import("std"); |
| 24 | 24 | |
| 25 | 25 | // run |
| 26 | // backend=llvm | |
| 26 | // backend=stage2,llvm | |
| 27 | // target=x86_64-linux |
test/cases/safety/truncating vector cast.zig	+2-2| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "integer cast truncated bits")) { | |
| 5 | if (std.mem.eql(u8, message, "integer does not fit in destination type")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
| ... | ... | @@ -17,5 +17,5 @@ pub fn main() !void { |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | // backend=llvm | |
| 20 | // backend=stage2,llvm | |
| 21 | 21 | // target=native |
test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig	+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "integer cast truncated bits")) { | |
| 5 | if (std.mem.eql(u8, message, "integer does not fit in destination type")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
test/cases/safety/unsigned-signed vector cast.zig	+2-2| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "integer cast truncated bits")) { | |
| 5 | if (std.mem.eql(u8, message, "integer does not fit in destination type")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
| ... | ... | @@ -17,5 +17,5 @@ pub fn main() !void { |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | 19 | // run |
| 20 | // backend=llvm | |
| 20 | // backend=stage2,llvm | |
| 21 | 21 | // target=native |
test/cases/safety/value does not fit in shortening cast - u0.zig	+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "integer cast truncated bits")) { | |
| 5 | if (std.mem.eql(u8, message, "integer does not fit in destination type")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
test/cases/safety/value does not fit in shortening cast.zig	+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 4 | _ = stack_trace; |
| 5 | if (std.mem.eql(u8, message, "integer cast truncated bits")) { | |
| 5 | if (std.mem.eql(u8, message, "integer does not fit in destination type")) { | |
| 6 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
test/cases/safety/vector integer addition overflow.zig	+1-1| ... | ... | @@ -18,5 +18,5 @@ fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { |
| 18 | 18 | return a + b; |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | // backend=llvm | |
| 21 | // backend=stage2,llvm | |
| 22 | 22 | // target=native |
test/cases/safety/vector integer multiplication overflow.zig	+1-1| ... | ... | @@ -18,5 +18,5 @@ fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) { |
| 18 | 18 | return a * b; |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | // backend=llvm | |
| 21 | // backend=stage2,llvm | |
| 22 | 22 | // target=native |
test/cases/safety/vector integer negation overflow.zig	+1-1| ... | ... | @@ -18,5 +18,5 @@ fn neg(a: @Vector(4, i16)) @Vector(4, i16) { |
| 18 | 18 | return -a; |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | // backend=llvm | |
| 21 | // backend=stage2,llvm | |
| 22 | 22 | // target=native |
test/cases/safety/vector integer subtraction overflow.zig	+1-1| ... | ... | @@ -18,5 +18,5 @@ fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) { |
| 18 | 18 | return a - b; |
| 19 | 19 | } |
| 20 | 20 | // run |
| 21 | // backend=llvm | |
| 21 | // backend=stage2,llvm | |
| 22 | 22 | // target=native |
test/incremental/change_panic_handler_explicit+3-12| ... | ... | @@ -26,8 +26,7 @@ pub const panic = struct { |
| 26 | 26 | pub const castToNull = no_panic.castToNull; |
| 27 | 27 | pub const incorrectAlignment = no_panic.incorrectAlignment; |
| 28 | 28 | pub const invalidErrorCode = no_panic.invalidErrorCode; |
| 29 | pub const castTruncatedData = no_panic.castTruncatedData; | |
| 30 | pub const negativeToUnsigned = no_panic.negativeToUnsigned; | |
| 29 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | |
| 31 | 30 | pub const shlOverflow = no_panic.shlOverflow; |
| 32 | 31 | pub const shrOverflow = no_panic.shrOverflow; |
| 33 | 32 | pub const divideByZero = no_panic.divideByZero; |
| ... | ... | @@ -37,8 +36,6 @@ pub const panic = struct { |
| 37 | 36 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; |
| 38 | 37 | pub const invalidEnumValue = no_panic.invalidEnumValue; |
| 39 | 38 | pub const forLenMismatch = no_panic.forLenMismatch; |
| 40 | /// Delete after next zig1.wasm update | |
| 41 | pub const memcpyLenMismatch = copyLenMismatch; | |
| 42 | 39 | pub const copyLenMismatch = no_panic.copyLenMismatch; |
| 43 | 40 | pub const memcpyAlias = no_panic.memcpyAlias; |
| 44 | 41 | pub const noreturnReturned = no_panic.noreturnReturned; |
| ... | ... | @@ -75,8 +72,7 @@ pub const panic = struct { |
| 75 | 72 | pub const castToNull = no_panic.castToNull; |
| 76 | 73 | pub const incorrectAlignment = no_panic.incorrectAlignment; |
| 77 | 74 | pub const invalidErrorCode = no_panic.invalidErrorCode; |
| 78 | pub const castTruncatedData = no_panic.castTruncatedData; | |
| 79 | pub const negativeToUnsigned = no_panic.negativeToUnsigned; | |
| 75 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | |
| 80 | 76 | pub const shlOverflow = no_panic.shlOverflow; |
| 81 | 77 | pub const shrOverflow = no_panic.shrOverflow; |
| 82 | 78 | pub const divideByZero = no_panic.divideByZero; |
| ... | ... | @@ -86,8 +82,6 @@ pub const panic = struct { |
| 86 | 82 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; |
| 87 | 83 | pub const invalidEnumValue = no_panic.invalidEnumValue; |
| 88 | 84 | pub const forLenMismatch = no_panic.forLenMismatch; |
| 89 | /// Delete after next zig1.wasm update | |
| 90 | pub const memcpyLenMismatch = copyLenMismatch; | |
| 91 | 85 | pub const copyLenMismatch = no_panic.copyLenMismatch; |
| 92 | 86 | pub const memcpyAlias = no_panic.memcpyAlias; |
| 93 | 87 | pub const noreturnReturned = no_panic.noreturnReturned; |
| ... | ... | @@ -124,8 +118,7 @@ pub const panic = struct { |
| 124 | 118 | pub const castToNull = no_panic.castToNull; |
| 125 | 119 | pub const incorrectAlignment = no_panic.incorrectAlignment; |
| 126 | 120 | pub const invalidErrorCode = no_panic.invalidErrorCode; |
| 127 | pub const castTruncatedData = no_panic.castTruncatedData; | |
| 128 | pub const negativeToUnsigned = no_panic.negativeToUnsigned; | |
| 121 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; | |
| 129 | 122 | pub const shlOverflow = no_panic.shlOverflow; |
| 130 | 123 | pub const shrOverflow = no_panic.shrOverflow; |
| 131 | 124 | pub const divideByZero = no_panic.divideByZero; |
| ... | ... | @@ -135,8 +128,6 @@ pub const panic = struct { |
| 135 | 128 | pub const shiftRhsTooBig = no_panic.shiftRhsTooBig; |
| 136 | 129 | pub const invalidEnumValue = no_panic.invalidEnumValue; |
| 137 | 130 | pub const forLenMismatch = no_panic.forLenMismatch; |
| 138 | /// Delete after next zig1.wasm update | |
| 139 | pub const memcpyLenMismatch = copyLenMismatch; | |
| 140 | 131 | pub const copyLenMismatch = no_panic.copyLenMismatch; |
| 141 | 132 | pub const memcpyAlias = no_panic.memcpyAlias; |
| 142 | 133 | pub const noreturnReturned = no_panic.noreturnReturned; |
test/src/Cases.zig+17-3| ... | ... | @@ -400,7 +400,7 @@ fn addFromDirInner( |
| 400 | 400 | for (targets) |target_query| { |
| 401 | 401 | const output = try manifest.trailingLinesSplit(ctx.arena); |
| 402 | 402 | try ctx.translate.append(.{ |
| 403 | .name = std.fs.path.stem(filename), | |
| 403 | .name = try caseNameFromPath(ctx.arena, filename), | |
| 404 | 404 | .c_frontend = c_frontend, |
| 405 | 405 | .target = b.resolveTargetQuery(target_query), |
| 406 | 406 | .link_libc = link_libc, |
| ... | ... | @@ -416,7 +416,7 @@ fn addFromDirInner( |
| 416 | 416 | for (targets) |target_query| { |
| 417 | 417 | const output = try manifest.trailingSplit(ctx.arena); |
| 418 | 418 | try ctx.translate.append(.{ |
| 419 | .name = std.fs.path.stem(filename), | |
| 419 | .name = try caseNameFromPath(ctx.arena, filename), | |
| 420 | 420 | .c_frontend = c_frontend, |
| 421 | 421 | .target = b.resolveTargetQuery(target_query), |
| 422 | 422 | .link_libc = link_libc, |
| ... | ... | @@ -454,7 +454,7 @@ fn addFromDirInner( |
| 454 | 454 | |
| 455 | 455 | const next = ctx.cases.items.len; |
| 456 | 456 | try ctx.cases.append(.{ |
| 457 | .name = std.fs.path.stem(filename), | |
| 457 | .name = try caseNameFromPath(ctx.arena, filename), | |
| 458 | 458 | .import_path = std.fs.path.dirname(filename), |
| 459 | 459 | .backend = backend, |
| 460 | 460 | .files = .init(ctx.arena), |
| ... | ... | @@ -1138,3 +1138,17 @@ fn knownFileExtension(filename: []const u8) bool { |
| 1138 | 1138 | if (it.next() != null) return false; |
| 1139 | 1139 | return false; |
| 1140 | 1140 | } |
| 1141 | ||
| 1142 | /// `path` is a path relative to the root case directory. | |
| 1143 | /// e.g. `compile_errors/undeclared_identifier.zig` | |
| 1144 | /// The case name is computed by removing the extension and substituting path separators for dots. | |
| 1145 | /// e.g. `compile_errors.undeclared_identifier` | |
| 1146 | /// Including the directory components makes `-Dtest-filter` more useful, because you can filter | |
| 1147 | /// based on subdirectory; e.g. `-Dtest-filter=compile_errors` to run the compile error tets. | |
| 1148 | fn caseNameFromPath(arena: Allocator, path: []const u8) Allocator.Error![]const u8 { | |
| 1149 | const ext_len = std.fs.path.extension(path).len; | |
| 1150 | const path_sans_ext = path[0 .. path.len - ext_len]; | |
| 1151 | const result = try arena.dupe(u8, path_sans_ext); | |
| 1152 | std.mem.replaceScalar(u8, result, std.fs.path.sep, '.'); | |
| 1153 | return result; | |
| 1154 | } |
tools/lldb_pretty_printers.py+2-1| ... | ... | @@ -601,7 +601,8 @@ type_tag_handlers = { |
| 601 | 601 | 'fn_void_no_args': lambda payload: 'fn() void', |
| 602 | 602 | 'fn_naked_noreturn_no_args': lambda payload: 'fn() callconv(.naked) noreturn', |
| 603 | 603 | 'fn_ccc_void_no_args': lambda payload: 'fn() callconv(.c) void', |
| 604 | 'single_const_pointer_to_comptime_int': lambda payload: '*const comptime_int', | |
| 604 | 'ptr_usize': lambda payload: '*usize', | |
| 605 | 'ptr_const_comptime_int': lambda payload: '*const comptime_int', | |
| 605 | 606 | 'manyptr_u8': lambda payload: '[*]u8', |
| 606 | 607 | 'manyptr_const_u8': lambda payload: '[*]const u8', |
| 607 | 608 | 'manyptr_const_u8_sentinel_0': lambda payload: '[*:0]const u8', |