authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-02 03:10:19-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-01-16 20:42:08-05:00
loge5d5a8bc4ea6b27dc3540ad4800a1231ff50b33d
tree114481f7bbf4d5e6a4703a7606f654dabb5df330
parentac1a975f9b5a7d939663fa90556a2f038250c531

x86_64: implement switch jump tables


33 files changed, 476 insertions(+), 199 deletions(-)

lib/std/Thread/Condition.zig+3-3
...@@ -161,17 +161,17 @@ const WindowsImpl = struct {...@@ -161,17 +161,17 @@ const WindowsImpl = struct {
161 }161 }
162 }162 }
163163
164 if (comptime builtin.mode == .Debug) {164 if (builtin.mode == .Debug) {
165 // The internal state of the DebugMutex needs to be handled here as well.165 // The internal state of the DebugMutex needs to be handled here as well.
166 mutex.impl.locking_thread.store(0, .unordered);166 mutex.impl.locking_thread.store(0, .unordered);
167 }167 }
168 const rc = os.windows.kernel32.SleepConditionVariableSRW(168 const rc = os.windows.kernel32.SleepConditionVariableSRW(
169 &self.condition,169 &self.condition,
170 if (comptime builtin.mode == .Debug) &mutex.impl.impl.srwlock else &mutex.impl.srwlock,170 if (builtin.mode == .Debug) &mutex.impl.impl.srwlock else &mutex.impl.srwlock,
171 timeout_ms,171 timeout_ms,
172 0, // the srwlock was assumed to acquired in exclusive mode not shared172 0, // the srwlock was assumed to acquired in exclusive mode not shared
173 );173 );
174 if (comptime builtin.mode == .Debug) {174 if (builtin.mode == .Debug) {
175 // The internal state of the DebugMutex needs to be handled here as well.175 // The internal state of the DebugMutex needs to be handled here as well.
176 mutex.impl.locking_thread.store(std.Thread.getCurrentId(), .unordered);176 mutex.impl.locking_thread.store(std.Thread.getCurrentId(), .unordered);
177 }177 }
lib/std/Thread/Mutex.zig+1-1
...@@ -158,7 +158,7 @@ const FutexImpl = struct {...@@ -158,7 +158,7 @@ const FutexImpl = struct {
158 // On x86, use `lock bts` instead of `lock cmpxchg` as:158 // On x86, use `lock bts` instead of `lock cmpxchg` as:
159 // - they both seem to mark the cache-line as modified regardless: https://stackoverflow.com/a/63350048159 // - they both seem to mark the cache-line as modified regardless: https://stackoverflow.com/a/63350048
160 // - `lock bts` is smaller instruction-wise which makes it better for inlining160 // - `lock bts` is smaller instruction-wise which makes it better for inlining
161 if (comptime builtin.target.cpu.arch.isX86()) {161 if (builtin.target.cpu.arch.isX86()) {
162 const locked_bit = @ctz(locked);162 const locked_bit = @ctz(locked);
163 return self.state.bitSet(locked_bit, .acquire) == 0;163 return self.state.bitSet(locked_bit, .acquire) == 0;
164 }164 }
lib/std/debug.zig+3-3
...@@ -179,7 +179,7 @@ pub fn dumpHexFallible(bytes: []const u8) !void {...@@ -179,7 +179,7 @@ pub fn dumpHexFallible(bytes: []const u8) !void {
179/// TODO multithreaded awareness179/// TODO multithreaded awareness
180pub fn dumpCurrentStackTrace(start_addr: ?usize) void {180pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
181 nosuspend {181 nosuspend {
182 if (comptime builtin.target.isWasm()) {182 if (builtin.target.isWasm()) {
183 if (native_os == .wasi) {183 if (native_os == .wasi) {
184 const stderr = io.getStdErr().writer();184 const stderr = io.getStdErr().writer();
185 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;185 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
...@@ -267,7 +267,7 @@ pub inline fn getContext(context: *ThreadContext) bool {...@@ -267,7 +267,7 @@ pub inline fn getContext(context: *ThreadContext) bool {
267/// TODO multithreaded awareness267/// TODO multithreaded awareness
268pub fn dumpStackTraceFromBase(context: *ThreadContext) void {268pub fn dumpStackTraceFromBase(context: *ThreadContext) void {
269 nosuspend {269 nosuspend {
270 if (comptime builtin.target.isWasm()) {270 if (builtin.target.isWasm()) {
271 if (native_os == .wasi) {271 if (native_os == .wasi) {
272 const stderr = io.getStdErr().writer();272 const stderr = io.getStdErr().writer();
273 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;273 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
...@@ -365,7 +365,7 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT...@@ -365,7 +365,7 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT
365/// TODO multithreaded awareness365/// TODO multithreaded awareness
366pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void {366pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void {
367 nosuspend {367 nosuspend {
368 if (comptime builtin.target.isWasm()) {368 if (builtin.target.isWasm()) {
369 if (native_os == .wasi) {369 if (native_os == .wasi) {
370 const stderr = io.getStdErr().writer();370 const stderr = io.getStdErr().writer();
371 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;371 stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return;
lib/std/debug/SelfInfo.zig+4-4
...@@ -121,13 +121,13 @@ pub fn deinit(self: *SelfInfo) void {...@@ -121,13 +121,13 @@ pub fn deinit(self: *SelfInfo) void {
121}121}
122122
123pub fn getModuleForAddress(self: *SelfInfo, address: usize) !*Module {123pub fn getModuleForAddress(self: *SelfInfo, address: usize) !*Module {
124 if (comptime builtin.target.isDarwin()) {124 if (builtin.target.isDarwin()) {
125 return self.lookupModuleDyld(address);125 return self.lookupModuleDyld(address);
126 } else if (native_os == .windows) {126 } else if (native_os == .windows) {
127 return self.lookupModuleWin32(address);127 return self.lookupModuleWin32(address);
128 } else if (native_os == .haiku) {128 } else if (native_os == .haiku) {
129 return self.lookupModuleHaiku(address);129 return self.lookupModuleHaiku(address);
130 } else if (comptime builtin.target.isWasm()) {130 } else if (builtin.target.isWasm()) {
131 return self.lookupModuleWasm(address);131 return self.lookupModuleWasm(address);
132 } else {132 } else {
133 return self.lookupModuleDl(address);133 return self.lookupModuleDl(address);
...@@ -138,13 +138,13 @@ pub fn getModuleForAddress(self: *SelfInfo, address: usize) !*Module {...@@ -138,13 +138,13 @@ pub fn getModuleForAddress(self: *SelfInfo, address: usize) !*Module {
138// This can be called when getModuleForAddress fails, so implementations should provide138// This can be called when getModuleForAddress fails, so implementations should provide
139// a path that doesn't rely on any side-effects of a prior successful module lookup.139// a path that doesn't rely on any side-effects of a prior successful module lookup.
140pub fn getModuleNameForAddress(self: *SelfInfo, address: usize) ?[]const u8 {140pub fn getModuleNameForAddress(self: *SelfInfo, address: usize) ?[]const u8 {
141 if (comptime builtin.target.isDarwin()) {141 if (builtin.target.isDarwin()) {
142 return self.lookupModuleNameDyld(address);142 return self.lookupModuleNameDyld(address);
143 } else if (native_os == .windows) {143 } else if (native_os == .windows) {
144 return self.lookupModuleNameWin32(address);144 return self.lookupModuleNameWin32(address);
145 } else if (native_os == .haiku) {145 } else if (native_os == .haiku) {
146 return null;146 return null;
147 } else if (comptime builtin.target.isWasm()) {147 } else if (builtin.target.isWasm()) {
148 return null;148 return null;
149 } else {149 } else {
150 return self.lookupModuleNameDl(address);150 return self.lookupModuleNameDl(address);
lib/std/heap.zig+1-1
...@@ -890,7 +890,7 @@ test {...@@ -890,7 +890,7 @@ test {
890 _ = @import("heap/memory_pool.zig");890 _ = @import("heap/memory_pool.zig");
891 _ = ArenaAllocator;891 _ = ArenaAllocator;
892 _ = GeneralPurposeAllocator;892 _ = GeneralPurposeAllocator;
893 if (comptime builtin.target.isWasm()) {893 if (builtin.target.isWasm()) {
894 _ = WasmAllocator;894 _ = WasmAllocator;
895 _ = WasmPageAllocator;895 _ = WasmPageAllocator;
896 }896 }
lib/std/math/big/int.zig+1-1
...@@ -2523,7 +2523,7 @@ pub const Const = struct {...@@ -2523,7 +2523,7 @@ pub const Const = struct {
2523 /// Returns the number of leading zeros in twos-complement form.2523 /// Returns the number of leading zeros in twos-complement form.
2524 pub fn clz(a: Const, bits: Limb) Limb {2524 pub fn clz(a: Const, bits: Limb) Limb {
2525 // Limbs are stored in little-endian order but we need to iterate big-endian.2525 // Limbs are stored in little-endian order but we need to iterate big-endian.
2526 if (!a.positive) return 0;2526 if (!a.positive and !a.eqlZero()) return 0;
2527 var total_limb_lz: Limb = 0;2527 var total_limb_lz: Limb = 0;
2528 var i: usize = a.limbs.len;2528 var i: usize = a.limbs.len;
2529 const bits_per_limb = @bitSizeOf(Limb);2529 const bits_per_limb = @bitSizeOf(Limb);
lib/std/os.zig+1-1
...@@ -157,7 +157,7 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix....@@ -157,7 +157,7 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.
157 return target;157 return target;
158 },158 },
159 .freebsd => {159 .freebsd => {
160 if (comptime builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0, .patch = 0 }) orelse false) {160 if (builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0, .patch = 0 }) orelse false) {
161 var kfile: std.c.kinfo_file = undefined;161 var kfile: std.c.kinfo_file = undefined;
162 kfile.structsize = std.c.KINFO_FILE_SIZE;162 kfile.structsize = std.c.KINFO_FILE_SIZE;
163 switch (posix.errno(std.c.fcntl(fd, std.c.F.KINFO, @intFromPtr(&kfile)))) {163 switch (posix.errno(std.c.fcntl(fd, std.c.F.KINFO, @intFromPtr(&kfile)))) {
lib/std/os/windows.zig+1-1
...@@ -1061,7 +1061,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil...@@ -1061,7 +1061,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
1061 // us INVALID_PARAMETER.1061 // us INVALID_PARAMETER.
1062 // The same reasoning for win10_rs5 as in os.renameatW() applies (FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE requires >= win10_rs5).1062 // The same reasoning for win10_rs5 as in os.renameatW() applies (FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE requires >= win10_rs5).
1063 var need_fallback = true;1063 var need_fallback = true;
1064 if (comptime builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs5)) {1064 if (builtin.target.os.version_range.windows.min.isAtLeast(.win10_rs5)) {
1065 // Deletion with posix semantics if the filesystem supports it.1065 // Deletion with posix semantics if the filesystem supports it.
1066 var info = FILE_DISPOSITION_INFORMATION_EX{1066 var info = FILE_DISPOSITION_INFORMATION_EX{
1067 .Flags = FILE_DISPOSITION_DELETE |1067 .Flags = FILE_DISPOSITION_DELETE |
lib/std/posix.zig+1-1
...@@ -6819,7 +6819,7 @@ pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {...@@ -6819,7 +6819,7 @@ pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {
6819 }6819 }
6820 },6820 },
6821 .freebsd => {6821 .freebsd => {
6822 if (comptime builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0, .patch = 0 }) == .lt)6822 if (builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0, .patch = 0 }) == .lt)
6823 @compileError("memfd_create is unavailable on FreeBSD < 13.0");6823 @compileError("memfd_create is unavailable on FreeBSD < 13.0");
6824 const rc = system.memfd_create(name, flags);6824 const rc = system.memfd_create(name, flags);
6825 switch (errno(rc)) {6825 switch (errno(rc)) {
lib/std/posix/test.zig+1-1
...@@ -804,7 +804,7 @@ test "getrlimit and setrlimit" {...@@ -804,7 +804,7 @@ test "getrlimit and setrlimit" {
804 //804 //
805 // This happens for example if RLIMIT_MEMLOCK is bigger than ~2GiB.805 // This happens for example if RLIMIT_MEMLOCK is bigger than ~2GiB.
806 // In that case the following the limit would be RLIM_INFINITY and the following setrlimit fails with EPERM.806 // In that case the following the limit would be RLIM_INFINITY and the following setrlimit fails with EPERM.
807 if (comptime builtin.cpu.arch.isMIPS() and builtin.link_libc) {807 if (builtin.cpu.arch.isMIPS() and builtin.link_libc) {
808 if (limit.cur != linux.RLIM.INFINITY) {808 if (limit.cur != linux.RLIM.INFINITY) {
809 try posix.setrlimit(resource, limit);809 try posix.setrlimit(resource, limit);
810 }810 }
lib/std/simd.zig+4-6
...@@ -163,7 +163,7 @@ pub fn interlace(vecs: anytype) @Vector(vectorLength(@TypeOf(vecs[0])) * vecs.le...@@ -163,7 +163,7 @@ pub fn interlace(vecs: anytype) @Vector(vectorLength(@TypeOf(vecs[0])) * vecs.le
163 // The indices are correct. The problem seems to be with the @shuffle builtin.163 // The indices are correct. The problem seems to be with the @shuffle builtin.
164 // On MIPS, the test that interlaces small_base gives { 0, 2, 0, 0, 64, 255, 248, 200, 0, 0 }.164 // On MIPS, the test that interlaces small_base gives { 0, 2, 0, 0, 64, 255, 248, 200, 0, 0 }.
165 // Calling this with two inputs seems to work fine, but I'll let the compile error trigger for all inputs, just to be safe.165 // Calling this with two inputs seems to work fine, but I'll let the compile error trigger for all inputs, just to be safe.
166 comptime if (builtin.cpu.arch.isMIPS()) @compileError("TODO: Find out why interlace() doesn't work on MIPS");166 if (builtin.cpu.arch.isMIPS()) @compileError("TODO: Find out why interlace() doesn't work on MIPS");
167167
168 const VecType = @TypeOf(vecs[0]);168 const VecType = @TypeOf(vecs[0]);
169 const vecs_arr = @as([vecs.len]VecType, vecs);169 const vecs_arr = @as([vecs.len]VecType, vecs);
...@@ -248,7 +248,7 @@ test "vector patterns" {...@@ -248,7 +248,7 @@ test "vector patterns" {
248 try std.testing.expectEqual([8]u32{ 10, 20, 30, 40, 55, 66, 77, 88 }, join(base, other_base));248 try std.testing.expectEqual([8]u32{ 10, 20, 30, 40, 55, 66, 77, 88 }, join(base, other_base));
249 try std.testing.expectEqual([2]u32{ 20, 30 }, extract(base, 1, 2));249 try std.testing.expectEqual([2]u32{ 20, 30 }, extract(base, 1, 2));
250250
251 if (comptime !builtin.cpu.arch.isMIPS()) {251 if (!builtin.cpu.arch.isMIPS()) {
252 try std.testing.expectEqual([8]u32{ 10, 55, 20, 66, 30, 77, 40, 88 }, interlace(.{ base, other_base }));252 try std.testing.expectEqual([8]u32{ 10, 55, 20, 66, 30, 77, 40, 88 }, interlace(.{ base, other_base }));
253253
254 const small_braid = interlace(small_bases);254 const small_braid = interlace(small_bases);
...@@ -390,7 +390,7 @@ pub fn prefixScanWithFunc(...@@ -390,7 +390,7 @@ pub fn prefixScanWithFunc(
390 comptime identity: std.meta.Child(@TypeOf(vec)),390 comptime identity: std.meta.Child(@TypeOf(vec)),
391) if (ErrorType == void) @TypeOf(vec) else ErrorType!@TypeOf(vec) {391) if (ErrorType == void) @TypeOf(vec) else ErrorType!@TypeOf(vec) {
392 // I haven't debugged this, but it might be a cousin of sorts to what's going on with interlace.392 // I haven't debugged this, but it might be a cousin of sorts to what's going on with interlace.
393 comptime if (builtin.cpu.arch.isMIPS()) @compileError("TODO: Find out why prefixScan doesn't work on MIPS");393 if (builtin.cpu.arch.isMIPS()) @compileError("TODO: Find out why prefixScan doesn't work on MIPS");
394394
395 const len = vectorLength(@TypeOf(vec));395 const len = vectorLength(@TypeOf(vec));
396396
...@@ -465,9 +465,7 @@ test "vector prefix scan" {...@@ -465,9 +465,7 @@ test "vector prefix scan" {
465 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/22060465 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
466 if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21893466 if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21893
467467
468 if (comptime builtin.cpu.arch.isMIPS()) {468 if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
469 return error.SkipZigTest;
470 }
471469
472 const int_base = @Vector(4, i32){ 11, 23, 9, -21 };470 const int_base = @Vector(4, i32){ 11, 23, 9, -21 };
473 const float_base = @Vector(4, f32){ 2, 0.5, -10, 6.54321 };471 const float_base = @Vector(4, f32){ 2, 0.5, -10, 6.54321 };
lib/std/zig/system/NativePaths.zig+1-1
...@@ -83,7 +83,7 @@ pub fn detect(arena: Allocator, native_target: std.Target) !NativePaths {...@@ -83,7 +83,7 @@ pub fn detect(arena: Allocator, native_target: std.Target) !NativePaths {
8383
84 // TODO: consider also adding homebrew paths84 // TODO: consider also adding homebrew paths
85 // TODO: consider also adding macports paths85 // TODO: consider also adding macports paths
86 if (comptime builtin.target.isDarwin()) {86 if (builtin.target.isDarwin()) {
87 if (std.zig.system.darwin.isSdkInstalled(arena)) sdk: {87 if (std.zig.system.darwin.isSdkInstalled(arena)) sdk: {
88 const sdk = std.zig.system.darwin.getSdk(arena, native_target) orelse break :sdk;88 const sdk = std.zig.system.darwin.getSdk(arena, native_target) orelse break :sdk;
89 try self.addLibDir(try std.fs.path.join(arena, &.{ sdk, "usr/lib" }));89 try self.addLibDir(try std.fs.path.join(arena, &.{ sdk, "usr/lib" }));
src/Liveness.zig+6-13
...@@ -719,32 +719,25 @@ pub const SwitchBrTable = struct {...@@ -719,32 +719,25 @@ pub const SwitchBrTable = struct {
719719
720/// Caller owns the memory.720/// Caller owns the memory.
721pub fn getSwitchBr(l: Liveness, gpa: Allocator, inst: Air.Inst.Index, cases_len: u32) Allocator.Error!SwitchBrTable {721pub fn getSwitchBr(l: Liveness, gpa: Allocator, inst: Air.Inst.Index, cases_len: u32) Allocator.Error!SwitchBrTable {
722 var index: usize = l.special.get(inst) orelse return SwitchBrTable{722 var index: usize = l.special.get(inst) orelse return .{ .deaths = &.{} };
723 .deaths = &.{},
724 };
725 const else_death_count = l.extra[index];723 const else_death_count = l.extra[index];
726 index += 1;724 index += 1;
727725
728 var deaths = std.ArrayList([]const Air.Inst.Index).init(gpa);726 var deaths = try gpa.alloc([]const Air.Inst.Index, cases_len);
729 defer deaths.deinit();727 errdefer gpa.free(deaths);
730 try deaths.ensureTotalCapacity(cases_len + 1);
731728
732 var case_i: u32 = 0;729 var case_i: u32 = 0;
733 while (case_i < cases_len - 1) : (case_i += 1) {730 while (case_i < cases_len - 1) : (case_i += 1) {
734 const case_death_count: u32 = l.extra[index];731 const case_death_count: u32 = l.extra[index];
735 index += 1;732 index += 1;
736 const case_deaths: []const Air.Inst.Index = @ptrCast(l.extra[index..][0..case_death_count]);733 deaths[case_i] = @ptrCast(l.extra[index..][0..case_death_count]);
737 index += case_death_count;734 index += case_death_count;
738 deaths.appendAssumeCapacity(case_deaths);
739 }735 }
740 {736 {
741 // Else737 // Else
742 const else_deaths: []const Air.Inst.Index = @ptrCast(l.extra[index..][0..else_death_count]);738 deaths[case_i] = @ptrCast(l.extra[index..][0..else_death_count]);
743 deaths.appendAssumeCapacity(else_deaths);
744 }739 }
745 return SwitchBrTable{740 return .{ .deaths = deaths };
746 .deaths = try deaths.toOwnedSlice(),
747 };
748}741}
749742
750/// Note that this information is technically redundant, but is useful for743/// Note that this information is technically redundant, but is useful for
src/arch/x86_64/CodeGen.zig+273-26
...@@ -61,9 +61,10 @@ src_loc: Zcu.LazySrcLoc,...@@ -61,9 +61,10 @@ src_loc: Zcu.LazySrcLoc,
61eflags_inst: ?Air.Inst.Index = null,61eflags_inst: ?Air.Inst.Index = null,
6262
63/// MIR Instructions63/// MIR Instructions
64mir_instructions: std.MultiArrayList(Mir.Inst) = .{},64mir_instructions: std.MultiArrayList(Mir.Inst) = .empty,
65/// MIR extra data65/// MIR extra data
66mir_extra: std.ArrayListUnmanaged(u32) = .empty,66mir_extra: std.ArrayListUnmanaged(u32) = .empty,
67mir_table: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty,
6768
68/// Byte offset within the source file of the ending curly.69/// Byte offset within the source file of the ending curly.
69end_di_line: u32,70end_di_line: u32,
...@@ -75,8 +76,8 @@ end_di_column: u32,...@@ -75,8 +76,8 @@ end_di_column: u32,
75exitlude_jump_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty,76exitlude_jump_relocs: std.ArrayListUnmanaged(Mir.Inst.Index) = .empty,
7677
77reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,78reused_operands: std.StaticBitSet(Liveness.bpi - 1) = undefined,
78const_tracking: ConstTrackingMap = .{},79const_tracking: ConstTrackingMap = .empty,
79inst_tracking: InstTrackingMap = .{},80inst_tracking: InstTrackingMap = .empty,
8081
81// Key is the block instruction82// Key is the block instruction
82blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .empty,83blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .empty,
...@@ -86,16 +87,26 @@ register_manager: RegisterManager = .{},...@@ -86,16 +87,26 @@ register_manager: RegisterManager = .{},
86/// Generation of the current scope, increments by 1 for every entered scope.87/// Generation of the current scope, increments by 1 for every entered scope.
87scope_generation: u32 = 0,88scope_generation: u32 = 0,
8889
89frame_allocs: std.MultiArrayList(FrameAlloc) = .{},90frame_allocs: std.MultiArrayList(FrameAlloc) = .empty,
90free_frame_indices: std.AutoArrayHashMapUnmanaged(FrameIndex, void) = .empty,91free_frame_indices: std.AutoArrayHashMapUnmanaged(FrameIndex, void) = .empty,
91frame_locs: std.MultiArrayList(Mir.FrameLoc) = .{},92frame_locs: std.MultiArrayList(Mir.FrameLoc) = .empty,
9293
93loops: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {94loops: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
94 /// The state to restore before branching.95 /// The state to restore before branching.
95 state: State,96 state: State,
96 /// The branch target.97 /// The branch target.
97 target: Mir.Inst.Index,98 target: Mir.Inst.Index,
98}) = .{},99}) = .empty,
100loop_switches: std.AutoHashMapUnmanaged(Air.Inst.Index, struct {
101 start: u31,
102 len: u11,
103 min: Value,
104 else_relocs: union(enum) {
105 @"unreachable",
106 forward: std.ArrayListUnmanaged(Mir.Inst.Index),
107 backward: Mir.Inst.Index,
108 },
109}) = .empty,
99110
100next_temp_index: Temp.Index = @enumFromInt(0),111next_temp_index: Temp.Index = @enumFromInt(0),
101temp_type: [Temp.Index.max]Type = undefined,112temp_type: [Temp.Index.max]Type = undefined,
...@@ -904,6 +915,7 @@ pub fn generate(...@@ -904,6 +915,7 @@ pub fn generate(
904 function.free_frame_indices.deinit(gpa);915 function.free_frame_indices.deinit(gpa);
905 function.frame_locs.deinit(gpa);916 function.frame_locs.deinit(gpa);
906 function.loops.deinit(gpa);917 function.loops.deinit(gpa);
918 function.loop_switches.deinit(gpa);
907 var block_it = function.blocks.valueIterator();919 var block_it = function.blocks.valueIterator();
908 while (block_it.next()) |block| block.deinit(gpa);920 while (block_it.next()) |block| block.deinit(gpa);
909 function.blocks.deinit(gpa);921 function.blocks.deinit(gpa);
...@@ -912,6 +924,7 @@ pub fn generate(...@@ -912,6 +924,7 @@ pub fn generate(
912 function.exitlude_jump_relocs.deinit(gpa);924 function.exitlude_jump_relocs.deinit(gpa);
913 function.mir_instructions.deinit(gpa);925 function.mir_instructions.deinit(gpa);
914 function.mir_extra.deinit(gpa);926 function.mir_extra.deinit(gpa);
927 function.mir_table.deinit(gpa);
915 }928 }
916 try function.inst_tracking.ensureTotalCapacity(gpa, Temp.Index.max);929 try function.inst_tracking.ensureTotalCapacity(gpa, Temp.Index.max);
917 for (0..Temp.Index.max) |temp_index| {930 for (0..Temp.Index.max) |temp_index| {
...@@ -978,6 +991,7 @@ pub fn generate(...@@ -978,6 +991,7 @@ pub fn generate(
978 var mir: Mir = .{991 var mir: Mir = .{
979 .instructions = function.mir_instructions.toOwnedSlice(),992 .instructions = function.mir_instructions.toOwnedSlice(),
980 .extra = try function.mir_extra.toOwnedSlice(gpa),993 .extra = try function.mir_extra.toOwnedSlice(gpa),
994 .table = try function.mir_table.toOwnedSlice(gpa),
981 .frame_locs = function.frame_locs.toOwnedSlice(),995 .frame_locs = function.frame_locs.toOwnedSlice(),
982 };996 };
983 defer mir.deinit(gpa);997 defer mir.deinit(gpa);
...@@ -1012,7 +1026,6 @@ pub fn generate(...@@ -1012,7 +1026,6 @@ pub fn generate(
1012 },1026 },
1013 .prev_di_pc = 0,1027 .prev_di_pc = 0,
1014 };1028 };
1015 defer emit.deinit();
1016 emit.emitMir() catch |err| switch (err) {1029 emit.emitMir() catch |err| switch (err) {
1017 error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),1030 error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),
10181031
...@@ -1056,6 +1069,7 @@ pub fn generateLazy(...@@ -1056,6 +1069,7 @@ pub fn generateLazy(
1056 defer {1069 defer {
1057 function.mir_instructions.deinit(gpa);1070 function.mir_instructions.deinit(gpa);
1058 function.mir_extra.deinit(gpa);1071 function.mir_extra.deinit(gpa);
1072 function.mir_table.deinit(gpa);
1059 }1073 }
10601074
1061 function.genLazy(lazy_sym) catch |err| switch (err) {1075 function.genLazy(lazy_sym) catch |err| switch (err) {
...@@ -1067,6 +1081,7 @@ pub fn generateLazy(...@@ -1067,6 +1081,7 @@ pub fn generateLazy(
1067 var mir: Mir = .{1081 var mir: Mir = .{
1068 .instructions = function.mir_instructions.toOwnedSlice(),1082 .instructions = function.mir_instructions.toOwnedSlice(),
1069 .extra = try function.mir_extra.toOwnedSlice(gpa),1083 .extra = try function.mir_extra.toOwnedSlice(gpa),
1084 .table = try function.mir_table.toOwnedSlice(gpa),
1070 .frame_locs = function.frame_locs.toOwnedSlice(),1085 .frame_locs = function.frame_locs.toOwnedSlice(),
1071 };1086 };
1072 defer mir.deinit(gpa);1087 defer mir.deinit(gpa);
...@@ -1093,7 +1108,6 @@ pub fn generateLazy(...@@ -1093,7 +1108,6 @@ pub fn generateLazy(
1093 .prev_di_loc = undefined, // no debug info yet1108 .prev_di_loc = undefined, // no debug info yet
1094 .prev_di_pc = undefined, // no debug info yet1109 .prev_di_pc = undefined, // no debug info yet
1095 };1110 };
1096 defer emit.deinit();
1097 emit.emitMir() catch |err| switch (err) {1111 emit.emitMir() catch |err| switch (err) {
1098 error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),1112 error.LowerFail, error.EmitFail => return function.failMsg(emit.lower.err_msg.?),
1099 error.InvalidInstruction => return function.fail("failed to find a viable x86 instruction (Zig compiler bug)", .{}),1113 error.InvalidInstruction => return function.fail("failed to find a viable x86 instruction (Zig compiler bug)", .{}),
...@@ -1161,6 +1175,7 @@ fn formatWipMir(...@@ -1161,6 +1175,7 @@ fn formatWipMir(
1161 .mir = .{1175 .mir = .{
1162 .instructions = data.self.mir_instructions.slice(),1176 .instructions = data.self.mir_instructions.slice(),
1163 .extra = data.self.mir_extra.items,1177 .extra = data.self.mir_extra.items,
1178 .table = data.self.mir_table.items,
1164 .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(),1179 .frame_locs = (std.MultiArrayList(Mir.FrameLoc){}).slice(),
1165 },1180 },
1166 .cc = .auto,1181 .cc = .auto,
...@@ -20748,25 +20763,195 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index...@@ -20748,25 +20763,195 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index
20748 self.getValueIfFree(tracking.short, inst);20763 self.getValueIfFree(tracking.short, inst);
20749}20764}
2075020765
20751fn lowerSwitchBr(self: *CodeGen, inst: Air.Inst.Index, switch_br: Air.UnwrappedSwitch, condition: MCValue) !void {20766fn lowerSwitchBr(
20767 self: *CodeGen,
20768 inst: Air.Inst.Index,
20769 switch_br: Air.UnwrappedSwitch,
20770 condition: MCValue,
20771 condition_dies: bool,
20772 is_loop: bool,
20773) !void {
20752 const zcu = self.pt.zcu;20774 const zcu = self.pt.zcu;
20753 const condition_ty = self.typeOf(switch_br.operand);20775 const condition_ty = self.typeOf(switch_br.operand);
20754 const liveness = try self.liveness.getSwitchBr(self.gpa, inst, switch_br.cases_len + 1);
20755 defer self.gpa.free(liveness.deaths);
2075620776
20757 const signedness = switch (condition_ty.zigTypeTag(zcu)) {20777 const ExpectedContents = extern struct {
20758 .bool, .pointer => .unsigned,20778 liveness_deaths: [1 << 8 | 1]Air.Inst.Index,
20759 .int, .@"enum", .error_set => condition_ty.intInfo(zcu).signedness,20779 bigint_limbs: [std.math.big.int.calcTwosCompLimbCount(1 << 8)]std.math.big.Limb,
20760 else => unreachable,20780 relocs: [1 << 6]Mir.Inst.Index,
20761 };20781 };
20782 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
20783 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
20784 const allocator = stack.get();
2076220785
20763 self.scope_generation += 1;20786 self.scope_generation += 1;
20764 const state = try self.saveState();20787 const state = try self.saveState();
2076520788
20766 var it = switch_br.iterateCases();20789 const liveness = try self.liveness.getSwitchBr(allocator, inst, switch_br.cases_len + 1);
20767 while (it.next()) |case| {20790 defer allocator.free(liveness.deaths);
20768 var relocs = try self.gpa.alloc(Mir.Inst.Index, case.items.len + case.ranges.len);20791
20769 defer self.gpa.free(relocs);20792 if (!self.mod.pic and self.target.ofmt == .elf) table: {
20793 var prong_items: u32 = 0;
20794 var min: ?Value = null;
20795 var max: ?Value = null;
20796 {
20797 var cases_it = switch_br.iterateCases();
20798 while (cases_it.next()) |case| {
20799 prong_items += @intCast(case.items.len + case.ranges.len);
20800 for (case.items) |item| {
20801 const val = Value.fromInterned(item.toInterned().?);
20802 if (min == null or val.compareHetero(.lt, min.?, zcu)) min = val;
20803 if (max == null or val.compareHetero(.gt, max.?, zcu)) max = val;
20804 }
20805 for (case.ranges) |range| {
20806 const low = Value.fromInterned(range[0].toInterned().?);
20807 if (min == null or low.compareHetero(.lt, min.?, zcu)) min = low;
20808 const high = Value.fromInterned(range[1].toInterned().?);
20809 if (max == null or high.compareHetero(.gt, max.?, zcu)) max = high;
20810 }
20811 }
20812 }
20813 // This condition also triggers for switches with no non-else prongs and switches on bool.
20814 if (prong_items < 1 << 2 or prong_items > 1 << 8) break :table;
20815
20816 var min_space: Value.BigIntSpace = undefined;
20817 const min_bigint = min.?.toBigInt(&min_space, zcu);
20818 var max_space: Value.BigIntSpace = undefined;
20819 const max_bigint = max.?.toBigInt(&max_space, zcu);
20820 const limbs = try allocator.alloc(
20821 std.math.big.Limb,
20822 @max(min_bigint.limbs.len, max_bigint.limbs.len) + 1,
20823 );
20824 defer allocator.free(limbs);
20825 const table_len = table_len: {
20826 var table_len_bigint: std.math.big.int.Mutable = .{ .limbs = limbs, .positive = undefined, .len = undefined };
20827 table_len_bigint.sub(max_bigint, min_bigint);
20828 assert(table_len_bigint.positive); // min <= max
20829 break :table_len @as(u11, table_len_bigint.toConst().to(u10) catch break :table) + 1; // no more than a 1024 entry table
20830 };
20831 assert(prong_items <= table_len); // each prong item introduces at least one unique integer to the range
20832 if (prong_items < table_len >> 2) break :table; // no more than 75% waste
20833
20834 const condition_index = if (condition_dies and condition.isModifiable()) condition else condition_index: {
20835 const condition_index = try self.allocTempRegOrMem(condition_ty, true);
20836 try self.genCopy(condition_ty, condition_index, condition, .{});
20837 break :condition_index condition_index;
20838 };
20839 try self.spillEflagsIfOccupied();
20840 if (min.?.orderAgainstZero(zcu).compare(.neq)) try self.genBinOpMir(
20841 .{ ._, .sub },
20842 condition_ty,
20843 condition_index,
20844 .{ .air_ref = Air.internedToRef(min.?.toIntern()) },
20845 );
20846 const else_reloc = if (switch_br.else_body_len > 0) else_reloc: {
20847 try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition_index, .{ .immediate = table_len - 1 });
20848 break :else_reloc try self.asmJccReloc(.a, undefined);
20849 } else undefined;
20850 const table_start: u31 = @intCast(self.mir_table.items.len);
20851 {
20852 const condition_index_reg = if (condition_index.isRegister())
20853 condition_index.getReg().?
20854 else
20855 try self.copyToTmpRegister(.usize, condition_index);
20856 const condition_index_lock = self.register_manager.lockReg(condition_index_reg);
20857 defer if (condition_index_lock) |lock| self.register_manager.unlockReg(lock);
20858 try self.truncateRegister(condition_ty, condition_index_reg);
20859 const ptr_size = @divExact(self.target.ptrBitWidth(), 8);
20860 try self.asmMemory(.{ ._, .jmp }, .{
20861 .base = .table,
20862 .mod = .{ .rm = .{
20863 .size = .ptr,
20864 .index = registerAlias(condition_index_reg, ptr_size),
20865 .scale = .fromFactor(@intCast(ptr_size)),
20866 .disp = table_start * ptr_size,
20867 } },
20868 });
20869 }
20870 const else_reloc_marker: u32 = 0;
20871 assert(self.mir_instructions.len > else_reloc_marker);
20872 try self.mir_table.appendNTimes(self.gpa, else_reloc_marker, table_len);
20873 if (is_loop) try self.loop_switches.putNoClobber(self.gpa, inst, .{
20874 .start = table_start,
20875 .len = table_len,
20876 .min = min.?,
20877 .else_relocs = if (switch_br.else_body_len > 0) .{ .forward = .empty } else .@"unreachable",
20878 });
20879 defer if (is_loop) {
20880 var loop_switch_data = self.loop_switches.fetchRemove(inst).?.value;
20881 switch (loop_switch_data.else_relocs) {
20882 .@"unreachable", .backward => {},
20883 .forward => |*else_relocs| else_relocs.deinit(self.gpa),
20884 }
20885 };
20886 var cases_it = switch_br.iterateCases();
20887 while (cases_it.next()) |case| {
20888 {
20889 const table = self.mir_table.items[table_start..][0..table_len];
20890 for (case.items) |item| {
20891 const val = Value.fromInterned(item.toInterned().?);
20892 var val_space: Value.BigIntSpace = undefined;
20893 const val_bigint = val.toBigInt(&val_space, zcu);
20894 var index_bigint: std.math.big.int.Mutable = .{ .limbs = limbs, .positive = undefined, .len = undefined };
20895 index_bigint.sub(val_bigint, min_bigint);
20896 table[index_bigint.toConst().to(u10) catch unreachable] = @intCast(self.mir_instructions.len);
20897 }
20898 for (case.ranges) |range| {
20899 var low_space: Value.BigIntSpace = undefined;
20900 const low_bigint = Value.fromInterned(range[0].toInterned().?).toBigInt(&low_space, zcu);
20901 var high_space: Value.BigIntSpace = undefined;
20902 const high_bigint = Value.fromInterned(range[1].toInterned().?).toBigInt(&high_space, zcu);
20903 var index_bigint: std.math.big.int.Mutable = .{ .limbs = limbs, .positive = undefined, .len = undefined };
20904 index_bigint.sub(low_bigint, min_bigint);
20905 const start = index_bigint.toConst().to(u10) catch unreachable;
20906 index_bigint.sub(high_bigint, min_bigint);
20907 const end = @as(u11, index_bigint.toConst().to(u10) catch unreachable) + 1;
20908 @memset(table[start..end], @intCast(self.mir_instructions.len));
20909 }
20910 }
20911
20912 for (liveness.deaths[case.idx]) |operand| try self.processDeath(operand);
20913
20914 try self.genBodyBlock(case.body);
20915 try self.restoreState(state, &.{}, .{
20916 .emit_instructions = false,
20917 .update_tracking = true,
20918 .resurrect = true,
20919 .close_scope = true,
20920 });
20921 }
20922 if (switch_br.else_body_len > 0) {
20923 const else_body = cases_it.elseBody();
20924
20925 const else_deaths = liveness.deaths.len - 1;
20926 for (liveness.deaths[else_deaths]) |operand| try self.processDeath(operand);
20927
20928 self.performReloc(else_reloc);
20929 if (is_loop) {
20930 const loop_switch_data = self.loop_switches.getPtr(inst).?;
20931 for (loop_switch_data.else_relocs.forward.items) |reloc| self.performReloc(reloc);
20932 loop_switch_data.else_relocs.forward.deinit(self.gpa);
20933 loop_switch_data.else_relocs = .{ .backward = @intCast(self.mir_instructions.len) };
20934 }
20935 for (self.mir_table.items[table_start..][0..table_len]) |*entry| if (entry.* == else_reloc_marker) {
20936 entry.* = @intCast(self.mir_instructions.len);
20937 };
20938
20939 try self.genBodyBlock(else_body);
20940 try self.restoreState(state, &.{}, .{
20941 .emit_instructions = false,
20942 .update_tracking = true,
20943 .resurrect = true,
20944 .close_scope = true,
20945 });
20946 }
20947 return;
20948 }
20949
20950 const signedness = if (condition_ty.isAbiInt(zcu)) condition_ty.intInfo(zcu).signedness else .unsigned;
20951 var cases_it = switch_br.iterateCases();
20952 while (cases_it.next()) |case| {
20953 var relocs = try allocator.alloc(Mir.Inst.Index, case.items.len + case.ranges.len);
20954 defer allocator.free(relocs);
2077020955
20771 try self.spillEflagsIfOccupied();20956 try self.spillEflagsIfOccupied();
20772 for (case.items, relocs[0..case.items.len]) |item, *reloc| {20957 for (case.items, relocs[0..case.items.len]) |item, *reloc| {
...@@ -20849,9 +21034,8 @@ fn lowerSwitchBr(self: *CodeGen, inst: Air.Inst.Index, switch_br: Air.UnwrappedS...@@ -20849,9 +21034,8 @@ fn lowerSwitchBr(self: *CodeGen, inst: Air.Inst.Index, switch_br: Air.UnwrappedS
20849 // Relocate the "skip" branch to fall through to the next case.21034 // Relocate the "skip" branch to fall through to the next case.
20850 self.performReloc(skip_case_reloc);21035 self.performReloc(skip_case_reloc);
20851 }21036 }
20852
20853 if (switch_br.else_body_len > 0) {21037 if (switch_br.else_body_len > 0) {
20854 const else_body = it.elseBody();21038 const else_body = cases_it.elseBody();
2085521039
20856 const else_deaths = liveness.deaths.len - 1;21040 const else_deaths = liveness.deaths.len - 1;
20857 for (liveness.deaths[else_deaths]) |operand| try self.processDeath(operand);21041 for (liveness.deaths[else_deaths]) |operand| try self.processDeath(operand);
...@@ -20873,11 +21057,11 @@ fn airSwitchBr(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20873,11 +21057,11 @@ fn airSwitchBr(self: *CodeGen, inst: Air.Inst.Index) !void {
20873 // If the condition dies here in this switch instruction, process21057 // If the condition dies here in this switch instruction, process
20874 // that death now instead of later as this has an effect on21058 // that death now instead of later as this has an effect on
20875 // whether it needs to be spilled in the branches21059 // whether it needs to be spilled in the branches
20876 if (self.liveness.operandDies(inst, 0)) {21060 const condition_dies = self.liveness.operandDies(inst, 0);
21061 if (condition_dies) {
20877 if (switch_br.operand.toIndex()) |op_inst| try self.processDeath(op_inst);21062 if (switch_br.operand.toIndex()) |op_inst| try self.processDeath(op_inst);
20878 }21063 }
2087921064 try self.lowerSwitchBr(inst, switch_br, condition, condition_dies, false);
20880 try self.lowerSwitchBr(inst, switch_br, condition);
2088121065
20882 // We already took care of pl_op.operand earlier, so there's nothing left to do21066 // We already took care of pl_op.operand earlier, so there's nothing left to do
20883}21067}
...@@ -20915,7 +21099,7 @@ fn airLoopSwitchBr(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20915,7 +21099,7 @@ fn airLoopSwitchBr(self: *CodeGen, inst: Air.Inst.Index) !void {
20915 // Stop tracking block result without forgetting tracking info21099 // Stop tracking block result without forgetting tracking info
20916 try self.freeValue(mat_cond);21100 try self.freeValue(mat_cond);
2091721101
20918 try self.lowerSwitchBr(inst, switch_br, mat_cond);21102 try self.lowerSwitchBr(inst, switch_br, mat_cond, true, true);
2091921103
20920 try self.processDeath(inst);21104 try self.processDeath(inst);
20921}21105}
...@@ -20924,8 +21108,67 @@ fn airSwitchDispatch(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -20924,8 +21108,67 @@ fn airSwitchDispatch(self: *CodeGen, inst: Air.Inst.Index) !void {
20924 const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br;21108 const br = self.air.instructions.items(.data)[@intFromEnum(inst)].br;
2092521109
20926 const block_ty = self.typeOfIndex(br.block_inst);21110 const block_ty = self.typeOfIndex(br.block_inst);
20927 const block_tracking = self.inst_tracking.getPtr(br.block_inst).?;
20928 const loop_data = self.loops.getPtr(br.block_inst).?;21111 const loop_data = self.loops.getPtr(br.block_inst).?;
21112 if (self.loop_switches.getPtr(br.block_inst)) |table| {
21113 // Process operand death so that it is properly accounted for in the State below.
21114 const condition_dies = self.liveness.operandDies(inst, 0);
21115
21116 try self.restoreState(loop_data.state, &.{}, .{
21117 .emit_instructions = true,
21118 .update_tracking = false,
21119 .resurrect = false,
21120 .close_scope = false,
21121 });
21122
21123 const condition_ty = self.typeOf(br.operand);
21124 const condition = try self.resolveInst(br.operand);
21125 const condition_index = if (condition_dies and condition.isModifiable()) condition else condition_index: {
21126 const condition_index = try self.allocTempRegOrMem(condition_ty, true);
21127 try self.genCopy(condition_ty, condition_index, condition, .{});
21128 break :condition_index condition_index;
21129 };
21130 try self.spillEflagsIfOccupied();
21131 if (table.min.orderAgainstZero(self.pt.zcu).compare(.neq)) try self.genBinOpMir(
21132 .{ ._, .sub },
21133 condition_ty,
21134 condition_index,
21135 .{ .air_ref = Air.internedToRef(table.min.toIntern()) },
21136 );
21137 switch (table.else_relocs) {
21138 .@"unreachable" => {},
21139 .forward => |*else_relocs| {
21140 try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition_index, .{ .immediate = table.len - 1 });
21141 try else_relocs.append(self.gpa, try self.asmJccReloc(.a, undefined));
21142 },
21143 .backward => |else_reloc| {
21144 try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition_index, .{ .immediate = table.len - 1 });
21145 _ = try self.asmJccReloc(.a, else_reloc);
21146 },
21147 }
21148 {
21149 const condition_index_reg = if (condition_index.isRegister())
21150 condition_index.getReg().?
21151 else
21152 try self.copyToTmpRegister(.usize, condition_index);
21153 const condition_index_lock = self.register_manager.lockReg(condition_index_reg);
21154 defer if (condition_index_lock) |lock| self.register_manager.unlockReg(lock);
21155 try self.truncateRegister(condition_ty, condition_index_reg);
21156 const ptr_size = @divExact(self.target.ptrBitWidth(), 8);
21157 try self.asmMemory(.{ ._, .jmp }, .{
21158 .base = .table,
21159 .mod = .{ .rm = .{
21160 .size = .ptr,
21161 .index = registerAlias(condition_index_reg, ptr_size),
21162 .scale = .fromFactor(@intCast(ptr_size)),
21163 .disp = @intCast(table.start * ptr_size),
21164 } },
21165 });
21166 }
21167
21168 return self.finishAir(inst, .none, .{ br.operand, .none, .none });
21169 }
21170
21171 const block_tracking = self.inst_tracking.getPtr(br.block_inst).?;
20929 done: {21172 done: {
20930 try self.getValue(block_tracking.short, null);21173 try self.getValue(block_tracking.short, null);
20931 const src_mcv = try self.resolveInst(br.operand);21174 const src_mcv = try self.resolveInst(br.operand);
...@@ -22543,6 +22786,7 @@ fn genSetMem(...@@ -22543,6 +22786,7 @@ fn genSetMem(
22543 .none => .{ .immediate = @bitCast(@as(i64, disp)) },22786 .none => .{ .immediate = @bitCast(@as(i64, disp)) },
22544 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },22787 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
22545 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },22788 .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } },
22789 .table => unreachable,
22546 .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } },22790 .reloc => |sym_index| .{ .lea_symbol = .{ .sym_index = sym_index, .off = disp } },
22547 };22791 };
22548 switch (src_mcv) {22792 switch (src_mcv) {
...@@ -22652,6 +22896,7 @@ fn genSetMem(...@@ -22652,6 +22896,7 @@ fn genSetMem(
22652 .index = frame_index,22896 .index = frame_index,
22653 .off = disp,22897 .off = disp,
22654 }).compare(.gte, src_align),22898 }).compare(.gte, src_align),
22899 .table => unreachable,
22655 .reloc => false,22900 .reloc => false,
22656 })).write(22901 })).write(
22657 self,22902 self,
...@@ -23260,6 +23505,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -23260,6 +23505,7 @@ fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void {
23260 const ptr_lock = switch (ptr_mem.base) {23505 const ptr_lock = switch (ptr_mem.base) {
23261 .none, .frame, .reloc => null,23506 .none, .frame, .reloc => null,
23262 .reg => |reg| self.register_manager.lockReg(reg),23507 .reg => |reg| self.register_manager.lockReg(reg),
23508 .table => unreachable,
23263 };23509 };
23264 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);23510 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
2326523511
...@@ -23327,6 +23573,7 @@ fn atomicOp(...@@ -23327,6 +23573,7 @@ fn atomicOp(
23327 const mem_lock = switch (ptr_mem.base) {23573 const mem_lock = switch (ptr_mem.base) {
23328 .none, .frame, .reloc => null,23574 .none, .frame, .reloc => null,
23329 .reg => |reg| self.register_manager.lockReg(reg),23575 .reg => |reg| self.register_manager.lockReg(reg),
23576 .table => unreachable,
23330 };23577 };
23331 defer if (mem_lock) |lock| self.register_manager.unlockReg(lock);23578 defer if (mem_lock) |lock| self.register_manager.unlockReg(lock);
2333223579
src/arch/x86_64/Emit.zig+58-34
...@@ -10,22 +10,21 @@ prev_di_loc: Loc,...@@ -10,22 +10,21 @@ prev_di_loc: Loc,
10/// Relative to the beginning of `code`.10/// Relative to the beginning of `code`.
11prev_di_pc: usize,11prev_di_pc: usize,
1212
13code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .empty,
14relocs: std.ArrayListUnmanaged(Reloc) = .empty,
15
16pub const Error = Lower.Error || error{13pub const Error = Lower.Error || error{
17 EmitFail,14 EmitFail,
18} || link.File.UpdateDebugInfoError;15} || link.File.UpdateDebugInfoError;
1916
20pub fn emitMir(emit: *Emit) Error!void {17pub fn emitMir(emit: *Emit) Error!void {
21 const gpa = emit.lower.bin_file.comp.gpa;18 const gpa = emit.lower.bin_file.comp.gpa;
19 const code_offset_mapping = try emit.lower.allocator.alloc(u32, emit.lower.mir.instructions.len);
20 defer emit.lower.allocator.free(code_offset_mapping);
21 var relocs: std.ArrayListUnmanaged(Reloc) = .empty;
22 defer relocs.deinit(emit.lower.allocator);
23 var table_relocs: std.ArrayListUnmanaged(TableReloc) = .empty;
24 defer table_relocs.deinit(emit.lower.allocator);
22 for (0..emit.lower.mir.instructions.len) |mir_i| {25 for (0..emit.lower.mir.instructions.len) |mir_i| {
23 const mir_index: Mir.Inst.Index = @intCast(mir_i);26 const mir_index: Mir.Inst.Index = @intCast(mir_i);
24 try emit.code_offset_mapping.putNoClobber(27 code_offset_mapping[mir_index] = @intCast(emit.code.items.len);
25 emit.lower.allocator,
26 mir_index,
27 @intCast(emit.code.items.len),
28 );
29 const lowered = try emit.lower.lowerMir(mir_index);28 const lowered = try emit.lower.lowerMir(mir_index);
30 var lowered_relocs = lowered.relocs;29 var lowered_relocs = lowered.relocs;
31 for (lowered.insts, 0..) |lowered_inst, lowered_index| {30 for (lowered.insts, 0..) |lowered_inst, lowered_index| {
...@@ -89,13 +88,17 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -89,13 +88,17 @@ pub fn emitMir(emit: *Emit) Error!void {
89 lowered_relocs[0].lowered_inst_index == lowered_index) : ({88 lowered_relocs[0].lowered_inst_index == lowered_index) : ({
90 lowered_relocs = lowered_relocs[1..];89 lowered_relocs = lowered_relocs[1..];
91 }) switch (lowered_relocs[0].target) {90 }) switch (lowered_relocs[0].target) {
92 .inst => |target| try emit.relocs.append(emit.lower.allocator, .{91 .inst => |target| try relocs.append(emit.lower.allocator, .{
93 .source = start_offset,92 .source = start_offset,
94 .source_offset = end_offset - 4,93 .source_offset = end_offset - 4,
95 .target = target,94 .target = target,
96 .target_offset = lowered_relocs[0].off,95 .target_offset = lowered_relocs[0].off,
97 .length = @intCast(end_offset - start_offset),96 .length = @intCast(end_offset - start_offset),
98 }),97 }),
98 .table => try table_relocs.append(emit.lower.allocator, .{
99 .source_offset = end_offset - 4,
100 .target_offset = lowered_relocs[0].off,
101 }),
99 .linker_extern_fn => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {102 .linker_extern_fn => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
100 // Add relocation to the decl.103 // Add relocation to the decl.
101 const zo = elf_file.zigObjectPtr().?;104 const zo = elf_file.zigObjectPtr().?;
...@@ -103,7 +106,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -103,7 +106,7 @@ pub fn emitMir(emit: *Emit) Error!void {
103 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);106 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
104 try atom_ptr.addReloc(gpa, .{107 try atom_ptr.addReloc(gpa, .{
105 .r_offset = end_offset - 4,108 .r_offset = end_offset - 4,
106 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,109 .r_info = @as(u64, sym_index) << 32 | r_type,
107 .r_addend = lowered_relocs[0].off - 4,110 .r_addend = lowered_relocs[0].off - 4,
108 }, zo);111 }, zo);
109 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {112 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
...@@ -150,7 +153,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -150,7 +153,7 @@ pub fn emitMir(emit: *Emit) Error!void {
150 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);153 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
151 try atom.addReloc(gpa, .{154 try atom.addReloc(gpa, .{
152 .r_offset = end_offset - 4,155 .r_offset = end_offset - 4,
153 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,156 .r_info = @as(u64, sym_index) << 32 | r_type,
154 .r_addend = lowered_relocs[0].off - 4,157 .r_addend = lowered_relocs[0].off - 4,
155 }, zo);158 }, zo);
156 },159 },
...@@ -161,7 +164,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -161,7 +164,7 @@ pub fn emitMir(emit: *Emit) Error!void {
161 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);164 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
162 try atom.addReloc(gpa, .{165 try atom.addReloc(gpa, .{
163 .r_offset = end_offset - 4,166 .r_offset = end_offset - 4,
164 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,167 .r_info = @as(u64, sym_index) << 32 | r_type,
165 .r_addend = lowered_relocs[0].off,168 .r_addend = lowered_relocs[0].off,
166 }, zo);169 }, zo);
167 },170 },
...@@ -176,7 +179,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -176,7 +179,7 @@ pub fn emitMir(emit: *Emit) Error!void {
176 @intFromEnum(std.elf.R_X86_64.PC32);179 @intFromEnum(std.elf.R_X86_64.PC32);
177 try atom.addReloc(gpa, .{180 try atom.addReloc(gpa, .{
178 .r_offset = end_offset - 4,181 .r_offset = end_offset - 4,
179 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,182 .r_info = @as(u64, sym_index) << 32 | r_type,
180 .r_addend = lowered_relocs[0].off - 4,183 .r_addend = lowered_relocs[0].off - 4,
181 }, zo);184 }, zo);
182 } else {185 } else {
...@@ -186,7 +189,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -186,7 +189,7 @@ pub fn emitMir(emit: *Emit) Error!void {
186 @intFromEnum(std.elf.R_X86_64.@"32");189 @intFromEnum(std.elf.R_X86_64.@"32");
187 try atom.addReloc(gpa, .{190 try atom.addReloc(gpa, .{
188 .r_offset = end_offset - 4,191 .r_offset = end_offset - 4,
189 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,192 .r_info = @as(u64, sym_index) << 32 | r_type,
190 .r_addend = lowered_relocs[0].off,193 .r_addend = lowered_relocs[0].off,
191 }, zo);194 }, zo);
192 }195 }
...@@ -412,7 +415,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -412,7 +415,7 @@ pub fn emitMir(emit: *Emit) Error!void {
412 loc_buf[0] = switch (mem.base()) {415 loc_buf[0] = switch (mem.base()) {
413 .none => .{ .constu = 0 },416 .none => .{ .constu = 0 },
414 .reg => |reg| .{ .breg = reg.dwarfNum() },417 .reg => |reg| .{ .breg = reg.dwarfNum() },
415 .frame => unreachable,418 .frame, .table => unreachable,
416 .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },419 .reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
417 };420 };
418 break :base &loc_buf[0];421 break :base &loc_buf[0];
...@@ -463,13 +466,40 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -463,13 +466,40 @@ pub fn emitMir(emit: *Emit) Error!void {
463 }466 }
464 }467 }
465 }468 }
466 try emit.fixupRelocs();469 {
467}470 // TODO this function currently assumes all relocs via JMP/CALL instructions are 32bit in size.
471 // This should be reversed like it is done in aarch64 MIR emit code: start with the smallest
472 // possible resolution, i.e., 8bit, and iteratively converge on the minimum required resolution
473 // until the entire decl is correctly emitted with all JMP/CALL instructions within range.
474 for (relocs.items) |reloc| {
475 const target = code_offset_mapping[reloc.target];
476 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length)) + reloc.target_offset;
477 std.mem.writeInt(i32, emit.code.items[reloc.source_offset..][0..4], @intCast(disp), .little);
478 }
479 }
480 if (emit.lower.mir.table.len > 0) {
481 if (emit.lower.bin_file.cast(.elf)) |elf_file| {
482 const zo = elf_file.zigObjectPtr().?;
483 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
468484
469pub fn deinit(emit: *Emit) void {485 const ptr_size = @divExact(emit.lower.target.ptrBitWidth(), 8);
470 emit.relocs.deinit(emit.lower.allocator);486 var table_offset = std.mem.alignForward(u32, @intCast(emit.code.items.len), ptr_size);
471 emit.code_offset_mapping.deinit(emit.lower.allocator);487 for (table_relocs.items) |table_reloc| try atom.addReloc(gpa, .{
472 emit.* = undefined;488 .r_offset = table_reloc.source_offset,
489 .r_info = @as(u64, emit.atom_index) << 32 | @intFromEnum(std.elf.R_X86_64.@"32"),
490 .r_addend = @as(i64, table_offset) + table_reloc.target_offset,
491 }, zo);
492 for (emit.lower.mir.table) |entry| {
493 try atom.addReloc(gpa, .{
494 .r_offset = table_offset,
495 .r_info = @as(u64, emit.atom_index) << 32 | @intFromEnum(std.elf.R_X86_64.@"64"),
496 .r_addend = code_offset_mapping[entry],
497 }, zo);
498 table_offset += ptr_size;
499 }
500 try emit.code.appendNTimes(gpa, 0, table_offset - emit.code.items.len);
501 } else unreachable;
502 }
473}503}
474504
475fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {505fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
...@@ -481,7 +511,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {...@@ -481,7 +511,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
481511
482const Reloc = struct {512const Reloc = struct {
483 /// Offset of the instruction.513 /// Offset of the instruction.
484 source: usize,514 source: u32,
485 /// Offset of the relocation within the instruction.515 /// Offset of the relocation within the instruction.
486 source_offset: u32,516 source_offset: u32,
487 /// Target of the relocation.517 /// Target of the relocation.
...@@ -492,18 +522,12 @@ const Reloc = struct {...@@ -492,18 +522,12 @@ const Reloc = struct {
492 length: u5,522 length: u5,
493};523};
494524
495fn fixupRelocs(emit: *Emit) Error!void {525const TableReloc = struct {
496 // TODO this function currently assumes all relocs via JMP/CALL instructions are 32bit in size.526 /// Offset of the relocation.
497 // This should be reversed like it is done in aarch64 MIR emit code: start with the smallest527 source_offset: u32,
498 // possible resolution, i.e., 8bit, and iteratively converge on the minimum required resolution528 /// Offset from the start of the table.
499 // until the entire decl is correctly emitted with all JMP/CALL instructions within range.529 target_offset: i32,
500 for (emit.relocs.items) |reloc| {530};
501 const target = emit.code_offset_mapping.get(reloc.target) orelse
502 return emit.fail("JMP/CALL relocation target not found!", .{});
503 const disp = @as(i64, @intCast(target)) - @as(i64, @intCast(reloc.source + reloc.length)) + reloc.target_offset;
504 std.mem.writeInt(i32, emit.code.items[reloc.source_offset..][0..4], @intCast(disp), .little);
505 }
506}
507531
508const Loc = struct {532const Loc = struct {
509 line: u32,533 line: u32,
src/arch/x86_64/Lower.zig+12-3
...@@ -57,6 +57,7 @@ pub const Reloc = struct {...@@ -57,6 +57,7 @@ pub const Reloc = struct {
5757
58 const Target = union(enum) {58 const Target = union(enum) {
59 inst: Mir.Inst.Index,59 inst: Mir.Inst.Index,
60 table,
60 linker_reloc: u32,61 linker_reloc: u32,
61 linker_tlsld: u32,62 linker_tlsld: u32,
62 linker_dtpoff: u32,63 linker_dtpoff: u32,
...@@ -348,7 +349,7 @@ pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {...@@ -348,7 +349,7 @@ pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {
348 return error.LowerFail;349 return error.LowerFail;
349}350}
350351
351pub fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {352pub fn imm(lower: *const Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
352 return switch (ops) {353 return switch (ops) {
353 .rri_s,354 .rri_s,
354 .ri_s,355 .ri_s,
...@@ -379,8 +380,16 @@ pub fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {...@@ -379,8 +380,16 @@ pub fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
379 };380 };
380}381}
381382
382pub fn mem(lower: Lower, payload: u32) Memory {383pub fn mem(lower: *Lower, payload: u32) Memory {
383 return lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();384 var m = lower.mir.resolveFrameLoc(lower.mir.extraData(Mir.Memory, payload).data).decode();
385 switch (m) {
386 .sib => |*sib| switch (sib.base) {
387 else => {},
388 .table => sib.disp = lower.reloc(.table, sib.disp).signed,
389 },
390 else => {},
391 }
392 return m;
384}393}
385394
386fn reloc(lower: *Lower, target: Reloc.Target, off: i32) Immediate {395fn reloc(lower: *Lower, target: Reloc.Target, off: i32) Immediate {
src/arch/x86_64/Mir.zig+6-3
...@@ -9,6 +9,7 @@...@@ -9,6 +9,7 @@
9instructions: std.MultiArrayList(Inst).Slice,9instructions: std.MultiArrayList(Inst).Slice,
10/// The meaning of this data is determined by `Inst.Tag` value.10/// The meaning of this data is determined by `Inst.Tag` value.
11extra: []const u32,11extra: []const u32,
12table: []const Inst.Index,
12frame_locs: std.MultiArrayList(FrameLoc).Slice,13frame_locs: std.MultiArrayList(FrameLoc).Slice,
1314
14pub const Inst = struct {15pub const Inst = struct {
...@@ -1237,7 +1238,7 @@ pub const Memory = struct {...@@ -1237,7 +1238,7 @@ pub const Memory = struct {
1237 size: bits.Memory.Size,1238 size: bits.Memory.Size,
1238 index: Register,1239 index: Register,
1239 scale: bits.Memory.Scale,1240 scale: bits.Memory.Scale,
1240 _: u16 = undefined,1241 _: u15 = undefined,
1241 };1242 };
12421243
1243 pub fn encode(mem: bits.Memory) Memory {1244 pub fn encode(mem: bits.Memory) Memory {
...@@ -1260,7 +1261,7 @@ pub const Memory = struct {...@@ -1260,7 +1261,7 @@ pub const Memory = struct {
1260 },1261 },
1261 },1262 },
1262 .base = switch (mem.base) {1263 .base = switch (mem.base) {
1263 .none => undefined,1264 .none, .table => undefined,
1264 .reg => |reg| @intFromEnum(reg),1265 .reg => |reg| @intFromEnum(reg),
1265 .frame => |frame_index| @intFromEnum(frame_index),1266 .frame => |frame_index| @intFromEnum(frame_index),
1266 .reloc => |sym_index| sym_index,1267 .reloc => |sym_index| sym_index,
...@@ -1289,6 +1290,7 @@ pub const Memory = struct {...@@ -1289,6 +1290,7 @@ pub const Memory = struct {
1289 .none => .none,1290 .none => .none,
1290 .reg => .{ .reg = @enumFromInt(mem.base) },1291 .reg => .{ .reg = @enumFromInt(mem.base) },
1291 .frame => .{ .frame = @enumFromInt(mem.base) },1292 .frame => .{ .frame = @enumFromInt(mem.base) },
1293 .table => .table,
1292 .reloc => .{ .reloc = mem.base },1294 .reloc => .{ .reloc = mem.base },
1293 },1295 },
1294 .scale_index = switch (mem.info.index) {1296 .scale_index = switch (mem.info.index) {
...@@ -1317,6 +1319,7 @@ pub const Memory = struct {...@@ -1317,6 +1319,7 @@ pub const Memory = struct {
1317pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {1319pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
1318 mir.instructions.deinit(gpa);1320 mir.instructions.deinit(gpa);
1319 gpa.free(mir.extra);1321 gpa.free(mir.extra);
1322 gpa.free(mir.table);
1320 mir.frame_locs.deinit(gpa);1323 mir.frame_locs.deinit(gpa);
1321 mir.* = undefined;1324 mir.* = undefined;
1322}1325}
...@@ -1352,7 +1355,7 @@ pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffse...@@ -1352,7 +1355,7 @@ pub fn resolveFrameAddr(mir: Mir, frame_addr: bits.FrameAddr) bits.RegisterOffse
13521355
1353pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {1356pub fn resolveFrameLoc(mir: Mir, mem: Memory) Memory {
1354 return switch (mem.info.base) {1357 return switch (mem.info.base) {
1355 .none, .reg, .reloc => mem,1358 .none, .reg, .table, .reloc => mem,
1356 .frame => if (mir.frame_locs.len > 0) .{1359 .frame => if (mir.frame_locs.len > 0) .{
1357 .info = .{1360 .info = .{
1358 .base = .reg,1361 .base = .reg,
src/arch/x86_64/bits.zig+3-2
...@@ -482,17 +482,18 @@ pub const Memory = struct {...@@ -482,17 +482,18 @@ pub const Memory = struct {
482 base: Base = .none,482 base: Base = .none,
483 mod: Mod = .{ .rm = .{} },483 mod: Mod = .{ .rm = .{} },
484484
485 pub const Base = union(enum(u2)) {485 pub const Base = union(enum(u3)) {
486 none,486 none,
487 reg: Register,487 reg: Register,
488 frame: FrameIndex,488 frame: FrameIndex,
489 table,
489 reloc: u32,490 reloc: u32,
490491
491 pub const Tag = @typeInfo(Base).@"union".tag_type.?;492 pub const Tag = @typeInfo(Base).@"union".tag_type.?;
492493
493 pub fn isExtended(self: Base) bool {494 pub fn isExtended(self: Base) bool {
494 return switch (self) {495 return switch (self) {
495 .none, .frame, .reloc => false, // rsp, rbp, and rip are not extended496 .none, .frame, .table, .reloc => false, // rsp, rbp, and rip are not extended
496 .reg => |reg| reg.isExtended(),497 .reg => |reg| reg.isExtended(),
497 };498 };
498 }499 }
src/arch/x86_64/encoder.zig+52-51
...@@ -138,7 +138,7 @@ pub const Instruction = struct {...@@ -138,7 +138,7 @@ pub const Instruction = struct {
138 .moffs => true,138 .moffs => true,
139 .rip => false,139 .rip => false,
140 .sib => |s| switch (s.base) {140 .sib => |s| switch (s.base) {
141 .none, .frame, .reloc => false,141 .none, .frame, .table, .reloc => false,
142 .reg => |reg| reg.class() == .segment,142 .reg => |reg| reg.class() == .segment,
143 },143 },
144 };144 };
...@@ -161,9 +161,9 @@ pub const Instruction = struct {...@@ -161,9 +161,9 @@ pub const Instruction = struct {
161161
162 pub fn disp(mem: Memory) Immediate {162 pub fn disp(mem: Memory) Immediate {
163 return switch (mem) {163 return switch (mem) {
164 .sib => |s| Immediate.s(s.disp),164 .sib => |s| .s(s.disp),
165 .rip => |r| Immediate.s(r.disp),165 .rip => |r| .s(r.disp),
166 .moffs => |m| Immediate.u(m.offset),166 .moffs => |m| .u(m.offset),
167 };167 };
168 }168 }
169169
...@@ -277,6 +277,7 @@ pub const Instruction = struct {...@@ -277,6 +277,7 @@ pub const Instruction = struct {
277 .none => any = false,277 .none => any = false,
278 .reg => |reg| try writer.print("{s}", .{@tagName(reg)}),278 .reg => |reg| try writer.print("{s}", .{@tagName(reg)}),
279 .frame => |frame_index| try writer.print("{}", .{frame_index}),279 .frame => |frame_index| try writer.print("{}", .{frame_index}),
280 .table => try writer.print("Table", .{}),
280 .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}),281 .reloc => |sym_index| try writer.print("Symbol({d})", .{sym_index}),
281 }282 }
282 if (mem.scaleIndex()) |si| {283 if (mem.scaleIndex()) |si| {
...@@ -614,7 +615,7 @@ pub const Instruction = struct {...@@ -614,7 +615,7 @@ pub const Instruction = struct {
614 switch (mem) {615 switch (mem) {
615 .moffs => unreachable,616 .moffs => unreachable,
616 .sib => |sib| switch (sib.base) {617 .sib => |sib| switch (sib.base) {
617 .none => {618 .none, .table => {
618 try encoder.modRm_SIBDisp0(operand_enc);619 try encoder.modRm_SIBDisp0(operand_enc);
619 if (mem.scaleIndex()) |si| {620 if (mem.scaleIndex()) |si| {
620 const scale = math.log2_int(u4, si.scale);621 const scale = math.log2_int(u4, si.scale);
...@@ -1191,7 +1192,7 @@ const TestEncode = struct {...@@ -1191,7 +1192,7 @@ const TestEncode = struct {
1191 ) !void {1192 ) !void {
1192 var stream = std.io.fixedBufferStream(&enc.buffer);1193 var stream = std.io.fixedBufferStream(&enc.buffer);
1193 var count_writer = std.io.countingWriter(stream.writer());1194 var count_writer = std.io.countingWriter(stream.writer());
1194 const inst = try Instruction.new(.none, mnemonic, ops);1195 const inst: Instruction = try .new(.none, mnemonic, ops);
1195 try inst.encode(count_writer.writer(), .{});1196 try inst.encode(count_writer.writer(), .{});
1196 enc.index = count_writer.bytes_written;1197 enc.index = count_writer.bytes_written;
1197 }1198 }
...@@ -1205,9 +1206,9 @@ test "encode" {...@@ -1205,9 +1206,9 @@ test "encode" {
1205 var buf = std.ArrayList(u8).init(testing.allocator);1206 var buf = std.ArrayList(u8).init(testing.allocator);
1206 defer buf.deinit();1207 defer buf.deinit();
12071208
1208 const inst = try Instruction.new(.none, .mov, &.{1209 const inst: Instruction = try .new(.none, .mov, &.{
1209 .{ .reg = .rbx },1210 .{ .reg = .rbx },
1210 .{ .imm = Instruction.Immediate.u(4) },1211 .{ .imm = .u(4) },
1211 });1212 });
1212 try inst.encode(buf.writer(), .{});1213 try inst.encode(buf.writer(), .{});
1213 try testing.expectEqualSlices(u8, &.{ 0x48, 0xc7, 0xc3, 0x4, 0x0, 0x0, 0x0 }, buf.items);1214 try testing.expectEqualSlices(u8, &.{ 0x48, 0xc7, 0xc3, 0x4, 0x0, 0x0, 0x0 }, buf.items);
...@@ -1217,47 +1218,47 @@ test "lower I encoding" {...@@ -1217,47 +1218,47 @@ test "lower I encoding" {
1217 var enc = TestEncode{};1218 var enc = TestEncode{};
12181219
1219 try enc.encode(.push, &.{1220 try enc.encode(.push, &.{
1220 .{ .imm = Instruction.Immediate.u(0x10) },1221 .{ .imm = .u(0x10) },
1221 });1222 });
1222 try expectEqualHexStrings("\x6A\x10", enc.code(), "push 0x10");1223 try expectEqualHexStrings("\x6A\x10", enc.code(), "push 0x10");
12231224
1224 try enc.encode(.push, &.{1225 try enc.encode(.push, &.{
1225 .{ .imm = Instruction.Immediate.u(0x1000) },1226 .{ .imm = .u(0x1000) },
1226 });1227 });
1227 try expectEqualHexStrings("\x66\x68\x00\x10", enc.code(), "push 0x1000");1228 try expectEqualHexStrings("\x66\x68\x00\x10", enc.code(), "push 0x1000");
12281229
1229 try enc.encode(.push, &.{1230 try enc.encode(.push, &.{
1230 .{ .imm = Instruction.Immediate.u(0x10000000) },1231 .{ .imm = .u(0x10000000) },
1231 });1232 });
1232 try expectEqualHexStrings("\x68\x00\x00\x00\x10", enc.code(), "push 0x10000000");1233 try expectEqualHexStrings("\x68\x00\x00\x00\x10", enc.code(), "push 0x10000000");
12331234
1234 try enc.encode(.adc, &.{1235 try enc.encode(.adc, &.{
1235 .{ .reg = .rax },1236 .{ .reg = .rax },
1236 .{ .imm = Instruction.Immediate.u(0x10000000) },1237 .{ .imm = .u(0x10000000) },
1237 });1238 });
1238 try expectEqualHexStrings("\x48\x15\x00\x00\x00\x10", enc.code(), "adc rax, 0x10000000");1239 try expectEqualHexStrings("\x48\x15\x00\x00\x00\x10", enc.code(), "adc rax, 0x10000000");
12391240
1240 try enc.encode(.add, &.{1241 try enc.encode(.add, &.{
1241 .{ .reg = .al },1242 .{ .reg = .al },
1242 .{ .imm = Instruction.Immediate.u(0x10) },1243 .{ .imm = .u(0x10) },
1243 });1244 });
1244 try expectEqualHexStrings("\x04\x10", enc.code(), "add al, 0x10");1245 try expectEqualHexStrings("\x04\x10", enc.code(), "add al, 0x10");
12451246
1246 try enc.encode(.add, &.{1247 try enc.encode(.add, &.{
1247 .{ .reg = .rax },1248 .{ .reg = .rax },
1248 .{ .imm = Instruction.Immediate.u(0x10) },1249 .{ .imm = .u(0x10) },
1249 });1250 });
1250 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");1251 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
12511252
1252 try enc.encode(.sbb, &.{1253 try enc.encode(.sbb, &.{
1253 .{ .reg = .ax },1254 .{ .reg = .ax },
1254 .{ .imm = Instruction.Immediate.u(0x10) },1255 .{ .imm = .u(0x10) },
1255 });1256 });
1256 try expectEqualHexStrings("\x66\x1D\x10\x00", enc.code(), "sbb ax, 0x10");1257 try expectEqualHexStrings("\x66\x1D\x10\x00", enc.code(), "sbb ax, 0x10");
12571258
1258 try enc.encode(.xor, &.{1259 try enc.encode(.xor, &.{
1259 .{ .reg = .al },1260 .{ .reg = .al },
1260 .{ .imm = Instruction.Immediate.u(0x10) },1261 .{ .imm = .u(0x10) },
1261 });1262 });
1262 try expectEqualHexStrings("\x34\x10", enc.code(), "xor al, 0x10");1263 try expectEqualHexStrings("\x34\x10", enc.code(), "xor al, 0x10");
1263}1264}
...@@ -1267,43 +1268,43 @@ test "lower MI encoding" {...@@ -1267,43 +1268,43 @@ test "lower MI encoding" {
12671268
1268 try enc.encode(.mov, &.{1269 try enc.encode(.mov, &.{
1269 .{ .reg = .r12 },1270 .{ .reg = .r12 },
1270 .{ .imm = Instruction.Immediate.u(0x1000) },1271 .{ .imm = .u(0x1000) },
1271 });1272 });
1272 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");1273 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
12731274
1274 try enc.encode(.mov, &.{1275 try enc.encode(.mov, &.{
1275 .{ .mem = Instruction.Memory.initSib(.byte, .{ .base = .{ .reg = .r12 } }) },1276 .{ .mem = Instruction.Memory.initSib(.byte, .{ .base = .{ .reg = .r12 } }) },
1276 .{ .imm = Instruction.Immediate.u(0x10) },1277 .{ .imm = .u(0x10) },
1277 });1278 });
1278 try expectEqualHexStrings("\x41\xC6\x04\x24\x10", enc.code(), "mov BYTE PTR [r12], 0x10");1279 try expectEqualHexStrings("\x41\xC6\x04\x24\x10", enc.code(), "mov BYTE PTR [r12], 0x10");
12791280
1280 try enc.encode(.mov, &.{1281 try enc.encode(.mov, &.{
1281 .{ .reg = .r12 },1282 .{ .reg = .r12 },
1282 .{ .imm = Instruction.Immediate.u(0x1000) },1283 .{ .imm = .u(0x1000) },
1283 });1284 });
1284 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");1285 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
12851286
1286 try enc.encode(.mov, &.{1287 try enc.encode(.mov, &.{
1287 .{ .reg = .r12 },1288 .{ .reg = .r12 },
1288 .{ .imm = Instruction.Immediate.u(0x1000) },1289 .{ .imm = .u(0x1000) },
1289 });1290 });
1290 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");1291 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
12911292
1292 try enc.encode(.mov, &.{1293 try enc.encode(.mov, &.{
1293 .{ .reg = .rax },1294 .{ .reg = .rax },
1294 .{ .imm = Instruction.Immediate.u(0x10) },1295 .{ .imm = .u(0x10) },
1295 });1296 });
1296 try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", enc.code(), "mov rax, 0x10");1297 try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", enc.code(), "mov rax, 0x10");
12971298
1298 try enc.encode(.mov, &.{1299 try enc.encode(.mov, &.{
1299 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .r11 } }) },1300 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .r11 } }) },
1300 .{ .imm = Instruction.Immediate.u(0x10) },1301 .{ .imm = .u(0x10) },
1301 });1302 });
1302 try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", enc.code(), "mov DWORD PTR [r11], 0x10");1303 try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", enc.code(), "mov DWORD PTR [r11], 0x10");
13031304
1304 try enc.encode(.mov, &.{1305 try enc.encode(.mov, &.{
1305 .{ .mem = Instruction.Memory.initRip(.qword, 0x10) },1306 .{ .mem = Instruction.Memory.initRip(.qword, 0x10) },
1306 .{ .imm = Instruction.Immediate.u(0x10) },1307 .{ .imm = .u(0x10) },
1307 });1308 });
1308 try expectEqualHexStrings(1309 try expectEqualHexStrings(
1309 "\x48\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00",1310 "\x48\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00",
...@@ -1313,19 +1314,19 @@ test "lower MI encoding" {...@@ -1313,19 +1314,19 @@ test "lower MI encoding" {
13131314
1314 try enc.encode(.mov, &.{1315 try enc.encode(.mov, &.{
1315 .{ .mem = Instruction.Memory.initSib(.qword, .{ .base = .{ .reg = .rbp }, .disp = -8 }) },1316 .{ .mem = Instruction.Memory.initSib(.qword, .{ .base = .{ .reg = .rbp }, .disp = -8 }) },
1316 .{ .imm = Instruction.Immediate.u(0x10) },1317 .{ .imm = .u(0x10) },
1317 });1318 });
1318 try expectEqualHexStrings("\x48\xc7\x45\xf8\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rbp - 8], 0x10");1319 try expectEqualHexStrings("\x48\xc7\x45\xf8\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rbp - 8], 0x10");
13191320
1320 try enc.encode(.mov, &.{1321 try enc.encode(.mov, &.{
1321 .{ .mem = Instruction.Memory.initSib(.word, .{ .base = .{ .reg = .rbp }, .disp = -2 }) },1322 .{ .mem = Instruction.Memory.initSib(.word, .{ .base = .{ .reg = .rbp }, .disp = -2 }) },
1322 .{ .imm = Instruction.Immediate.s(-16) },1323 .{ .imm = .s(-16) },
1323 });1324 });
1324 try expectEqualHexStrings("\x66\xC7\x45\xFE\xF0\xFF", enc.code(), "mov WORD PTR [rbp - 2], -16");1325 try expectEqualHexStrings("\x66\xC7\x45\xFE\xF0\xFF", enc.code(), "mov WORD PTR [rbp - 2], -16");
13251326
1326 try enc.encode(.mov, &.{1327 try enc.encode(.mov, &.{
1327 .{ .mem = Instruction.Memory.initSib(.byte, .{ .base = .{ .reg = .rbp }, .disp = -1 }) },1328 .{ .mem = Instruction.Memory.initSib(.byte, .{ .base = .{ .reg = .rbp }, .disp = -1 }) },
1328 .{ .imm = Instruction.Immediate.u(0x10) },1329 .{ .imm = .u(0x10) },
1329 });1330 });
1330 try expectEqualHexStrings("\xC6\x45\xFF\x10", enc.code(), "mov BYTE PTR [rbp - 1], 0x10");1331 try expectEqualHexStrings("\xC6\x45\xFF\x10", enc.code(), "mov BYTE PTR [rbp - 1], 0x10");
13311332
...@@ -1335,7 +1336,7 @@ test "lower MI encoding" {...@@ -1335,7 +1336,7 @@ test "lower MI encoding" {
1335 .disp = 0x10000000,1336 .disp = 0x10000000,
1336 .scale_index = .{ .scale = 2, .index = .rcx },1337 .scale_index = .{ .scale = 2, .index = .rcx },
1337 }) },1338 }) },
1338 .{ .imm = Instruction.Immediate.u(0x10) },1339 .{ .imm = .u(0x10) },
1339 });1340 });
1340 try expectEqualHexStrings(1341 try expectEqualHexStrings(
1341 "\x48\xC7\x04\x4D\x00\x00\x00\x10\x10\x00\x00\x00",1342 "\x48\xC7\x04\x4D\x00\x00\x00\x10\x10\x00\x00\x00",
...@@ -1345,43 +1346,43 @@ test "lower MI encoding" {...@@ -1345,43 +1346,43 @@ test "lower MI encoding" {
13451346
1346 try enc.encode(.adc, &.{1347 try enc.encode(.adc, &.{
1347 .{ .mem = Instruction.Memory.initSib(.byte, .{ .base = .{ .reg = .rbp }, .disp = -0x10 }) },1348 .{ .mem = Instruction.Memory.initSib(.byte, .{ .base = .{ .reg = .rbp }, .disp = -0x10 }) },
1348 .{ .imm = Instruction.Immediate.u(0x10) },1349 .{ .imm = .u(0x10) },
1349 });1350 });
1350 try expectEqualHexStrings("\x80\x55\xF0\x10", enc.code(), "adc BYTE PTR [rbp - 0x10], 0x10");1351 try expectEqualHexStrings("\x80\x55\xF0\x10", enc.code(), "adc BYTE PTR [rbp - 0x10], 0x10");
13511352
1352 try enc.encode(.adc, &.{1353 try enc.encode(.adc, &.{
1353 .{ .mem = Instruction.Memory.initRip(.qword, 0) },1354 .{ .mem = Instruction.Memory.initRip(.qword, 0) },
1354 .{ .imm = Instruction.Immediate.u(0x10) },1355 .{ .imm = .u(0x10) },
1355 });1356 });
1356 try expectEqualHexStrings("\x48\x83\x15\x00\x00\x00\x00\x10", enc.code(), "adc QWORD PTR [rip], 0x10");1357 try expectEqualHexStrings("\x48\x83\x15\x00\x00\x00\x00\x10", enc.code(), "adc QWORD PTR [rip], 0x10");
13571358
1358 try enc.encode(.adc, &.{1359 try enc.encode(.adc, &.{
1359 .{ .reg = .rax },1360 .{ .reg = .rax },
1360 .{ .imm = Instruction.Immediate.u(0x10) },1361 .{ .imm = .u(0x10) },
1361 });1362 });
1362 try expectEqualHexStrings("\x48\x83\xD0\x10", enc.code(), "adc rax, 0x10");1363 try expectEqualHexStrings("\x48\x83\xD0\x10", enc.code(), "adc rax, 0x10");
13631364
1364 try enc.encode(.add, &.{1365 try enc.encode(.add, &.{
1365 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .rdx }, .disp = -8 }) },1366 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .rdx }, .disp = -8 }) },
1366 .{ .imm = Instruction.Immediate.u(0x10) },1367 .{ .imm = .u(0x10) },
1367 });1368 });
1368 try expectEqualHexStrings("\x83\x42\xF8\x10", enc.code(), "add DWORD PTR [rdx - 8], 0x10");1369 try expectEqualHexStrings("\x83\x42\xF8\x10", enc.code(), "add DWORD PTR [rdx - 8], 0x10");
13691370
1370 try enc.encode(.add, &.{1371 try enc.encode(.add, &.{
1371 .{ .reg = .rax },1372 .{ .reg = .rax },
1372 .{ .imm = Instruction.Immediate.u(0x10) },1373 .{ .imm = .u(0x10) },
1373 });1374 });
1374 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");1375 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
13751376
1376 try enc.encode(.add, &.{1377 try enc.encode(.add, &.{
1377 .{ .mem = Instruction.Memory.initSib(.qword, .{ .base = .{ .reg = .rbp }, .disp = -0x10 }) },1378 .{ .mem = Instruction.Memory.initSib(.qword, .{ .base = .{ .reg = .rbp }, .disp = -0x10 }) },
1378 .{ .imm = Instruction.Immediate.s(-0x10) },1379 .{ .imm = .s(-0x10) },
1379 });1380 });
1380 try expectEqualHexStrings("\x48\x83\x45\xF0\xF0", enc.code(), "add QWORD PTR [rbp - 0x10], -0x10");1381 try expectEqualHexStrings("\x48\x83\x45\xF0\xF0", enc.code(), "add QWORD PTR [rbp - 0x10], -0x10");
13811382
1382 try enc.encode(.@"and", &.{1383 try enc.encode(.@"and", &.{
1383 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .ds }, .disp = 0x10000000 }) },1384 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .ds }, .disp = 0x10000000 }) },
1384 .{ .imm = Instruction.Immediate.u(0x10) },1385 .{ .imm = .u(0x10) },
1385 });1386 });
1386 try expectEqualHexStrings(1387 try expectEqualHexStrings(
1387 "\x83\x24\x25\x00\x00\x00\x10\x10",1388 "\x83\x24\x25\x00\x00\x00\x10\x10",
...@@ -1391,7 +1392,7 @@ test "lower MI encoding" {...@@ -1391,7 +1392,7 @@ test "lower MI encoding" {
13911392
1392 try enc.encode(.@"and", &.{1393 try enc.encode(.@"and", &.{
1393 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .es }, .disp = 0x10000000 }) },1394 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .es }, .disp = 0x10000000 }) },
1394 .{ .imm = Instruction.Immediate.u(0x10) },1395 .{ .imm = .u(0x10) },
1395 });1396 });
1396 try expectEqualHexStrings(1397 try expectEqualHexStrings(
1397 "\x26\x83\x24\x25\x00\x00\x00\x10\x10",1398 "\x26\x83\x24\x25\x00\x00\x00\x10\x10",
...@@ -1401,7 +1402,7 @@ test "lower MI encoding" {...@@ -1401,7 +1402,7 @@ test "lower MI encoding" {
14011402
1402 try enc.encode(.@"and", &.{1403 try enc.encode(.@"and", &.{
1403 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .r12 }, .disp = 0x10000000 }) },1404 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .r12 }, .disp = 0x10000000 }) },
1404 .{ .imm = Instruction.Immediate.u(0x10) },1405 .{ .imm = .u(0x10) },
1405 });1406 });
1406 try expectEqualHexStrings(1407 try expectEqualHexStrings(
1407 "\x41\x83\xA4\x24\x00\x00\x00\x10\x10",1408 "\x41\x83\xA4\x24\x00\x00\x00\x10\x10",
...@@ -1411,7 +1412,7 @@ test "lower MI encoding" {...@@ -1411,7 +1412,7 @@ test "lower MI encoding" {
14111412
1412 try enc.encode(.sub, &.{1413 try enc.encode(.sub, &.{
1413 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .r11 }, .disp = 0x10000000 }) },1414 .{ .mem = Instruction.Memory.initSib(.dword, .{ .base = .{ .reg = .r11 }, .disp = 0x10000000 }) },
1414 .{ .imm = Instruction.Immediate.u(0x10) },1415 .{ .imm = .u(0x10) },
1415 });1416 });
1416 try expectEqualHexStrings(1417 try expectEqualHexStrings(
1417 "\x41\x83\xAB\x00\x00\x00\x10\x10",1418 "\x41\x83\xAB\x00\x00\x00\x10\x10",
...@@ -1630,14 +1631,14 @@ test "lower RMI encoding" {...@@ -1630,14 +1631,14 @@ test "lower RMI encoding" {
1630 try enc.encode(.imul, &.{1631 try enc.encode(.imul, &.{
1631 .{ .reg = .r11 },1632 .{ .reg = .r11 },
1632 .{ .reg = .r12 },1633 .{ .reg = .r12 },
1633 .{ .imm = Instruction.Immediate.s(-2) },1634 .{ .imm = .s(-2) },
1634 });1635 });
1635 try expectEqualHexStrings("\x4D\x6B\xDC\xFE", enc.code(), "imul r11, r12, -2");1636 try expectEqualHexStrings("\x4D\x6B\xDC\xFE", enc.code(), "imul r11, r12, -2");
16361637
1637 try enc.encode(.imul, &.{1638 try enc.encode(.imul, &.{
1638 .{ .reg = .r11 },1639 .{ .reg = .r11 },
1639 .{ .mem = Instruction.Memory.initRip(.qword, -16) },1640 .{ .mem = Instruction.Memory.initRip(.qword, -16) },
1640 .{ .imm = Instruction.Immediate.s(-1024) },1641 .{ .imm = .s(-1024) },
1641 });1642 });
1642 try expectEqualHexStrings(1643 try expectEqualHexStrings(
1643 "\x4C\x69\x1D\xF0\xFF\xFF\xFF\x00\xFC\xFF\xFF",1644 "\x4C\x69\x1D\xF0\xFF\xFF\xFF\x00\xFC\xFF\xFF",
...@@ -1648,7 +1649,7 @@ test "lower RMI encoding" {...@@ -1648,7 +1649,7 @@ test "lower RMI encoding" {
1648 try enc.encode(.imul, &.{1649 try enc.encode(.imul, &.{
1649 .{ .reg = .bx },1650 .{ .reg = .bx },
1650 .{ .mem = Instruction.Memory.initSib(.word, .{ .base = .{ .reg = .rbp }, .disp = -16 }) },1651 .{ .mem = Instruction.Memory.initSib(.word, .{ .base = .{ .reg = .rbp }, .disp = -16 }) },
1651 .{ .imm = Instruction.Immediate.s(-1024) },1652 .{ .imm = .s(-1024) },
1652 });1653 });
1653 try expectEqualHexStrings(1654 try expectEqualHexStrings(
1654 "\x66\x69\x5D\xF0\x00\xFC",1655 "\x66\x69\x5D\xF0\x00\xFC",
...@@ -1659,7 +1660,7 @@ test "lower RMI encoding" {...@@ -1659,7 +1660,7 @@ test "lower RMI encoding" {
1659 try enc.encode(.imul, &.{1660 try enc.encode(.imul, &.{
1660 .{ .reg = .bx },1661 .{ .reg = .bx },
1661 .{ .mem = Instruction.Memory.initSib(.word, .{ .base = .{ .reg = .rbp }, .disp = -16 }) },1662 .{ .mem = Instruction.Memory.initSib(.word, .{ .base = .{ .reg = .rbp }, .disp = -16 }) },
1662 .{ .imm = Instruction.Immediate.u(1024) },1663 .{ .imm = .u(1024) },
1663 });1664 });
1664 try expectEqualHexStrings(1665 try expectEqualHexStrings(
1665 "\x66\x69\x5D\xF0\x00\x04",1666 "\x66\x69\x5D\xF0\x00\x04",
...@@ -1775,7 +1776,7 @@ test "lower M encoding" {...@@ -1775,7 +1776,7 @@ test "lower M encoding" {
1775 try expectEqualHexStrings("\x65\xFF\x14\x25\x00\x00\x00\x00", enc.code(), "call gs:0x0");1776 try expectEqualHexStrings("\x65\xFF\x14\x25\x00\x00\x00\x00", enc.code(), "call gs:0x0");
17761777
1777 try enc.encode(.call, &.{1778 try enc.encode(.call, &.{
1778 .{ .imm = Instruction.Immediate.s(0) },1779 .{ .imm = .s(0) },
1779 });1780 });
1780 try expectEqualHexStrings("\xE8\x00\x00\x00\x00", enc.code(), "call 0x0");1781 try expectEqualHexStrings("\xE8\x00\x00\x00\x00", enc.code(), "call 0x0");
17811782
...@@ -1834,7 +1835,7 @@ test "lower OI encoding" {...@@ -1834,7 +1835,7 @@ test "lower OI encoding" {
18341835
1835 try enc.encode(.mov, &.{1836 try enc.encode(.mov, &.{
1836 .{ .reg = .rax },1837 .{ .reg = .rax },
1837 .{ .imm = Instruction.Immediate.u(0x1000000000000000) },1838 .{ .imm = .u(0x1000000000000000) },
1838 });1839 });
1839 try expectEqualHexStrings(1840 try expectEqualHexStrings(
1840 "\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x10",1841 "\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x10",
...@@ -1844,7 +1845,7 @@ test "lower OI encoding" {...@@ -1844,7 +1845,7 @@ test "lower OI encoding" {
18441845
1845 try enc.encode(.mov, &.{1846 try enc.encode(.mov, &.{
1846 .{ .reg = .r11 },1847 .{ .reg = .r11 },
1847 .{ .imm = Instruction.Immediate.u(0x1000000000000000) },1848 .{ .imm = .u(0x1000000000000000) },
1848 });1849 });
1849 try expectEqualHexStrings(1850 try expectEqualHexStrings(
1850 "\x49\xBB\x00\x00\x00\x00\x00\x00\x00\x10",1851 "\x49\xBB\x00\x00\x00\x00\x00\x00\x00\x10",
...@@ -1854,19 +1855,19 @@ test "lower OI encoding" {...@@ -1854,19 +1855,19 @@ test "lower OI encoding" {
18541855
1855 try enc.encode(.mov, &.{1856 try enc.encode(.mov, &.{
1856 .{ .reg = .r11d },1857 .{ .reg = .r11d },
1857 .{ .imm = Instruction.Immediate.u(0x10000000) },1858 .{ .imm = .u(0x10000000) },
1858 });1859 });
1859 try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", enc.code(), "mov r11d, 0x10000000");1860 try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", enc.code(), "mov r11d, 0x10000000");
18601861
1861 try enc.encode(.mov, &.{1862 try enc.encode(.mov, &.{
1862 .{ .reg = .r11w },1863 .{ .reg = .r11w },
1863 .{ .imm = Instruction.Immediate.u(0x1000) },1864 .{ .imm = .u(0x1000) },
1864 });1865 });
1865 try expectEqualHexStrings("\x66\x41\xBB\x00\x10", enc.code(), "mov r11w, 0x1000");1866 try expectEqualHexStrings("\x66\x41\xBB\x00\x10", enc.code(), "mov r11w, 0x1000");
18661867
1867 try enc.encode(.mov, &.{1868 try enc.encode(.mov, &.{
1868 .{ .reg = .r11b },1869 .{ .reg = .r11b },
1869 .{ .imm = Instruction.Immediate.u(0x10) },1870 .{ .imm = .u(0x10) },
1870 });1871 });
1871 try expectEqualHexStrings("\x41\xB3\x10", enc.code(), "mov r11b, 0x10");1872 try expectEqualHexStrings("\x41\xB3\x10", enc.code(), "mov r11b, 0x10");
1872}1873}
...@@ -1940,7 +1941,7 @@ test "lower NP encoding" {...@@ -1940,7 +1941,7 @@ test "lower NP encoding" {
1940}1941}
19411942
1942fn invalidInstruction(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void {1943fn invalidInstruction(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void {
1943 const err = Instruction.new(.none, mnemonic, ops);1944 const err: Instruction = .new(.none, mnemonic, ops);
1944 try testing.expectError(error.InvalidInstruction, err);1945 try testing.expectError(error.InvalidInstruction, err);
1945}1946}
19461947
...@@ -1988,12 +1989,12 @@ test "invalid instruction" {...@@ -1988,12 +1989,12 @@ test "invalid instruction" {
1988 .{ .reg = .r12d },1989 .{ .reg = .r12d },
1989 });1990 });
1990 try invalidInstruction(.push, &.{1991 try invalidInstruction(.push, &.{
1991 .{ .imm = Instruction.Immediate.u(0x1000000000000000) },1992 .{ .imm = .u(0x1000000000000000) },
1992 });1993 });
1993}1994}
19941995
1995fn cannotEncode(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void {1996fn cannotEncode(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void {
1996 try testing.expectError(error.CannotEncode, Instruction.new(.none, mnemonic, ops));1997 try testing.expectError(error.CannotEncode, .new(.none, mnemonic, ops));
1997}1998}
19981999
1999test "cannot encode" {2000test "cannot encode" {
...@@ -2177,7 +2178,7 @@ const Assembler = struct {...@@ -2177,7 +2178,7 @@ const Assembler = struct {
21772178
2178 pub fn assemble(as: *Assembler, writer: anytype) !void {2179 pub fn assemble(as: *Assembler, writer: anytype) !void {
2179 while (try as.next()) |parsed_inst| {2180 while (try as.next()) |parsed_inst| {
2180 const inst = try Instruction.new(.none, parsed_inst.mnemonic, &parsed_inst.ops);2181 const inst: Instruction = try .new(.none, parsed_inst.mnemonic, &parsed_inst.ops);
2181 try inst.encode(writer, .{});2182 try inst.encode(writer, .{});
2182 }2183 }
2183 }2184 }
src/link/MachO.zig+1-1
...@@ -3548,7 +3548,7 @@ pub fn getTarget(self: MachO) std.Target {...@@ -3548,7 +3548,7 @@ pub fn getTarget(self: MachO) std.Target {
3548pub fn invalidateKernelCache(dir: fs.Dir, sub_path: []const u8) !void {3548pub fn invalidateKernelCache(dir: fs.Dir, sub_path: []const u8) !void {
3549 const tracy = trace(@src());3549 const tracy = trace(@src());
3550 defer tracy.end();3550 defer tracy.end();
3551 if (comptime builtin.target.isDarwin() and builtin.target.cpu.arch == .aarch64) {3551 if (builtin.target.isDarwin() and builtin.target.cpu.arch == .aarch64) {
3552 try dir.copyFile(sub_path, dir, sub_path, .{});3552 try dir.copyFile(sub_path, dir, sub_path, .{});
3553 }3553 }
3554}3554}
test/behavior/align.zig+10-10
...@@ -277,8 +277,8 @@ test "function alignment" {...@@ -277,8 +277,8 @@ test "function alignment" {
277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
279279
280 // function alignment is a compile error on wasm32/wasm64280 // function alignment is a compile error on wasm
281 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;281 if (native_arch.isWasm()) return error.SkipZigTest;
282282
283 const S = struct {283 const S = struct {
284 fn alignExpr() align(@sizeOf(usize) * 2) i32 {284 fn alignExpr() align(@sizeOf(usize) * 2) i32 {
...@@ -307,8 +307,8 @@ test "implicitly decreasing fn alignment" {...@@ -307,8 +307,8 @@ test "implicitly decreasing fn alignment" {
307 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO307 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
308 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;308 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
309309
310 // function alignment is a compile error on wasm32/wasm64310 // function alignment is a compile error on wasm
311 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;311 if (native_arch.isWasm()) return error.SkipZigTest;
312312
313 try testImplicitlyDecreaseFnAlign(alignedSmall, 1234);313 try testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
314 try testImplicitlyDecreaseFnAlign(alignedBig, 5678);314 try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
...@@ -331,9 +331,9 @@ test "@alignCast functions" {...@@ -331,9 +331,9 @@ test "@alignCast functions" {
331 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO331 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
332 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;332 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
333333
334 // function alignment is a compile error on wasm32/wasm64334 // function alignment is a compile error on wasm
335 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;335 if (native_arch.isWasm()) return error.SkipZigTest;
336 if (native_arch == .thumb or native_arch == .thumbeb) return error.SkipZigTest;336 if (native_arch.isThumb()) return error.SkipZigTest;
337337
338 try expect(fnExpectsOnly1(simple4) == 0x19);338 try expect(fnExpectsOnly1(simple4) == 0x19);
339}339}
...@@ -496,9 +496,9 @@ test "align(N) on functions" {...@@ -496,9 +496,9 @@ test "align(N) on functions" {
496 return error.SkipZigTest;496 return error.SkipZigTest;
497 }497 }
498498
499 // function alignment is a compile error on wasm32/wasm64499 // function alignment is a compile error on wasm
500 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;500 if (native_arch.isWasm()) return error.SkipZigTest;
501 if (native_arch == .thumb or native_arch == .thumbeb) return error.SkipZigTest;501 if (native_arch.isThumb()) return error.SkipZigTest;
502502
503 try expect((@intFromPtr(&overaligned_fn) & (0x1000 - 1)) == 0);503 try expect((@intFromPtr(&overaligned_fn) & (0x1000 - 1)) == 0);
504}504}
test/behavior/asm.zig+1-1
...@@ -178,7 +178,7 @@ test "rw constraint (x86_64)" {...@@ -178,7 +178,7 @@ test "rw constraint (x86_64)" {
178}178}
179179
180test "asm modifiers (AArch64)" {180test "asm modifiers (AArch64)" {
181 if (builtin.target.cpu.arch != .aarch64) return error.SkipZigTest;181 if (!builtin.target.cpu.arch.isAARCH64()) return error.SkipZigTest;
182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
183183
184 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly184 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
test/behavior/call.zig+1
...@@ -660,6 +660,7 @@ test "arguments pointed to on stack into tailcall" {...@@ -660,6 +660,7 @@ test "arguments pointed to on stack into tailcall" {
660660
661 switch (builtin.cpu.arch) {661 switch (builtin.cpu.arch) {
662 .wasm32,662 .wasm32,
663 .wasm64,
663 .mips,664 .mips,
664 .mipsel,665 .mipsel,
665 .mips64,666 .mips64,
test/behavior/cast.zig+2-2
...@@ -124,7 +124,7 @@ test "@floatFromInt(f80)" {...@@ -124,7 +124,7 @@ test "@floatFromInt(f80)" {
124 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO124 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;126 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
127 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;127 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
128 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;128 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
129 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;129 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
130130
...@@ -1362,7 +1362,7 @@ test "cast f16 to wider types" {...@@ -1362,7 +1362,7 @@ test "cast f16 to wider types" {
1362 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1362 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1364 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1364 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1365 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;1365 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1366 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;1366 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1367 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1367 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13681368
test/behavior/eval.zig+1-1
...@@ -522,7 +522,7 @@ test "runtime 128 bit integer division" {...@@ -522,7 +522,7 @@ test "runtime 128 bit integer division" {
522 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO522 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
523 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO523 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
524 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;524 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
525 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;525 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
526 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;526 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
527 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;527 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
528528
test/behavior/math.zig+4-4
...@@ -785,7 +785,7 @@ test "128-bit multiplication" {...@@ -785,7 +785,7 @@ test "128-bit multiplication" {
785 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO785 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
786 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;786 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
787 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;787 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
788 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;788 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
789 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;789 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
790790
791 {791 {
...@@ -1374,7 +1374,7 @@ test "remainder division" {...@@ -1374,7 +1374,7 @@ test "remainder division" {
1374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1375 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1375 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1376 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;1376 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1377 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;1377 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1378 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1378 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13791379
1380 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {1380 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
...@@ -1527,7 +1527,7 @@ test "@round f80" {...@@ -1527,7 +1527,7 @@ test "@round f80" {
1527 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1527 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1528 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1528 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1529 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1529 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1530 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;1530 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1531 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;1531 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1532 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1532 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15331533
...@@ -1540,7 +1540,7 @@ test "@round f128" {...@@ -1540,7 +1540,7 @@ test "@round f128" {
1540 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1540 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1541 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1541 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1542 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1542 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1543 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;1543 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1544 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;1544 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1545 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1545 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15461546
test/behavior/maximum_minimum.zig+1-1
...@@ -122,7 +122,7 @@ test "@min/max for floats" {...@@ -122,7 +122,7 @@ test "@min/max for floats" {
122 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO122 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
123 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO123 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
124 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;124 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
125 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;125 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
126 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;126 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
127 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;127 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
128128
test/behavior/muladd.zig+4-4
...@@ -58,7 +58,7 @@ test "@mulAdd f80" {...@@ -58,7 +58,7 @@ test "@mulAdd f80" {
58 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO58 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
59 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO59 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
60 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;60 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
61 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;61 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
62 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;62 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
63 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;63 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
6464
...@@ -79,7 +79,7 @@ test "@mulAdd f128" {...@@ -79,7 +79,7 @@ test "@mulAdd f128" {
79 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO79 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
80 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO80 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
81 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;81 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
82 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;82 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;83 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;84 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8585
...@@ -189,7 +189,7 @@ test "vector f80" {...@@ -189,7 +189,7 @@ test "vector f80" {
189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
190 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO190 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
191 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;191 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
192 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;192 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
193 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;193 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
194194
195 try comptime vector80();195 try comptime vector80();
...@@ -216,7 +216,7 @@ test "vector f128" {...@@ -216,7 +216,7 @@ test "vector f128" {
216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
218 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;218 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
219 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;219 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
220 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;220 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
221221
222 try comptime vector128();222 try comptime vector128();
test/behavior/saturating_arithmetic.zig+5-5
...@@ -164,10 +164,10 @@ test "saturating multiplication <= 32 bits" {...@@ -164,10 +164,10 @@ test "saturating multiplication <= 32 bits" {
164 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO164 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;166 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
167 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;167 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
168 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;168 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
169169
170 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .wasm32) {170 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isWasm()) {
171 // https://github.com/ziglang/zig/issues/9660171 // https://github.com/ziglang/zig/issues/9660
172 return error.SkipZigTest;172 return error.SkipZigTest;
173 }173 }
...@@ -264,10 +264,10 @@ test "saturating multiplication" {...@@ -264,10 +264,10 @@ test "saturating multiplication" {
264 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO264 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
265 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO265 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
266 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;266 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
267 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;267 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
268 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;268 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
269269
270 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .wasm32) {270 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isWasm()) {
271 // https://github.com/ziglang/zig/issues/9660271 // https://github.com/ziglang/zig/issues/9660
272 return error.SkipZigTest;272 return error.SkipZigTest;
273 }273 }
...@@ -311,7 +311,7 @@ test "saturating shift-left" {...@@ -311,7 +311,7 @@ test "saturating shift-left" {
311 try testSatShl(i8, 127, 1, 127);311 try testSatShl(i8, 127, 1, 127);
312 try testSatShl(i8, -128, 1, -128);312 try testSatShl(i8, -128, 1, -128);
313 // TODO: remove this check once #9668 is completed313 // TODO: remove this check once #9668 is completed
314 if (builtin.cpu.arch != .wasm32) {314 if (!builtin.cpu.arch.isWasm()) {
315 // skip testing ints > 64 bits on wasm due to miscompilation / wasmtime ci error315 // skip testing ints > 64 bits on wasm due to miscompilation / wasmtime ci error
316 try testSatShl(i128, maxInt(i128), 64, maxInt(i128));316 try testSatShl(i128, maxInt(i128), 64, maxInt(i128));
317 try testSatShl(u128, maxInt(u128), 64, maxInt(u128));317 try testSatShl(u128, maxInt(u128), 64, maxInt(u128));
test/behavior/struct.zig+4-4
...@@ -418,8 +418,8 @@ test "packed struct 24bits" {...@@ -418,8 +418,8 @@ test "packed struct 24bits" {
418 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;418 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
419 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO419 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
421 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO421 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; // TODO
422 if (comptime builtin.cpu.arch.isArm()) return error.SkipZigTest; // TODO422 if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // TODO
423 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO423 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
424 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;424 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
425425
...@@ -818,7 +818,7 @@ test "non-packed struct with u128 entry in union" {...@@ -818,7 +818,7 @@ test "non-packed struct with u128 entry in union" {
818 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO818 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
819 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO819 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
820 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;820 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
821 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;821 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
822 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;822 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
823823
824 const U = union(enum) {824 const U = union(enum) {
...@@ -941,7 +941,7 @@ test "tuple assigned to variable" {...@@ -941,7 +941,7 @@ test "tuple assigned to variable" {
941941
942test "comptime struct field" {942test "comptime struct field" {
943 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO943 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
944 if (comptime builtin.cpu.arch.isArm()) return error.SkipZigTest; // TODO944 if (builtin.cpu.arch.isArm()) return error.SkipZigTest; // TODO
945945
946 const T = struct {946 const T = struct {
947 a: i32,947 a: i32,
test/behavior/var_args.zig+5-5
...@@ -100,7 +100,7 @@ test "simple variadic function" {...@@ -100,7 +100,7 @@ test "simple variadic function" {
100 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO100 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
101 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;101 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
102 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;102 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
103 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {103 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
104 // https://github.com/ziglang/zig/issues/14096104 // https://github.com/ziglang/zig/issues/14096
105 return error.SkipZigTest;105 return error.SkipZigTest;
106 }106 }
...@@ -161,7 +161,7 @@ test "coerce reference to var arg" {...@@ -161,7 +161,7 @@ test "coerce reference to var arg" {
161 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO161 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;162 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
163 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;163 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
164 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {164 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
165 // https://github.com/ziglang/zig/issues/14096165 // https://github.com/ziglang/zig/issues/14096
166 return error.SkipZigTest;166 return error.SkipZigTest;
167 }167 }
...@@ -194,7 +194,7 @@ test "variadic functions" {...@@ -194,7 +194,7 @@ test "variadic functions" {
194 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO194 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
195 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;195 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
196 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;196 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
197 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {197 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
198 // https://github.com/ziglang/zig/issues/14096198 // https://github.com/ziglang/zig/issues/14096
199 return error.SkipZigTest;199 return error.SkipZigTest;
200 }200 }
...@@ -239,7 +239,7 @@ test "copy VaList" {...@@ -239,7 +239,7 @@ test "copy VaList" {
239 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO239 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
240 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;240 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
241 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;241 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
242 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {242 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
243 // https://github.com/ziglang/zig/issues/14096243 // https://github.com/ziglang/zig/issues/14096
244 return error.SkipZigTest;244 return error.SkipZigTest;
245 }245 }
...@@ -273,7 +273,7 @@ test "unused VaList arg" {...@@ -273,7 +273,7 @@ test "unused VaList arg" {
273 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO273 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
274 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;274 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
275 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;275 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
276 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {276 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
277 // https://github.com/ziglang/zig/issues/14096277 // https://github.com/ziglang/zig/issues/14096
278 return error.SkipZigTest;278 return error.SkipZigTest;
279 }279 }
test/behavior/vector.zig+4-4
...@@ -101,7 +101,7 @@ test "vector float operators" {...@@ -101,7 +101,7 @@ test "vector float operators" {
101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;103 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
104 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;104 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
105 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO105 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
106106
107 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {107 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
...@@ -754,7 +754,7 @@ test "vector reduce operation" {...@@ -754,7 +754,7 @@ test "vector reduce operation" {
754 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO754 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
755 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO755 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
756 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;756 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
757 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArm()) return error.SkipZigTest;757 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
758 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;758 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
759 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21091759 if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21091
760760
...@@ -989,7 +989,7 @@ test "saturating multiplication" {...@@ -989,7 +989,7 @@ test "saturating multiplication" {
989 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;989 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
990990
991 // TODO: once #9660 has been solved, remove this line991 // TODO: once #9660 has been solved, remove this line
992 if (builtin.target.cpu.arch == .wasm32) return error.SkipZigTest;992 if (builtin.target.cpu.arch.isWasm()) return error.SkipZigTest;
993993
994 const S = struct {994 const S = struct {
995 fn doTheTest() !void {995 fn doTheTest() !void {
...@@ -1256,7 +1256,7 @@ test "byte vector initialized in inline function" {...@@ -1256,7 +1256,7 @@ test "byte vector initialized in inline function" {
1256 if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;1256 if (builtin.cpu.arch == .aarch64_be and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
12571257
1258 if (comptime builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and1258 if (comptime builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and
1259 builtin.cpu.features.isEnabled(@intFromEnum(std.Target.x86.Feature.avx512f)))1259 std.Target.x86.featureSetHas(builtin.cpu.features, .avx512f))
1260 {1260 {
1261 // TODO https://github.com/ziglang/zig/issues/132791261 // TODO https://github.com/ziglang/zig/issues/13279
1262 return error.SkipZigTest;1262 return error.SkipZigTest;
test/behavior/wrapping_arithmetic.zig+1-1
...@@ -83,7 +83,7 @@ test "wrapping multiplication" {...@@ -83,7 +83,7 @@ test "wrapping multiplication" {
83 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;83 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
8484
85 // TODO: once #9660 has been solved, remove this line85 // TODO: once #9660 has been solved, remove this line
86 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest;86 if (builtin.cpu.arch.isWasm()) return error.SkipZigTest;
8787
88 const S = struct {88 const S = struct {
89 fn doTheTest() !void {89 fn doTheTest() !void {