authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-23 09:13:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-23 09:13:52-07:00
logdfbb6e9879693331c7b8ea57eb7aa8bdf934403f
tree7e924c23a4469c6ff554c3bc40609f8873a95376
parent1d2b870501ab4ef6adb38c817976669c0329329c
parentbc8e1a74c514e487842c03ab32d7f6e49f42c529

Merge remote-tracking branch 'origin/master' into wrangle-writer-buffering


181 files changed, 28727 insertions(+), 4297 deletions(-)

CMakeLists.txt+8-9
...@@ -390,15 +390,6 @@ set(ZIG_STAGE2_SOURCES...@@ -390,15 +390,6 @@ set(ZIG_STAGE2_SOURCES
390 lib/std/Io.zig390 lib/std/Io.zig
391 lib/std/Io/Reader.zig391 lib/std/Io/Reader.zig
392 lib/std/Io/Writer.zig392 lib/std/Io/Writer.zig
393 lib/std/Io/buffered_atomic_file.zig
394 lib/std/Io/buffered_writer.zig
395 lib/std/Io/change_detection_stream.zig
396 lib/std/Io/counting_reader.zig
397 lib/std/Io/counting_writer.zig
398 lib/std/Io/find_byte_writer.zig
399 lib/std/Io/fixed_buffer_stream.zig
400 lib/std/Io/limited_reader.zig
401 lib/std/Io/seekable_stream.zig
402 lib/std/Progress.zig393 lib/std/Progress.zig
403 lib/std/Random.zig394 lib/std/Random.zig
404 lib/std/Target.zig395 lib/std/Target.zig
...@@ -550,6 +541,14 @@ set(ZIG_STAGE2_SOURCES...@@ -550,6 +541,14 @@ set(ZIG_STAGE2_SOURCES
550 src/clang_options.zig541 src/clang_options.zig
551 src/clang_options_data.zig542 src/clang_options_data.zig
552 src/codegen.zig543 src/codegen.zig
544 src/codegen/aarch64.zig
545 src/codegen/aarch64/abi.zig
546 src/codegen/aarch64/Assemble.zig
547 src/codegen/aarch64/Disassemble.zig
548 src/codegen/aarch64/encoding.zig
549 src/codegen/aarch64/instructions.zon
550 src/codegen/aarch64/Mir.zig
551 src/codegen/aarch64/Select.zig
553 src/codegen/c.zig552 src/codegen/c.zig
554 src/codegen/c/Type.zig553 src/codegen/c/Type.zig
555 src/codegen/llvm.zig554 src/codegen/llvm.zig
lib/compiler/std-docs.zig+9-2
...@@ -59,7 +59,9 @@ pub fn main() !void {...@@ -59,7 +59,9 @@ pub fn main() !void {
59 const should_open_browser = force_open_browser orelse (listen_port == 0);59 const should_open_browser = force_open_browser orelse (listen_port == 0);
6060
61 const address = std.net.Address.parseIp("127.0.0.1", listen_port) catch unreachable;61 const address = std.net.Address.parseIp("127.0.0.1", listen_port) catch unreachable;
62 var http_server = try address.listen(.{});62 var http_server = try address.listen(.{
63 .reuse_address = true,
64 });
63 const port = http_server.listen_address.in.getPort();65 const port = http_server.listen_address.in.getPort();
64 const url_with_newline = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/\n", .{port});66 const url_with_newline = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/\n", .{port});
65 std.fs.File.stdout().writeAll(url_with_newline) catch {};67 std.fs.File.stdout().writeAll(url_with_newline) catch {};
...@@ -218,7 +220,12 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void {...@@ -218,7 +220,12 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void {
218 var file = try entry.dir.openFile(entry.basename, .{});220 var file = try entry.dir.openFile(entry.basename, .{});
219 defer file.close();221 defer file.close();
220 const stat = try file.stat();222 const stat = try file.stat();
221 try tar_writer.writeFile(entry.path, file, stat);223 var file_reader: std.fs.File.Reader = .{
224 .file = file,
225 .interface = std.fs.File.Reader.initInterface(&.{}),
226 .size = stat.size,
227 };
228 try tar_writer.writeFile(entry.path, &file_reader, stat.mtime);
222 }229 }
223230
224 {231 {
lib/compiler/test_runner.zig+19-20
...@@ -16,6 +16,7 @@ var stdin_buffer: [4096]u8 = undefined;...@@ -16,6 +16,7 @@ var stdin_buffer: [4096]u8 = undefined;
16var stdout_buffer: [4096]u8 = undefined;16var stdout_buffer: [4096]u8 = undefined;
1717
18const crippled = switch (builtin.zig_backend) {18const crippled = switch (builtin.zig_backend) {
19 .stage2_aarch64,
19 .stage2_powerpc,20 .stage2_powerpc,
20 .stage2_riscv64,21 .stage2_riscv64,
21 => true,22 => true,
...@@ -287,13 +288,14 @@ pub fn log(...@@ -287,13 +288,14 @@ pub fn log(
287/// work-in-progress backends can handle it.288/// work-in-progress backends can handle it.
288pub fn mainSimple() anyerror!void {289pub fn mainSimple() anyerror!void {
289 @disableInstrumentation();290 @disableInstrumentation();
290 // is the backend capable of printing to stderr?291 // is the backend capable of calling `std.fs.File.writeAll`?
291 const enable_print = switch (builtin.zig_backend) {292 const enable_write = switch (builtin.zig_backend) {
293 .stage2_aarch64, .stage2_riscv64 => true,
292 else => false,294 else => false,
293 };295 };
294 // is the backend capable of using std.fmt.format to print a summary at the end?296 // is the backend capable of calling `std.Io.Writer.print`?
295 const print_summary = switch (builtin.zig_backend) {297 const enable_print = switch (builtin.zig_backend) {
296 .stage2_riscv64 => true,298 .stage2_aarch64, .stage2_riscv64 => true,
297 else => false,299 else => false,
298 };300 };
299301
...@@ -302,34 +304,31 @@ pub fn mainSimple() anyerror!void {...@@ -302,34 +304,31 @@ pub fn mainSimple() anyerror!void {
302 var failed: u64 = 0;304 var failed: u64 = 0;
303305
304 // we don't want to bring in File and Writer if the backend doesn't support it306 // we don't want to bring in File and Writer if the backend doesn't support it
305 const stderr = if (comptime enable_print) std.fs.File.stderr() else {};307 const stdout = if (enable_write) std.fs.File.stdout() else {};
306308
307 for (builtin.test_functions) |test_fn| {309 for (builtin.test_functions) |test_fn| {
310 if (enable_write) {
311 stdout.writeAll(test_fn.name) catch {};
312 stdout.writeAll("... ") catch {};
313 }
308 if (test_fn.func()) |_| {314 if (test_fn.func()) |_| {
309 if (enable_print) {315 if (enable_write) stdout.writeAll("PASS\n") catch {};
310 stderr.writeAll(test_fn.name) catch {};
311 stderr.writeAll("... ") catch {};
312 stderr.writeAll("PASS\n") catch {};
313 }
314 } else |err| {316 } else |err| {
315 if (enable_print) {
316 stderr.writeAll(test_fn.name) catch {};
317 stderr.writeAll("... ") catch {};
318 }
319 if (err != error.SkipZigTest) {317 if (err != error.SkipZigTest) {
320 if (enable_print) stderr.writeAll("FAIL\n") catch {};318 if (enable_write) stdout.writeAll("FAIL\n") catch {};
321 failed += 1;319 failed += 1;
322 if (!enable_print) return err;320 if (!enable_write) return err;
323 continue;321 continue;
324 }322 }
325 if (enable_print) stderr.writeAll("SKIP\n") catch {};323 if (enable_write) stdout.writeAll("SKIP\n") catch {};
326 skipped += 1;324 skipped += 1;
327 continue;325 continue;
328 }326 }
329 passed += 1;327 passed += 1;
330 }328 }
331 if (enable_print and print_summary) {329 if (enable_print) {
332 stderr.deprecatedWriter().print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {};330 var stdout_writer = stdout.writer(&.{});
331 stdout_writer.interface.print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {};
333 }332 }
334 if (failed != 0) std.process.exit(1);333 if (failed != 0) std.process.exit(1);
335}334}
lib/compiler_rt.zig+3-3
...@@ -240,7 +240,7 @@ comptime {...@@ -240,7 +240,7 @@ comptime {
240 _ = @import("compiler_rt/udivmodti4.zig");240 _ = @import("compiler_rt/udivmodti4.zig");
241241
242 // extra242 // extra
243 _ = @import("compiler_rt/os_version_check.zig");243 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/os_version_check.zig");
244 _ = @import("compiler_rt/emutls.zig");244 _ = @import("compiler_rt/emutls.zig");
245 _ = @import("compiler_rt/arm.zig");245 _ = @import("compiler_rt/arm.zig");
246 _ = @import("compiler_rt/aulldiv.zig");246 _ = @import("compiler_rt/aulldiv.zig");
...@@ -249,12 +249,12 @@ comptime {...@@ -249,12 +249,12 @@ comptime {
249 _ = @import("compiler_rt/hexagon.zig");249 _ = @import("compiler_rt/hexagon.zig");
250250
251 if (@import("builtin").object_format != .c) {251 if (@import("builtin").object_format != .c) {
252 _ = @import("compiler_rt/atomics.zig");252 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/atomics.zig");
253 _ = @import("compiler_rt/stack_probe.zig");253 _ = @import("compiler_rt/stack_probe.zig");
254254
255 // macOS has these functions inside libSystem.255 // macOS has these functions inside libSystem.
256 if (builtin.cpu.arch.isAARCH64() and !builtin.os.tag.isDarwin()) {256 if (builtin.cpu.arch.isAARCH64() and !builtin.os.tag.isDarwin()) {
257 _ = @import("compiler_rt/aarch64_outline_atomics.zig");257 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/aarch64_outline_atomics.zig");
258 }258 }
259259
260 _ = @import("compiler_rt/memcpy.zig");260 _ = @import("compiler_rt/memcpy.zig");
lib/compiler_rt/addo.zig+1-3
...@@ -1,6 +1,4 @@...@@ -1,6 +1,4 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const common = @import("./common.zig");2const common = @import("./common.zig");
5pub const panic = @import("common.zig").panic;3pub const panic = @import("common.zig").panic;
64
...@@ -16,7 +14,7 @@ comptime {...@@ -16,7 +14,7 @@ comptime {
16// - addoXi4_generic as default14// - addoXi4_generic as default
1715
18inline fn addoXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {16inline fn addoXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
19 @setRuntimeSafety(builtin.is_test);17 @setRuntimeSafety(common.test_safety);
20 overflow.* = 0;18 overflow.* = 0;
21 const sum: ST = a +% b;19 const sum: ST = a +% b;
22 // Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract20 // Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract
lib/compiler_rt/addoti4_test.zig+3
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const addv = @import("addo.zig");1const addv = @import("addo.zig");
2const builtin = @import("builtin");
2const std = @import("std");3const std = @import("std");
3const testing = std.testing;4const testing = std.testing;
4const math = std.math;5const math = std.math;
...@@ -23,6 +24,8 @@ fn simple_addoti4(a: i128, b: i128, overflow: *c_int) i128 {...@@ -23,6 +24,8 @@ fn simple_addoti4(a: i128, b: i128, overflow: *c_int) i128 {
23}24}
2425
25test "addoti4" {26test "addoti4" {
27 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28
26 const min: i128 = math.minInt(i128);29 const min: i128 = math.minInt(i128);
27 const max: i128 = math.maxInt(i128);30 const max: i128 = math.maxInt(i128);
28 var i: i128 = 1;31 var i: i128 = 1;
lib/compiler_rt/clear_cache.zig+4-10
...@@ -97,8 +97,7 @@ fn clear_cache(start: usize, end: usize) callconv(.c) void {...@@ -97,8 +97,7 @@ fn clear_cache(start: usize, end: usize) callconv(.c) void {
97 .nbytes = end - start,97 .nbytes = end - start,
98 .whichcache = 3, // ICACHE | DCACHE98 .whichcache = 3, // ICACHE | DCACHE
99 };99 };
100 asm volatile (100 asm volatile ("syscall"
101 \\ syscall
102 :101 :
103 : [_] "{$2}" (165), // nr = SYS_sysarch102 : [_] "{$2}" (165), // nr = SYS_sysarch
104 [_] "{$4}" (0), // op = MIPS_CACHEFLUSH103 [_] "{$4}" (0), // op = MIPS_CACHEFLUSH
...@@ -116,11 +115,8 @@ fn clear_cache(start: usize, end: usize) callconv(.c) void {...@@ -116,11 +115,8 @@ fn clear_cache(start: usize, end: usize) callconv(.c) void {
116 } else if (arm64 and !apple) {115 } else if (arm64 and !apple) {
117 // Get Cache Type Info.116 // Get Cache Type Info.
118 // TODO memoize this?117 // TODO memoize this?
119 var ctr_el0: u64 = 0;118 const ctr_el0 = asm volatile ("mrs %[ctr_el0], ctr_el0"
120 asm volatile (119 : [ctr_el0] "=r" (-> u64),
121 \\mrs %[x], ctr_el0
122 \\
123 : [x] "=r" (ctr_el0),
124 );120 );
125 // The DC and IC instructions must use 64-bit registers so we don't use121 // The DC and IC instructions must use 64-bit registers so we don't use
126 // uintptr_t in case this runs in an IPL32 environment.122 // uintptr_t in case this runs in an IPL32 environment.
...@@ -187,9 +183,7 @@ fn clear_cache(start: usize, end: usize) callconv(.c) void {...@@ -187,9 +183,7 @@ fn clear_cache(start: usize, end: usize) callconv(.c) void {
187 exportIt();183 exportIt();
188 } else if (os == .linux and loongarch) {184 } else if (os == .linux and loongarch) {
189 // See: https://github.com/llvm/llvm-project/blob/cf54cae26b65fc3201eff7200ffb9b0c9e8f9a13/compiler-rt/lib/builtins/clear_cache.c#L94-L95185 // See: https://github.com/llvm/llvm-project/blob/cf54cae26b65fc3201eff7200ffb9b0c9e8f9a13/compiler-rt/lib/builtins/clear_cache.c#L94-L95
190 asm volatile (186 asm volatile ("ibar 0");
191 \\ ibar 0
192 );
193 exportIt();187 exportIt();
194 }188 }
195189
lib/compiler_rt/cmp.zig-1
...@@ -1,6 +1,5 @@...@@ -1,6 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const common = @import("common.zig");3const common = @import("common.zig");
54
6pub const panic = common.panic;5pub const panic = common.panic;
lib/compiler_rt/common.zig+6-1
...@@ -102,9 +102,14 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) {...@@ -102,9 +102,14 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) {
102102
103pub const want_sparc_abi = builtin.cpu.arch.isSPARC();103pub const want_sparc_abi = builtin.cpu.arch.isSPARC();
104104
105pub const test_safety = switch (builtin.zig_backend) {
106 .stage2_aarch64 => false,
107 else => builtin.is_test,
108};
109
105// Avoid dragging in the runtime safety mechanisms into this .o file, unless110// Avoid dragging in the runtime safety mechanisms into this .o file, unless
106// we're trying to test compiler-rt.111// we're trying to test compiler-rt.
107pub const panic = if (builtin.is_test) std.debug.FullPanic(std.debug.defaultPanic) else std.debug.no_panic;112pub const panic = if (test_safety) std.debug.FullPanic(std.debug.defaultPanic) else std.debug.no_panic;
108113
109/// This seems to mostly correspond to `clang::TargetInfo::HasFloat16`.114/// This seems to mostly correspond to `clang::TargetInfo::HasFloat16`.
110pub fn F16T(comptime OtherType: type) type {115pub fn F16T(comptime OtherType: type) type {
lib/compiler_rt/comparedf2_test.zig-1
...@@ -4,7 +4,6 @@...@@ -4,7 +4,6 @@
44
5const std = @import("std");5const std = @import("std");
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const is_test = builtin.is_test;
87
9const __eqdf2 = @import("./cmpdf2.zig").__eqdf2;8const __eqdf2 = @import("./cmpdf2.zig").__eqdf2;
10const __ledf2 = @import("./cmpdf2.zig").__ledf2;9const __ledf2 = @import("./cmpdf2.zig").__ledf2;
lib/compiler_rt/comparesf2_test.zig-1
...@@ -4,7 +4,6 @@...@@ -4,7 +4,6 @@
44
5const std = @import("std");5const std = @import("std");
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const is_test = builtin.is_test;
87
9const __eqsf2 = @import("./cmpsf2.zig").__eqsf2;8const __eqsf2 = @import("./cmpsf2.zig").__eqsf2;
10const __lesf2 = @import("./cmpsf2.zig").__lesf2;9const __lesf2 = @import("./cmpsf2.zig").__lesf2;
lib/compiler_rt/count0bits.zig-1
...@@ -1,6 +1,5 @@...@@ -1,6 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const common = @import("common.zig");3const common = @import("common.zig");
54
6pub const panic = common.panic;5pub const panic = common.panic;
lib/compiler_rt/divdf3.zig-1
...@@ -5,7 +5,6 @@...@@ -5,7 +5,6 @@
5const std = @import("std");5const std = @import("std");
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const arch = builtin.cpu.arch;7const arch = builtin.cpu.arch;
8const is_test = builtin.is_test;
9const common = @import("common.zig");8const common = @import("common.zig");
109
11const normalize = common.normalize;10const normalize = common.normalize;
lib/compiler_rt/divmodei4.zig+2-2
...@@ -34,7 +34,7 @@ fn divmod(q: ?[]u32, r: ?[]u32, u: []u32, v: []u32) !void {...@@ -34,7 +34,7 @@ fn divmod(q: ?[]u32, r: ?[]u32, u: []u32, v: []u32) !void {
34}34}
3535
36pub fn __divei4(q_p: [*]u8, u_p: [*]u8, v_p: [*]u8, bits: usize) callconv(.c) void {36pub fn __divei4(q_p: [*]u8, u_p: [*]u8, v_p: [*]u8, bits: usize) callconv(.c) void {
37 @setRuntimeSafety(builtin.is_test);37 @setRuntimeSafety(common.test_safety);
38 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));38 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
39 const q: []u32 = @ptrCast(@alignCast(q_p[0..byte_size]));39 const q: []u32 = @ptrCast(@alignCast(q_p[0..byte_size]));
40 const u: []u32 = @ptrCast(@alignCast(u_p[0..byte_size]));40 const u: []u32 = @ptrCast(@alignCast(u_p[0..byte_size]));
...@@ -43,7 +43,7 @@ pub fn __divei4(q_p: [*]u8, u_p: [*]u8, v_p: [*]u8, bits: usize) callconv(.c) vo...@@ -43,7 +43,7 @@ pub fn __divei4(q_p: [*]u8, u_p: [*]u8, v_p: [*]u8, bits: usize) callconv(.c) vo
43}43}
4444
45pub fn __modei4(r_p: [*]u8, u_p: [*]u8, v_p: [*]u8, bits: usize) callconv(.c) void {45pub fn __modei4(r_p: [*]u8, u_p: [*]u8, v_p: [*]u8, bits: usize) callconv(.c) void {
46 @setRuntimeSafety(builtin.is_test);46 @setRuntimeSafety(common.test_safety);
47 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));47 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
48 const r: []u32 = @ptrCast(@alignCast(r_p[0..byte_size]));48 const r: []u32 = @ptrCast(@alignCast(r_p[0..byte_size]));
49 const u: []u32 = @ptrCast(@alignCast(u_p[0..byte_size]));49 const u: []u32 = @ptrCast(@alignCast(u_p[0..byte_size]));
lib/compiler_rt/fixint_test.zig-1
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1const is_test = @import("builtin").is_test;
2const std = @import("std");1const std = @import("std");
3const math = std.math;2const math = std.math;
4const testing = std.testing;3const testing = std.testing;
lib/compiler_rt/int.zig-1
...@@ -6,7 +6,6 @@ const testing = std.testing;...@@ -6,7 +6,6 @@ const testing = std.testing;
6const maxInt = std.math.maxInt;6const maxInt = std.math.maxInt;
7const minInt = std.math.minInt;7const minInt = std.math.minInt;
8const arch = builtin.cpu.arch;8const arch = builtin.cpu.arch;
9const is_test = builtin.is_test;
10const common = @import("common.zig");9const common = @import("common.zig");
11const udivmod = @import("udivmod.zig").udivmod;10const udivmod = @import("udivmod.zig").udivmod;
12const __divti3 = @import("divti3.zig").__divti3;11const __divti3 = @import("divti3.zig").__divti3;
lib/compiler_rt/memcpy.zig+3-1
...@@ -11,7 +11,7 @@ comptime {...@@ -11,7 +11,7 @@ comptime {
11 .visibility = common.visibility,11 .visibility = common.visibility,
12 };12 };
1313
14 if (builtin.mode == .ReleaseSmall)14 if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64)
15 @export(&memcpySmall, export_options)15 @export(&memcpySmall, export_options)
16 else16 else
17 @export(&memcpyFast, export_options);17 @export(&memcpyFast, export_options);
...@@ -195,6 +195,8 @@ inline fn copyRange4(...@@ -195,6 +195,8 @@ inline fn copyRange4(
195}195}
196196
197test "memcpy" {197test "memcpy" {
198 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
199
198 const S = struct {200 const S = struct {
199 fn testFunc(comptime copy_func: anytype) !void {201 fn testFunc(comptime copy_func: anytype) !void {
200 const max_len = 1024;202 const max_len = 1024;
lib/compiler_rt/memmove.zig+9-7
...@@ -14,7 +14,7 @@ comptime {...@@ -14,7 +14,7 @@ comptime {
14 .visibility = common.visibility,14 .visibility = common.visibility,
15 };15 };
1616
17 if (builtin.mode == .ReleaseSmall)17 if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64)
18 @export(&memmoveSmall, export_options)18 @export(&memmoveSmall, export_options)
19 else19 else
20 @export(&memmoveFast, export_options);20 @export(&memmoveFast, export_options);
...@@ -39,7 +39,7 @@ fn memmoveSmall(opt_dest: ?[*]u8, opt_src: ?[*]const u8, len: usize) callconv(.c...@@ -39,7 +39,7 @@ fn memmoveSmall(opt_dest: ?[*]u8, opt_src: ?[*]const u8, len: usize) callconv(.c
39}39}
4040
41fn memmoveFast(dest: ?[*]u8, src: ?[*]u8, len: usize) callconv(.c) ?[*]u8 {41fn memmoveFast(dest: ?[*]u8, src: ?[*]u8, len: usize) callconv(.c) ?[*]u8 {
42 @setRuntimeSafety(builtin.is_test);42 @setRuntimeSafety(common.test_safety);
43 const small_limit = @max(2 * @sizeOf(Element), @sizeOf(Element));43 const small_limit = @max(2 * @sizeOf(Element), @sizeOf(Element));
4444
45 if (copySmallLength(small_limit, dest.?, src.?, len)) return dest;45 if (copySmallLength(small_limit, dest.?, src.?, len)) return dest;
...@@ -79,7 +79,7 @@ inline fn copyLessThan16(...@@ -79,7 +79,7 @@ inline fn copyLessThan16(
79 src: [*]const u8,79 src: [*]const u8,
80 len: usize,80 len: usize,
81) void {81) void {
82 @setRuntimeSafety(builtin.is_test);82 @setRuntimeSafety(common.test_safety);
83 if (len < 4) {83 if (len < 4) {
84 if (len == 0) return;84 if (len == 0) return;
85 const b = len / 2;85 const b = len / 2;
...@@ -100,7 +100,7 @@ inline fn copy16ToSmallLimit(...@@ -100,7 +100,7 @@ inline fn copy16ToSmallLimit(
100 src: [*]const u8,100 src: [*]const u8,
101 len: usize,101 len: usize,
102) bool {102) bool {
103 @setRuntimeSafety(builtin.is_test);103 @setRuntimeSafety(common.test_safety);
104 inline for (2..(std.math.log2(small_limit) + 1) / 2 + 1) |p| {104 inline for (2..(std.math.log2(small_limit) + 1) / 2 + 1) |p| {
105 const limit = 1 << (2 * p);105 const limit = 1 << (2 * p);
106 if (len < limit) {106 if (len < limit) {
...@@ -119,7 +119,7 @@ inline fn copyRange4(...@@ -119,7 +119,7 @@ inline fn copyRange4(
119 src: [*]const u8,119 src: [*]const u8,
120 len: usize,120 len: usize,
121) void {121) void {
122 @setRuntimeSafety(builtin.is_test);122 @setRuntimeSafety(common.test_safety);
123 comptime assert(std.math.isPowerOfTwo(copy_len));123 comptime assert(std.math.isPowerOfTwo(copy_len));
124 assert(len >= copy_len);124 assert(len >= copy_len);
125 assert(len < 4 * copy_len);125 assert(len < 4 * copy_len);
...@@ -147,7 +147,7 @@ inline fn copyForwards(...@@ -147,7 +147,7 @@ inline fn copyForwards(
147 src: [*]const u8,147 src: [*]const u8,
148 len: usize,148 len: usize,
149) void {149) void {
150 @setRuntimeSafety(builtin.is_test);150 @setRuntimeSafety(common.test_safety);
151 assert(len >= 2 * @sizeOf(Element));151 assert(len >= 2 * @sizeOf(Element));
152152
153 const head = src[0..@sizeOf(Element)].*;153 const head = src[0..@sizeOf(Element)].*;
...@@ -181,7 +181,7 @@ inline fn copyBlocks(...@@ -181,7 +181,7 @@ inline fn copyBlocks(
181 src: anytype,181 src: anytype,
182 max_bytes: usize,182 max_bytes: usize,
183) void {183) void {
184 @setRuntimeSafety(builtin.is_test);184 @setRuntimeSafety(common.test_safety);
185185
186 const T = @typeInfo(@TypeOf(dest)).pointer.child;186 const T = @typeInfo(@TypeOf(dest)).pointer.child;
187 comptime assert(T == @typeInfo(@TypeOf(src)).pointer.child);187 comptime assert(T == @typeInfo(@TypeOf(src)).pointer.child);
...@@ -217,6 +217,8 @@ inline fn copyBackwards(...@@ -217,6 +217,8 @@ inline fn copyBackwards(
217}217}
218218
219test memmoveFast {219test memmoveFast {
220 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
221
220 const max_len = 1024;222 const max_len = 1024;
221 var buffer: [max_len + @alignOf(Element) - 1]u8 = undefined;223 var buffer: [max_len + @alignOf(Element) - 1]u8 = undefined;
222 for (&buffer, 0..) |*b, i| {224 for (&buffer, 0..) |*b, i| {
lib/compiler_rt/mulf3.zig+2-2
...@@ -6,7 +6,7 @@ const common = @import("./common.zig");...@@ -6,7 +6,7 @@ const common = @import("./common.zig");
6/// Ported from:6/// Ported from:
7/// https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc7/// https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc
8pub inline fn mulf3(comptime T: type, a: T, b: T) T {8pub inline fn mulf3(comptime T: type, a: T, b: T) T {
9 @setRuntimeSafety(builtin.is_test);9 @setRuntimeSafety(common.test_safety);
10 const typeWidth = @typeInfo(T).float.bits;10 const typeWidth = @typeInfo(T).float.bits;
11 const significandBits = math.floatMantissaBits(T);11 const significandBits = math.floatMantissaBits(T);
12 const fractionalBits = math.floatFractionalBits(T);12 const fractionalBits = math.floatFractionalBits(T);
...@@ -163,7 +163,7 @@ pub inline fn mulf3(comptime T: type, a: T, b: T) T {...@@ -163,7 +163,7 @@ pub inline fn mulf3(comptime T: type, a: T, b: T) T {
163///163///
164/// This is analogous to an shr version of `@shlWithOverflow`164/// This is analogous to an shr version of `@shlWithOverflow`
165fn wideShrWithTruncation(comptime Z: type, hi: *Z, lo: *Z, count: u32) bool {165fn wideShrWithTruncation(comptime Z: type, hi: *Z, lo: *Z, count: u32) bool {
166 @setRuntimeSafety(builtin.is_test);166 @setRuntimeSafety(common.test_safety);
167 const typeWidth = @typeInfo(Z).int.bits;167 const typeWidth = @typeInfo(Z).int.bits;
168 var inexact = false;168 var inexact = false;
169 if (count < typeWidth) {169 if (count < typeWidth) {
lib/compiler_rt/rem_pio2_large.zig+1-1
...@@ -251,7 +251,7 @@ const PIo2 = [_]f64{...@@ -251,7 +251,7 @@ const PIo2 = [_]f64{
251/// compiler will convert from decimal to binary accurately enough251/// compiler will convert from decimal to binary accurately enough
252/// to produce the hexadecimal values shown.252/// to produce the hexadecimal values shown.
253///253///
254pub fn rem_pio2_large(x: []f64, y: []f64, e0: i32, nx: i32, prec: usize) i32 {254pub fn rem_pio2_large(x: []const f64, y: []f64, e0: i32, nx: i32, prec: usize) i32 {
255 var jz: i32 = undefined;255 var jz: i32 = undefined;
256 var jx: i32 = undefined;256 var jx: i32 = undefined;
257 var jv: i32 = undefined;257 var jv: i32 = undefined;
lib/compiler_rt/stack_probe.zig-1
...@@ -4,7 +4,6 @@ const common = @import("common.zig");...@@ -4,7 +4,6 @@ const common = @import("common.zig");
4const os_tag = builtin.os.tag;4const os_tag = builtin.os.tag;
5const arch = builtin.cpu.arch;5const arch = builtin.cpu.arch;
6const abi = builtin.abi;6const abi = builtin.abi;
7const is_test = builtin.is_test;
87
9pub const panic = common.panic;8pub const panic = common.panic;
109
lib/compiler_rt/suboti4_test.zig+3
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const subo = @import("subo.zig");1const subo = @import("subo.zig");
2const builtin = @import("builtin");
2const std = @import("std");3const std = @import("std");
3const testing = std.testing;4const testing = std.testing;
4const math = std.math;5const math = std.math;
...@@ -27,6 +28,8 @@ pub fn simple_suboti4(a: i128, b: i128, overflow: *c_int) i128 {...@@ -27,6 +28,8 @@ pub fn simple_suboti4(a: i128, b: i128, overflow: *c_int) i128 {
27}28}
2829
29test "suboti3" {30test "suboti3" {
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
32
30 const min: i128 = math.minInt(i128);33 const min: i128 = math.minInt(i128);
31 const max: i128 = math.maxInt(i128);34 const max: i128 = math.maxInt(i128);
32 var i: i128 = 1;35 var i: i128 = 1;
lib/compiler_rt/udivmod.zig+5-5
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const Log2Int = std.math.Log2Int;3const Log2Int = std.math.Log2Int;
5const HalveInt = @import("common.zig").HalveInt;4const common = @import("common.zig");
5const HalveInt = common.HalveInt;
66
7const lo = switch (builtin.cpu.arch.endian()) {7const lo = switch (builtin.cpu.arch.endian()) {
8 .big => 1,8 .big => 1,
...@@ -14,7 +14,7 @@ const hi = 1 - lo;...@@ -14,7 +14,7 @@ const hi = 1 - lo;
14// Returns U / v_ and sets r = U % v_.14// Returns U / v_ and sets r = U % v_.
15fn divwide_generic(comptime T: type, _u1: T, _u0: T, v_: T, r: *T) T {15fn divwide_generic(comptime T: type, _u1: T, _u0: T, v_: T, r: *T) T {
16 const HalfT = HalveInt(T, false).HalfT;16 const HalfT = HalveInt(T, false).HalfT;
17 @setRuntimeSafety(is_test);17 @setRuntimeSafety(common.test_safety);
18 var v = v_;18 var v = v_;
1919
20 const b = @as(T, 1) << (@bitSizeOf(T) / 2);20 const b = @as(T, 1) << (@bitSizeOf(T) / 2);
...@@ -70,7 +70,7 @@ fn divwide_generic(comptime T: type, _u1: T, _u0: T, v_: T, r: *T) T {...@@ -70,7 +70,7 @@ fn divwide_generic(comptime T: type, _u1: T, _u0: T, v_: T, r: *T) T {
70}70}
7171
72fn divwide(comptime T: type, _u1: T, _u0: T, v: T, r: *T) T {72fn divwide(comptime T: type, _u1: T, _u0: T, v: T, r: *T) T {
73 @setRuntimeSafety(is_test);73 @setRuntimeSafety(common.test_safety);
74 if (T == u64 and builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag != .windows) {74 if (T == u64 and builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag != .windows) {
75 var rem: T = undefined;75 var rem: T = undefined;
76 const quo = asm (76 const quo = asm (
...@@ -90,7 +90,7 @@ fn divwide(comptime T: type, _u1: T, _u0: T, v: T, r: *T) T {...@@ -90,7 +90,7 @@ fn divwide(comptime T: type, _u1: T, _u0: T, v: T, r: *T) T {
9090
91// Returns a_ / b_ and sets maybe_rem = a_ % b.91// Returns a_ / b_ and sets maybe_rem = a_ % b.
92pub fn udivmod(comptime T: type, a_: T, b_: T, maybe_rem: ?*T) T {92pub fn udivmod(comptime T: type, a_: T, b_: T, maybe_rem: ?*T) T {
93 @setRuntimeSafety(is_test);93 @setRuntimeSafety(common.test_safety);
94 const HalfT = HalveInt(T, false).HalfT;94 const HalfT = HalveInt(T, false).HalfT;
95 const SignedT = std.meta.Int(.signed, @bitSizeOf(T));95 const SignedT = std.meta.Int(.signed, @bitSizeOf(T));
9696
lib/compiler_rt/udivmodei4.zig+3-2
...@@ -113,7 +113,7 @@ pub fn divmod(q: ?[]u32, r: ?[]u32, u: []const u32, v: []const u32) !void {...@@ -113,7 +113,7 @@ pub fn divmod(q: ?[]u32, r: ?[]u32, u: []const u32, v: []const u32) !void {
113}113}
114114
115pub fn __udivei4(q_p: [*]u8, u_p: [*]const u8, v_p: [*]const u8, bits: usize) callconv(.c) void {115pub fn __udivei4(q_p: [*]u8, u_p: [*]const u8, v_p: [*]const u8, bits: usize) callconv(.c) void {
116 @setRuntimeSafety(builtin.is_test);116 @setRuntimeSafety(common.test_safety);
117 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));117 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
118 const q: []u32 = @ptrCast(@alignCast(q_p[0..byte_size]));118 const q: []u32 = @ptrCast(@alignCast(q_p[0..byte_size]));
119 const u: []const u32 = @ptrCast(@alignCast(u_p[0..byte_size]));119 const u: []const u32 = @ptrCast(@alignCast(u_p[0..byte_size]));
...@@ -122,7 +122,7 @@ pub fn __udivei4(q_p: [*]u8, u_p: [*]const u8, v_p: [*]const u8, bits: usize) ca...@@ -122,7 +122,7 @@ pub fn __udivei4(q_p: [*]u8, u_p: [*]const u8, v_p: [*]const u8, bits: usize) ca
122}122}
123123
124pub fn __umodei4(r_p: [*]u8, u_p: [*]const u8, v_p: [*]const u8, bits: usize) callconv(.c) void {124pub fn __umodei4(r_p: [*]u8, u_p: [*]const u8, v_p: [*]const u8, bits: usize) callconv(.c) void {
125 @setRuntimeSafety(builtin.is_test);125 @setRuntimeSafety(common.test_safety);
126 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));126 const byte_size = std.zig.target.intByteSize(&builtin.target, @intCast(bits));
127 const r: []u32 = @ptrCast(@alignCast(r_p[0..byte_size]));127 const r: []u32 = @ptrCast(@alignCast(r_p[0..byte_size]));
128 const u: []const u32 = @ptrCast(@alignCast(u_p[0..byte_size]));128 const u: []const u32 = @ptrCast(@alignCast(u_p[0..byte_size]));
...@@ -131,6 +131,7 @@ pub fn __umodei4(r_p: [*]u8, u_p: [*]const u8, v_p: [*]const u8, bits: usize) ca...@@ -131,6 +131,7 @@ pub fn __umodei4(r_p: [*]u8, u_p: [*]const u8, v_p: [*]const u8, bits: usize) ca
131}131}
132132
133test "__udivei4/__umodei4" {133test "__udivei4/__umodei4" {
134 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
134 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;135 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
135 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;136 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
136137
lib/docs/wasm/main.zig+3-3
...@@ -779,10 +779,10 @@ export fn decl_type_html(decl_index: Decl.Index) String {...@@ -779,10 +779,10 @@ export fn decl_type_html(decl_index: Decl.Index) String {
779const Oom = error{OutOfMemory};779const Oom = error{OutOfMemory};
780780
781fn unpackInner(tar_bytes: []u8) !void {781fn unpackInner(tar_bytes: []u8) !void {
782 var br: std.io.Reader = .fixed(tar_bytes);782 var reader: std.Io.Reader = .fixed(tar_bytes);
783 var file_name_buffer: [1024]u8 = undefined;783 var file_name_buffer: [1024]u8 = undefined;
784 var link_name_buffer: [1024]u8 = undefined;784 var link_name_buffer: [1024]u8 = undefined;
785 var it = std.tar.Iterator.init(&br, .{785 var it: std.tar.Iterator = .init(&reader, .{
786 .file_name_buffer = &file_name_buffer,786 .file_name_buffer = &file_name_buffer,
787 .link_name_buffer = &link_name_buffer,787 .link_name_buffer = &link_name_buffer,
788 });788 });
...@@ -803,7 +803,7 @@ fn unpackInner(tar_bytes: []u8) !void {...@@ -803,7 +803,7 @@ fn unpackInner(tar_bytes: []u8) !void {
803 {803 {
804 gop.value_ptr.* = file;804 gop.value_ptr.* = file;
805 }805 }
806 const file_bytes = tar_bytes[br.seek..][0..@intCast(tar_file.size)];806 const file_bytes = tar_bytes[reader.seek..][0..@intCast(tar_file.size)];
807 assert(file == try Walk.add_file(file_name, file_bytes));807 assert(file == try Walk.add_file(file_name, file_bytes));
808 }808 }
809 } else {809 } else {
lib/std/Build/Fuzz/WebServer.zig+4-2
...@@ -519,6 +519,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {...@@ -519,6 +519,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
519519
520 var response_writer = body.writer().unbuffered();520 var response_writer = body.writer().unbuffered();
521 var archiver: std.tar.Writer = .{ .underlying_writer = &response_writer };521 var archiver: std.tar.Writer = .{ .underlying_writer = &response_writer };
522 var read_buffer: [1024]u8 = undefined;
522523
523 for (deduped_paths) |joined_path| {524 for (deduped_paths) |joined_path| {
524 var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {525 var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {
...@@ -526,9 +527,10 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {...@@ -526,9 +527,10 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
526 continue;527 continue;
527 };528 };
528 defer file.close();529 defer file.close();
529530 const stat = try file.stat();
531 var file_reader: std.fs.File.Reader = .initSize(file, &read_buffer, stat.size);
530 archiver.prefix = joined_path.root_dir.path orelse try memoizedCwd(arena, &cwd_cache);532 archiver.prefix = joined_path.root_dir.path orelse try memoizedCwd(arena, &cwd_cache);
531 try archiver.writeFile(joined_path.sub_path, file, try file.stat());533 try archiver.writeFile(joined_path.sub_path, &file_reader, stat.mtime);
532 }534 }
533535
534 try body.end();536 try body.end();
lib/std/Io.zig+1
...@@ -493,5 +493,6 @@ test {...@@ -493,5 +493,6 @@ test {
493 _ = Reader;493 _ = Reader;
494 _ = Reader.Limited;494 _ = Reader.Limited;
495 _ = Writer;495 _ = Writer;
496 _ = tty;
496 _ = @import("Io/test.zig");497 _ = @import("Io/test.zig");
497}498}
lib/std/Io/DeprecatedReader.zig+3-1
...@@ -393,10 +393,12 @@ pub const Adapter = struct {...@@ -393,10 +393,12 @@ pub const Adapter = struct {
393 fn stream(r: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {393 fn stream(r: *std.io.Reader, w: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
394 const a: *@This() = @alignCast(@fieldParentPtr("new_interface", r));394 const a: *@This() = @alignCast(@fieldParentPtr("new_interface", r));
395 const buf = limit.slice(try w.writableSliceGreedy(1));395 const buf = limit.slice(try w.writableSliceGreedy(1));
396 return a.derp_reader.read(buf) catch |err| {396 const n = a.derp_reader.read(buf) catch |err| {
397 a.err = err;397 a.err = err;
398 return error.ReadFailed;398 return error.ReadFailed;
399 };399 };
400 w.advance(n);
401 return n;
400 }402 }
401};403};
402404
lib/std/Io/DeprecatedWriter.zig+6-1
...@@ -100,7 +100,12 @@ pub const Adapter = struct {...@@ -100,7 +100,12 @@ pub const Adapter = struct {
100100
101 fn drain(w: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {101 fn drain(w: *std.io.Writer, data: []const []const u8, splat: usize) std.io.Writer.Error!usize {
102 _ = splat;102 _ = splat;
103 const a: *@This() = @fieldParentPtr("new_interface", w);103 const a: *@This() = @alignCast(@fieldParentPtr("new_interface", w));
104 const buffered = w.buffered();
105 if (buffered.len != 0) return w.consume(a.derp_writer.write(buffered) catch |err| {
106 a.err = err;
107 return error.WriteFailed;
108 });
104 return a.derp_writer.write(data[0]) catch |err| {109 return a.derp_writer.write(data[0]) catch |err| {
105 a.err = err;110 a.err = err;
106 return error.WriteFailed;111 return error.WriteFailed;
lib/std/Io/Reader.zig+6
...@@ -179,6 +179,12 @@ pub fn streamExact(r: *Reader, w: *Writer, n: usize) StreamError!void {...@@ -179,6 +179,12 @@ pub fn streamExact(r: *Reader, w: *Writer, n: usize) StreamError!void {
179 while (remaining != 0) remaining -= try r.stream(w, .limited(remaining));179 while (remaining != 0) remaining -= try r.stream(w, .limited(remaining));
180}180}
181181
182/// "Pump" exactly `n` bytes from the reader to the writer.
183pub fn streamExact64(r: *Reader, w: *Writer, n: u64) StreamError!void {
184 var remaining = n;
185 while (remaining != 0) remaining -= try r.stream(w, .limited64(remaining));
186}
187
182/// "Pump" data from the reader to the writer, handling `error.EndOfStream` as188/// "Pump" data from the reader to the writer, handling `error.EndOfStream` as
183/// a success case.189/// a success case.
184///190///
lib/std/Io/Writer.zig+4
...@@ -2242,6 +2242,10 @@ pub const Discarding = struct {...@@ -2242,6 +2242,10 @@ pub const Discarding = struct {
22422242
2243 pub fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {2243 pub fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
2244 if (File.Handle == void) return error.Unimplemented;2244 if (File.Handle == void) return error.Unimplemented;
2245 switch (builtin.zig_backend) {
2246 else => {},
2247 .stage2_aarch64 => return error.Unimplemented,
2248 }
2245 const d: *Discarding = @alignCast(@fieldParentPtr("writer", w));2249 const d: *Discarding = @alignCast(@fieldParentPtr("writer", w));
2246 d.count += w.end;2250 d.count += w.end;
2247 w.end = 0;2251 w.end = 0;
lib/std/Io/find_byte_writer.zig deleted-40
...@@ -1,40 +0,0 @@
1const std = @import("../std.zig");
2const io = std.io;
3const assert = std.debug.assert;
4
5/// A Writer that returns whether the given character has been written to it.
6/// The contents are not written to anything.
7pub fn FindByteWriter(comptime UnderlyingWriter: type) type {
8 return struct {
9 const Self = @This();
10 pub const Error = UnderlyingWriter.Error;
11 pub const Writer = io.GenericWriter(*Self, Error, write);
12
13 underlying_writer: UnderlyingWriter,
14 byte_found: bool,
15 byte: u8,
16
17 pub fn writer(self: *Self) Writer {
18 return .{ .context = self };
19 }
20
21 fn write(self: *Self, bytes: []const u8) Error!usize {
22 if (!self.byte_found) {
23 self.byte_found = blk: {
24 for (bytes) |b|
25 if (b == self.byte) break :blk true;
26 break :blk false;
27 };
28 }
29 return self.underlying_writer.write(bytes);
30 }
31 };
32}
33
34pub fn findByteWriter(byte: u8, underlying_writer: anytype) FindByteWriter(@TypeOf(underlying_writer)) {
35 return FindByteWriter(@TypeOf(underlying_writer)){
36 .underlying_writer = underlying_writer,
37 .byte = byte,
38 .byte_found = false,
39 };
40}
lib/std/Progress.zig+4-1
...@@ -408,6 +408,9 @@ pub const have_ipc = switch (builtin.os.tag) {...@@ -408,6 +408,9 @@ pub const have_ipc = switch (builtin.os.tag) {
408const noop_impl = builtin.single_threaded or switch (builtin.os.tag) {408const noop_impl = builtin.single_threaded or switch (builtin.os.tag) {
409 .wasi, .freestanding => true,409 .wasi, .freestanding => true,
410 else => false,410 else => false,
411} or switch (builtin.zig_backend) {
412 .stage2_aarch64 => true,
413 else => false,
411};414};
412415
413/// Initializes a global Progress instance.416/// Initializes a global Progress instance.
...@@ -754,7 +757,7 @@ fn appendTreeSymbol(symbol: TreeSymbol, buf: []u8, start_i: usize) usize {...@@ -754,7 +757,7 @@ fn appendTreeSymbol(symbol: TreeSymbol, buf: []u8, start_i: usize) usize {
754}757}
755758
756fn clearWrittenWithEscapeCodes() anyerror!void {759fn clearWrittenWithEscapeCodes() anyerror!void {
757 if (!global_progress.need_clear) return;760 if (noop_impl or !global_progress.need_clear) return;
758761
759 global_progress.need_clear = false;762 global_progress.need_clear = false;
760 try write(clear);763 try write(clear);
lib/std/builtin.zig+5-2
...@@ -774,7 +774,7 @@ pub const Endian = enum {...@@ -774,7 +774,7 @@ pub const Endian = enum {
774774
775/// This data structure is used by the Zig language code generation and775/// This data structure is used by the Zig language code generation and
776/// therefore must be kept in sync with the compiler implementation.776/// therefore must be kept in sync with the compiler implementation.
777pub const Signedness = enum {777pub const Signedness = enum(u1) {
778 signed,778 signed,
779 unsigned,779 unsigned,
780};780};
...@@ -896,7 +896,10 @@ pub const VaList = switch (builtin.cpu.arch) {...@@ -896,7 +896,10 @@ pub const VaList = switch (builtin.cpu.arch) {
896 .aarch64, .aarch64_be => switch (builtin.os.tag) {896 .aarch64, .aarch64_be => switch (builtin.os.tag) {
897 .windows => *u8,897 .windows => *u8,
898 .ios, .macos, .tvos, .watchos, .visionos => *u8,898 .ios, .macos, .tvos, .watchos, .visionos => *u8,
899 else => @compileError("disabled due to miscompilations"), // VaListAarch64,899 else => switch (builtin.zig_backend) {
900 .stage2_aarch64 => VaListAarch64,
901 else => @compileError("disabled due to miscompilations"),
902 },
900 },903 },
901 .arm, .armeb, .thumb, .thumbeb => switch (builtin.os.tag) {904 .arm, .armeb, .thumb, .thumbeb => switch (builtin.os.tag) {
902 .ios, .macos, .tvos, .watchos, .visionos => *u8,905 .ios, .macos, .tvos, .watchos, .visionos => *u8,
lib/std/crypto/md5.zig+10-2
...@@ -54,12 +54,20 @@ pub const Md5 = struct {...@@ -54,12 +54,20 @@ pub const Md5 = struct {
54 };54 };
55 }55 }
5656
57 pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void {57 pub fn hash(data: []const u8, out: *[digest_length]u8, options: Options) void {
58 var d = Md5.init(options);58 var d = Md5.init(options);
59 d.update(b);59 d.update(data);
60 d.final(out);60 d.final(out);
61 }61 }
6262
63 pub fn hashResult(data: []const u8) [digest_length]u8 {
64 var out: [digest_length]u8 = undefined;
65 var d = Md5.init(.{});
66 d.update(data);
67 d.final(&out);
68 return out;
69 }
70
63 pub fn update(d: *Self, b: []const u8) void {71 pub fn update(d: *Self, b: []const u8) void {
64 var off: usize = 0;72 var off: usize = 0;
6573
lib/std/elf.zig+1-1
...@@ -2001,7 +2001,7 @@ pub const R_AARCH64 = enum(u32) {...@@ -2001,7 +2001,7 @@ pub const R_AARCH64 = enum(u32) {
2001 TLSLE_LDST64_TPREL_LO12 = 558,2001 TLSLE_LDST64_TPREL_LO12 = 558,
2002 /// Likewise; no check.2002 /// Likewise; no check.
2003 TLSLE_LDST64_TPREL_LO12_NC = 559,2003 TLSLE_LDST64_TPREL_LO12_NC = 559,
2004 /// PC-rel. load immediate 20:2.2004 /// PC-rel. load immediate 20:2.
2005 TLSDESC_LD_PREL19 = 560,2005 TLSDESC_LD_PREL19 = 560,
2006 /// PC-rel. ADR immediate 20:0.2006 /// PC-rel. ADR immediate 20:0.
2007 TLSDESC_ADR_PREL21 = 561,2007 TLSDESC_ADR_PREL21 = 561,
lib/std/fs/File.zig+4-1
...@@ -1337,7 +1337,10 @@ pub const Writer = struct {...@@ -1337,7 +1337,10 @@ pub const Writer = struct {
1337 return .{1337 return .{
1338 .vtable = &.{1338 .vtable = &.{
1339 .drain = drain,1339 .drain = drain,
1340 .sendFile = sendFile,1340 .sendFile = switch (builtin.zig_backend) {
1341 else => sendFile,
1342 .stage2_aarch64 => std.io.Writer.unimplementedSendFile,
1343 },
1341 },1344 },
1342 .buffer = buffer,1345 .buffer = buffer,
1343 };1346 };
lib/std/math.zig+55-38
...@@ -45,6 +45,7 @@ pub const rad_per_deg = 0.017453292519943295769236907684886127134428718885417254...@@ -45,6 +45,7 @@ pub const rad_per_deg = 0.017453292519943295769236907684886127134428718885417254
45/// 180.0/pi45/// 180.0/pi
46pub const deg_per_rad = 57.295779513082320876798154814105170332405472466564321549160243861;46pub const deg_per_rad = 57.295779513082320876798154814105170332405472466564321549160243861;
4747
48pub const Sign = enum(u1) { positive, negative };
48pub const FloatRepr = float.FloatRepr;49pub const FloatRepr = float.FloatRepr;
49pub const floatExponentBits = float.floatExponentBits;50pub const floatExponentBits = float.floatExponentBits;
50pub const floatMantissaBits = float.floatMantissaBits;51pub const floatMantissaBits = float.floatMantissaBits;
...@@ -607,27 +608,30 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {...@@ -607,27 +608,30 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {
607/// Shifts left. Overflowed bits are truncated.608/// Shifts left. Overflowed bits are truncated.
608/// A negative shift amount results in a right shift.609/// A negative shift amount results in a right shift.
609pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {610pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {
611 const is_shl = shift_amt >= 0;
610 const abs_shift_amt = @abs(shift_amt);612 const abs_shift_amt = @abs(shift_amt);
611613 const casted_shift_amt = casted_shift_amt: switch (@typeInfo(T)) {
612 const casted_shift_amt = blk: {614 .int => |info| {
613 if (@typeInfo(T) == .vector) {615 if (abs_shift_amt < info.bits) break :casted_shift_amt @as(
614 const C = @typeInfo(T).vector.child;616 Log2Int(T),
615 const len = @typeInfo(T).vector.len;617 @intCast(abs_shift_amt),
616 if (abs_shift_amt >= @typeInfo(C).int.bits) return @splat(0);618 );
617 break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt))));619 if (info.signedness == .unsigned or is_shl) return 0;
618 } else {620 return a >> (info.bits - 1);
619 if (abs_shift_amt >= @typeInfo(T).int.bits) return 0;621 },
620 break :blk @as(Log2Int(T), @intCast(abs_shift_amt));622 .vector => |info| {
621 }623 const Child = info.child;
624 const child_info = @typeInfo(Child).int;
625 if (abs_shift_amt < child_info.bits) break :casted_shift_amt @as(
626 @Vector(info.len, Log2Int(Child)),
627 @splat(@as(Log2Int(Child), @intCast(abs_shift_amt))),
628 );
629 if (child_info.signedness == .unsigned or is_shl) return @splat(0);
630 return a >> @splat(child_info.bits - 1);
631 },
632 else => comptime unreachable,
622 };633 };
623634 return if (is_shl) a << casted_shift_amt else a >> casted_shift_amt;
624 if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).int.signedness == .signed) {
625 if (shift_amt < 0) {
626 return a >> casted_shift_amt;
627 }
628 }
629
630 return a << casted_shift_amt;
631}635}
632636
633test shl {637test shl {
...@@ -642,32 +646,40 @@ test shl {...@@ -642,32 +646,40 @@ test shl {
642 try testing.expect(shl(@Vector(1, u32), @Vector(1, u32){42}, @as(usize, 1))[0] == @as(u32, 42) << 1);646 try testing.expect(shl(@Vector(1, u32), @Vector(1, u32){42}, @as(usize, 1))[0] == @as(u32, 42) << 1);
643 try testing.expect(shl(@Vector(1, u32), @Vector(1, u32){42}, @as(isize, -1))[0] == @as(u32, 42) >> 1);647 try testing.expect(shl(@Vector(1, u32), @Vector(1, u32){42}, @as(isize, -1))[0] == @as(u32, 42) >> 1);
644 try testing.expect(shl(@Vector(1, u32), @Vector(1, u32){42}, 33)[0] == 0);648 try testing.expect(shl(@Vector(1, u32), @Vector(1, u32){42}, 33)[0] == 0);
649
650 try testing.expect(shl(i8, -1, -100) == -1);
651 try testing.expect(shl(i8, -1, 100) == 0);
652 try testing.expect(@reduce(.And, shl(@Vector(2, i8), .{ -1, 1 }, -100) == @Vector(2, i8){ -1, 0 }));
653 try testing.expect(@reduce(.And, shl(@Vector(2, i8), .{ -1, 1 }, 100) == @Vector(2, i8){ 0, 0 }));
645}654}
646655
647/// Shifts right. Overflowed bits are truncated.656/// Shifts right. Overflowed bits are truncated.
648/// A negative shift amount results in a left shift.657/// A negative shift amount results in a left shift.
649pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {658pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {
659 const is_shl = shift_amt < 0;
650 const abs_shift_amt = @abs(shift_amt);660 const abs_shift_amt = @abs(shift_amt);
651661 const casted_shift_amt = casted_shift_amt: switch (@typeInfo(T)) {
652 const casted_shift_amt = blk: {662 .int => |info| {
653 if (@typeInfo(T) == .vector) {663 if (abs_shift_amt < info.bits) break :casted_shift_amt @as(
654 const C = @typeInfo(T).vector.child;664 Log2Int(T),
655 const len = @typeInfo(T).vector.len;665 @intCast(abs_shift_amt),
656 if (abs_shift_amt >= @typeInfo(C).int.bits) return @splat(0);666 );
657 break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt))));667 if (info.signedness == .unsigned or is_shl) return 0;
658 } else {668 return a >> (info.bits - 1);
659 if (abs_shift_amt >= @typeInfo(T).int.bits) return 0;669 },
660 break :blk @as(Log2Int(T), @intCast(abs_shift_amt));670 .vector => |info| {
661 }671 const Child = info.child;
672 const child_info = @typeInfo(Child).int;
673 if (abs_shift_amt < child_info.bits) break :casted_shift_amt @as(
674 @Vector(info.len, Log2Int(Child)),
675 @splat(@as(Log2Int(Child), @intCast(abs_shift_amt))),
676 );
677 if (child_info.signedness == .unsigned or is_shl) return @splat(0);
678 return a >> @splat(child_info.bits - 1);
679 },
680 else => comptime unreachable,
662 };681 };
663682 return if (is_shl) a << casted_shift_amt else a >> casted_shift_amt;
664 if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).int.signedness == .signed) {
665 if (shift_amt < 0) {
666 return a << casted_shift_amt;
667 }
668 }
669
670 return a >> casted_shift_amt;
671}683}
672684
673test shr {685test shr {
...@@ -682,6 +694,11 @@ test shr {...@@ -682,6 +694,11 @@ test shr {
682 try testing.expect(shr(@Vector(1, u32), @Vector(1, u32){42}, @as(usize, 1))[0] == @as(u32, 42) >> 1);694 try testing.expect(shr(@Vector(1, u32), @Vector(1, u32){42}, @as(usize, 1))[0] == @as(u32, 42) >> 1);
683 try testing.expect(shr(@Vector(1, u32), @Vector(1, u32){42}, @as(isize, -1))[0] == @as(u32, 42) << 1);695 try testing.expect(shr(@Vector(1, u32), @Vector(1, u32){42}, @as(isize, -1))[0] == @as(u32, 42) << 1);
684 try testing.expect(shr(@Vector(1, u32), @Vector(1, u32){42}, 33)[0] == 0);696 try testing.expect(shr(@Vector(1, u32), @Vector(1, u32){42}, 33)[0] == 0);
697
698 try testing.expect(shr(i8, -1, -100) == 0);
699 try testing.expect(shr(i8, -1, 100) == -1);
700 try testing.expect(@reduce(.And, shr(@Vector(2, i8), .{ -1, 1 }, -100) == @Vector(2, i8){ 0, 0 }));
701 try testing.expect(@reduce(.And, shr(@Vector(2, i8), .{ -1, 1 }, 100) == @Vector(2, i8){ -1, 0 }));
685}702}
686703
687/// Rotates right. Only unsigned values can be rotated. Negative shift704/// Rotates right. Only unsigned values can be rotated. Negative shift
lib/std/math/big/int_test.zig-1
...@@ -2774,7 +2774,6 @@ test "bitNotWrap more than two limbs" {...@@ -2774,7 +2774,6 @@ test "bitNotWrap more than two limbs" {
2774 // This test requires int sizes greater than 128 bits.2774 // This test requires int sizes greater than 128 bits.
2775 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2775 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2776 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO2776 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2777 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2778 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2777 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2779 // LLVM: unexpected runtime library name: __umodei42778 // LLVM: unexpected runtime library name: __umodei4
2780 if (builtin.zig_backend == .stage2_llvm and comptime builtin.target.cpu.arch.isWasm()) return error.SkipZigTest; // TODO2779 if (builtin.zig_backend == .stage2_llvm and comptime builtin.target.cpu.arch.isWasm()) return error.SkipZigTest; // TODO
lib/std/math/float.zig+2-4
...@@ -4,8 +4,6 @@ const assert = std.debug.assert;...@@ -4,8 +4,6 @@ const assert = std.debug.assert;
4const expect = std.testing.expect;4const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;5const expectEqual = std.testing.expectEqual;
66
7pub const Sign = enum(u1) { positive, negative };
8
9pub fn FloatRepr(comptime Float: type) type {7pub fn FloatRepr(comptime Float: type) type {
10 const fractional_bits = floatFractionalBits(Float);8 const fractional_bits = floatFractionalBits(Float);
11 const exponent_bits = floatExponentBits(Float);9 const exponent_bits = floatExponentBits(Float);
...@@ -14,7 +12,7 @@ pub fn FloatRepr(comptime Float: type) type {...@@ -14,7 +12,7 @@ pub fn FloatRepr(comptime Float: type) type {
1412
15 mantissa: StoredMantissa,13 mantissa: StoredMantissa,
16 exponent: BiasedExponent,14 exponent: BiasedExponent,
17 sign: Sign,15 sign: std.math.Sign,
1816
19 pub const StoredMantissa = @Type(.{ .int = .{17 pub const StoredMantissa = @Type(.{ .int = .{
20 .signedness = .unsigned,18 .signedness = .unsigned,
...@@ -69,7 +67,7 @@ pub fn FloatRepr(comptime Float: type) type {...@@ -69,7 +67,7 @@ pub fn FloatRepr(comptime Float: type) type {
6967
70 /// This currently truncates denormal values, which needs to be fixed before this can be used to68 /// This currently truncates denormal values, which needs to be fixed before this can be used to
71 /// produce a rounded value.69 /// produce a rounded value.
72 pub fn reconstruct(normalized: Normalized, sign: Sign) Float {70 pub fn reconstruct(normalized: Normalized, sign: std.math.Sign) Float {
73 if (normalized.exponent > BiasedExponent.max_normal.unbias()) return @bitCast(Repr{71 if (normalized.exponent > BiasedExponent.max_normal.unbias()) return @bitCast(Repr{
74 .mantissa = 0,72 .mantissa = 0,
75 .exponent = .infinite,73 .exponent = .infinite,
lib/std/math/log10.zig-1
...@@ -132,7 +132,6 @@ inline fn less_than_5(x: u32) u32 {...@@ -132,7 +132,6 @@ inline fn less_than_5(x: u32) u32 {
132test log10_int {132test log10_int {
133 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO133 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO134 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
138 if (builtin.zig_backend == .stage2_llvm and comptime builtin.target.cpu.arch.isWasm()) return error.SkipZigTest; // TODO137 if (builtin.zig_backend == .stage2_llvm and comptime builtin.target.cpu.arch.isWasm()) return error.SkipZigTest; // TODO
lib/std/mem.zig+4-3
...@@ -676,6 +676,7 @@ test lessThan {...@@ -676,6 +676,7 @@ test lessThan {
676676
677const eqlBytes_allowed = switch (builtin.zig_backend) {677const eqlBytes_allowed = switch (builtin.zig_backend) {
678 // These backends don't support vectors yet.678 // These backends don't support vectors yet.
679 .stage2_aarch64,
679 .stage2_powerpc,680 .stage2_powerpc,
680 .stage2_riscv64,681 .stage2_riscv64,
681 => false,682 => false,
...@@ -4482,7 +4483,7 @@ pub fn doNotOptimizeAway(val: anytype) void {...@@ -4482,7 +4483,7 @@ pub fn doNotOptimizeAway(val: anytype) void {
4482 );4483 );
4483 asm volatile (""4484 asm volatile (""
4484 :4485 :
4485 : [val2] "r" (val2),4486 : [_] "r" (val2),
4486 );4487 );
4487 } else doNotOptimizeAway(&val);4488 } else doNotOptimizeAway(&val);
4488 },4489 },
...@@ -4490,7 +4491,7 @@ pub fn doNotOptimizeAway(val: anytype) void {...@@ -4490,7 +4491,7 @@ pub fn doNotOptimizeAway(val: anytype) void {
4490 if ((t.float.bits == 32 or t.float.bits == 64) and builtin.zig_backend != .stage2_c) {4491 if ((t.float.bits == 32 or t.float.bits == 64) and builtin.zig_backend != .stage2_c) {
4491 asm volatile (""4492 asm volatile (""
4492 :4493 :
4493 : [val] "rm" (val),4494 : [_] "rm" (val),
4494 );4495 );
4495 } else doNotOptimizeAway(&val);4496 } else doNotOptimizeAway(&val);
4496 },4497 },
...@@ -4500,7 +4501,7 @@ pub fn doNotOptimizeAway(val: anytype) void {...@@ -4500,7 +4501,7 @@ pub fn doNotOptimizeAway(val: anytype) void {
4500 } else {4501 } else {
4501 asm volatile (""4502 asm volatile (""
4502 :4503 :
4503 : [val] "m" (val),4504 : [_] "m" (val),
4504 : .{ .memory = true });4505 : .{ .memory = true });
4505 }4506 }
4506 },4507 },
lib/std/os/linux.zig-1
...@@ -503,7 +503,6 @@ pub var elf_aux_maybe: ?[*]std.elf.Auxv = null;...@@ -503,7 +503,6 @@ pub var elf_aux_maybe: ?[*]std.elf.Auxv = null;
503/// Whether an external or internal getauxval implementation is used.503/// Whether an external or internal getauxval implementation is used.
504const extern_getauxval = switch (builtin.zig_backend) {504const extern_getauxval = switch (builtin.zig_backend) {
505 // Calling extern functions is not yet supported with these backends505 // Calling extern functions is not yet supported with these backends
506 .stage2_aarch64,
507 .stage2_arm,506 .stage2_arm,
508 .stage2_powerpc,507 .stage2_powerpc,
509 .stage2_riscv64,508 .stage2_riscv64,
lib/std/start.zig+5-54
...@@ -101,17 +101,11 @@ comptime {...@@ -101,17 +101,11 @@ comptime {
101// Simplified start code for stage2 until it supports more language features ///101// Simplified start code for stage2 until it supports more language features ///
102102
103fn main2() callconv(.c) c_int {103fn main2() callconv(.c) c_int {
104 root.main();104 return callMain();
105 return 0;
106}105}
107106
108fn _start2() callconv(.withStackAlign(.c, 1)) noreturn {107fn _start2() callconv(.withStackAlign(.c, 1)) noreturn {
109 callMain2();108 std.posix.exit(callMain());
110}
111
112fn callMain2() noreturn {
113 root.main();
114 exit2(0);
115}109}
116110
117fn spirvMain2() callconv(.kernel) void {111fn spirvMain2() callconv(.kernel) void {
...@@ -119,51 +113,7 @@ fn spirvMain2() callconv(.kernel) void {...@@ -119,51 +113,7 @@ fn spirvMain2() callconv(.kernel) void {
119}113}
120114
121fn wWinMainCRTStartup2() callconv(.c) noreturn {115fn wWinMainCRTStartup2() callconv(.c) noreturn {
122 root.main();116 std.posix.exit(callMain());
123 exit2(0);
124}
125
126fn exit2(code: usize) noreturn {
127 switch (native_os) {
128 .linux => switch (builtin.cpu.arch) {
129 .x86_64 => {
130 asm volatile ("syscall"
131 :
132 : [number] "{rax}" (231),
133 [arg1] "{rdi}" (code),
134 : .{ .rcx = true, .r11 = true, .memory = true });
135 },
136 .arm => {
137 asm volatile ("svc #0"
138 :
139 : [number] "{r7}" (1),
140 [arg1] "{r0}" (code),
141 : .{ .memory = true });
142 },
143 .aarch64 => {
144 asm volatile ("svc #0"
145 :
146 : [number] "{x8}" (93),
147 [arg1] "{x0}" (code),
148 : .{ .memory = true });
149 },
150 .sparc64 => {
151 asm volatile ("ta 0x6d"
152 :
153 : [number] "{g1}" (1),
154 [arg1] "{o0}" (code),
155 : .{ .o0 = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o6 = true, .o7 = true, .memory = true });
156 },
157 else => @compileError("TODO"),
158 },
159 // exits(0)
160 .plan9 => std.os.plan9.exits(null),
161 .windows => {
162 std.os.windows.ntdll.RtlExitUserProcess(@truncate(code));
163 },
164 else => @compileError("TODO"),
165 }
166 unreachable;
167}117}
168118
169////////////////////////////////////////////////////////////////////////////////119////////////////////////////////////////////////////////////////////////////////
...@@ -676,10 +626,11 @@ pub inline fn callMain() u8 {...@@ -676,10 +626,11 @@ pub inline fn callMain() u8 {
676626
677 const result = root.main() catch |err| {627 const result = root.main() catch |err| {
678 switch (builtin.zig_backend) {628 switch (builtin.zig_backend) {
629 .stage2_aarch64,
679 .stage2_powerpc,630 .stage2_powerpc,
680 .stage2_riscv64,631 .stage2_riscv64,
681 => {632 => {
682 std.debug.print("error: failed with error\n", .{});633 _ = std.posix.write(std.posix.STDERR_FILENO, "error: failed with error\n") catch {};
683 return 1;634 return 1;
684 },635 },
685 else => {},636 else => {},
lib/std/tar.zig+51-83
...@@ -302,7 +302,7 @@ pub const FileKind = enum {...@@ -302,7 +302,7 @@ pub const FileKind = enum {
302302
303/// Iterator over entries in the tar file represented by reader.303/// Iterator over entries in the tar file represented by reader.
304pub const Iterator = struct {304pub const Iterator = struct {
305 reader: *std.io.Reader,305 reader: *std.Io.Reader,
306 diagnostics: ?*Diagnostics = null,306 diagnostics: ?*Diagnostics = null,
307307
308 // buffers for heeader and file attributes308 // buffers for heeader and file attributes
...@@ -328,7 +328,7 @@ pub const Iterator = struct {...@@ -328,7 +328,7 @@ pub const Iterator = struct {
328328
329 /// Iterates over files in tar archive.329 /// Iterates over files in tar archive.
330 /// `next` returns each file in tar archive.330 /// `next` returns each file in tar archive.
331 pub fn init(reader: *std.io.Reader, options: Options) Iterator {331 pub fn init(reader: *std.Io.Reader, options: Options) Iterator {
332 return .{332 return .{
333 .reader = reader,333 .reader = reader,
334 .diagnostics = options.diagnostics,334 .diagnostics = options.diagnostics,
...@@ -343,47 +343,6 @@ pub const Iterator = struct {...@@ -343,47 +343,6 @@ pub const Iterator = struct {
343 size: u64 = 0, // size of the file in bytes343 size: u64 = 0, // size of the file in bytes
344 mode: u32 = 0,344 mode: u32 = 0,
345 kind: FileKind = .file,345 kind: FileKind = .file,
346
347 unread_bytes: *u64,
348 parent_reader: *std.io.Reader,
349
350 pub fn reader(self: *File) std.io.Reader {
351 return .{
352 .context = self,
353 .vtable = &.{
354 .read = read,
355 .readVec = readVec,
356 .discard = discard,
357 },
358 };
359 }
360
361 fn read(context: ?*anyopaque, bw: *std.io.Writer, limit: std.io.Limit) std.io.Reader.StreamError!usize {
362 const file: *File = @ptrCast(@alignCast(context));
363 if (file.unread_bytes.* == 0) return error.EndOfStream;
364 const n = try file.parent_reader.read(bw, limit.min(.limited(file.unread_bytes.*)));
365 file.unread_bytes.* -= n;
366 return n;
367 }
368
369 fn readVec(context: ?*anyopaque, data: []const []u8) std.io.Reader.Error!usize {
370 const file: *File = @ptrCast(@alignCast(context));
371 if (file.unread_bytes.* == 0) return error.EndOfStream;
372 const n = try file.parent_reader.readVecLimit(data, .limited(file.unread_bytes.*));
373 file.unread_bytes.* -= n;
374 return n;
375 }
376
377 fn discard(context: ?*anyopaque, limit: std.io.Limit) std.io.Reader.Error!usize {
378 const file: *File = @ptrCast(@alignCast(context));
379 const n = limit.minInt(file.unread_bytes.*);
380 file.unread_bytes.* -= n;
381 return n;
382 }
383
384 pub fn streamRemaining(file: *File, out: *std.io.Writer) std.io.Reader.StreamRemainingError!usize {
385 return file.reader().streamRemaining(out);
386 }
387 };346 };
388347
389 fn readHeader(self: *Iterator) !?Header {348 fn readHeader(self: *Iterator) !?Header {
...@@ -401,7 +360,7 @@ pub const Iterator = struct {...@@ -401,7 +360,7 @@ pub const Iterator = struct {
401 fn readString(self: *Iterator, size: usize, buffer: []u8) ![]const u8 {360 fn readString(self: *Iterator, size: usize, buffer: []u8) ![]const u8 {
402 if (size > buffer.len) return error.TarInsufficientBuffer;361 if (size > buffer.len) return error.TarInsufficientBuffer;
403 const buf = buffer[0..size];362 const buf = buffer[0..size];
404 try self.reader.readSlice(buf);363 try self.reader.readSliceAll(buf);
405 return nullStr(buf);364 return nullStr(buf);
406 }365 }
407366
...@@ -409,8 +368,6 @@ pub const Iterator = struct {...@@ -409,8 +368,6 @@ pub const Iterator = struct {
409 return .{368 return .{
410 .name = self.file_name_buffer[0..0],369 .name = self.file_name_buffer[0..0],
411 .link_name = self.link_name_buffer[0..0],370 .link_name = self.link_name_buffer[0..0],
412 .parent_reader = self.reader,
413 .unread_bytes = &self.unread_file_bytes,
414 };371 };
415 }372 }
416373
...@@ -516,11 +473,16 @@ pub const Iterator = struct {...@@ -516,11 +473,16 @@ pub const Iterator = struct {
516 return null;473 return null;
517 }474 }
518475
476 pub fn streamRemaining(it: *Iterator, file: File, w: *std.Io.Writer) std.Io.Reader.StreamError!void {
477 try it.reader.streamExact64(w, file.size);
478 it.unread_file_bytes = 0;
479 }
480
519 fn skipGnuSparseExtendedHeaders(self: *Iterator, header: Header) !void {481 fn skipGnuSparseExtendedHeaders(self: *Iterator, header: Header) !void {
520 var is_extended = header.bytes[482] > 0;482 var is_extended = header.bytes[482] > 0;
521 while (is_extended) {483 while (is_extended) {
522 var buf: [Header.SIZE]u8 = undefined;484 var buf: [Header.SIZE]u8 = undefined;
523 try self.reader.readSlice(&buf);485 try self.reader.readSliceAll(&buf);
524 is_extended = buf[504] > 0;486 is_extended = buf[504] > 0;
525 }487 }
526 }488 }
...@@ -537,14 +499,14 @@ const pax_max_size_attr_len = 64;...@@ -537,14 +499,14 @@ const pax_max_size_attr_len = 64;
537499
538pub const PaxIterator = struct {500pub const PaxIterator = struct {
539 size: usize, // cumulative size of all pax attributes501 size: usize, // cumulative size of all pax attributes
540 reader: *std.io.Reader,502 reader: *std.Io.Reader,
541503
542 const Self = @This();504 const Self = @This();
543505
544 const Attribute = struct {506 const Attribute = struct {
545 kind: PaxAttributeKind,507 kind: PaxAttributeKind,
546 len: usize, // length of the attribute value508 len: usize, // length of the attribute value
547 reader: *std.io.Reader, // reader positioned at value start509 reader: *std.Io.Reader, // reader positioned at value start
548510
549 // Copies pax attribute value into destination buffer.511 // Copies pax attribute value into destination buffer.
550 // Must be called with destination buffer of size at least Attribute.len.512 // Must be called with destination buffer of size at least Attribute.len.
...@@ -611,22 +573,23 @@ pub const PaxIterator = struct {...@@ -611,22 +573,23 @@ pub const PaxIterator = struct {
611 }573 }
612574
613 // Checks that each record ends with new line.575 // Checks that each record ends with new line.
614 fn validateAttributeEnding(reader: *std.io.Reader) !void {576 fn validateAttributeEnding(reader: *std.Io.Reader) !void {
615 if (try reader.takeByte() != '\n') return error.PaxInvalidAttributeEnd;577 if (try reader.takeByte() != '\n') return error.PaxInvalidAttributeEnd;
616 }578 }
617};579};
618580
619/// Saves tar file content to the file systems.581/// Saves tar file content to the file systems.
620pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.io.Reader, options: PipeOptions) !void {582pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.Io.Reader, options: PipeOptions) !void {
621 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;583 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
622 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;584 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
623 var iter: Iterator = .init(reader, .{585 var file_contents_buffer: [1024]u8 = undefined;
586 var it: Iterator = .init(reader, .{
624 .file_name_buffer = &file_name_buffer,587 .file_name_buffer = &file_name_buffer,
625 .link_name_buffer = &link_name_buffer,588 .link_name_buffer = &link_name_buffer,
626 .diagnostics = options.diagnostics,589 .diagnostics = options.diagnostics,
627 });590 });
628591
629 while (try iter.next()) |file| {592 while (try it.next()) |file| {
630 const file_name = stripComponents(file.name, options.strip_components);593 const file_name = stripComponents(file.name, options.strip_components);
631 if (file_name.len == 0 and file.kind != .directory) {594 if (file_name.len == 0 and file.kind != .directory) {
632 const d = options.diagnostics orelse return error.TarComponentsOutsideStrippedPrefix;595 const d = options.diagnostics orelse return error.TarComponentsOutsideStrippedPrefix;
...@@ -648,7 +611,9 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.io.Reader, options: PipeOp...@@ -648,7 +611,9 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: *std.io.Reader, options: PipeOp
648 .file => {611 .file => {
649 if (createDirAndFile(dir, file_name, fileMode(file.mode, options))) |fs_file| {612 if (createDirAndFile(dir, file_name, fileMode(file.mode, options))) |fs_file| {
650 defer fs_file.close();613 defer fs_file.close();
651 try file.writeAll(fs_file);614 var file_writer = fs_file.writer(&file_contents_buffer);
615 try it.streamRemaining(file, &file_writer.interface);
616 try file_writer.interface.flush();
652 } else |err| {617 } else |err| {
653 const d = options.diagnostics orelse return err;618 const d = options.diagnostics orelse return err;
654 try d.errors.append(d.allocator, .{ .unable_to_create_file = .{619 try d.errors.append(d.allocator, .{ .unable_to_create_file = .{
...@@ -818,11 +783,14 @@ test PaxIterator {...@@ -818,11 +783,14 @@ test PaxIterator {
818 var buffer: [1024]u8 = undefined;783 var buffer: [1024]u8 = undefined;
819784
820 outer: for (cases) |case| {785 outer: for (cases) |case| {
821 var br: std.io.Reader = .fixed(case.data);786 var reader: std.Io.Reader = .fixed(case.data);
822 var iter: PaxIterator = .init(&br, case.data.len);787 var it: PaxIterator = .{
788 .size = case.data.len,
789 .reader = &reader,
790 };
823791
824 var i: usize = 0;792 var i: usize = 0;
825 while (iter.next() catch |err| {793 while (it.next() catch |err| {
826 if (case.err) |e| {794 if (case.err) |e| {
827 try testing.expectEqual(e, err);795 try testing.expectEqual(e, err);
828 continue;796 continue;
...@@ -845,12 +813,6 @@ test PaxIterator {...@@ -845,12 +813,6 @@ test PaxIterator {
845 }813 }
846}814}
847815
848test {
849 _ = @import("tar/test.zig");
850 _ = Writer;
851 _ = Diagnostics;
852}
853
854test "header parse size" {816test "header parse size" {
855 const cases = [_]struct {817 const cases = [_]struct {
856 in: []const u8,818 in: []const u8,
...@@ -954,19 +916,19 @@ test Iterator {...@@ -954,19 +916,19 @@ test Iterator {
954 // example/empty/916 // example/empty/
955917
956 const data = @embedFile("tar/testdata/example.tar");918 const data = @embedFile("tar/testdata/example.tar");
957 var br: std.io.Reader = .fixed(data);919 var reader: std.Io.Reader = .fixed(data);
958920
959 // User provided buffers to the iterator921 // User provided buffers to the iterator
960 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;922 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
961 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;923 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
962 // Create iterator924 // Create iterator
963 var iter: Iterator = .init(&br, .{925 var it: Iterator = .init(&reader, .{
964 .file_name_buffer = &file_name_buffer,926 .file_name_buffer = &file_name_buffer,
965 .link_name_buffer = &link_name_buffer,927 .link_name_buffer = &link_name_buffer,
966 });928 });
967 // Iterate over files in example.tar929 // Iterate over files in example.tar
968 var file_no: usize = 0;930 var file_no: usize = 0;
969 while (try iter.next()) |file| : (file_no += 1) {931 while (try it.next()) |file| : (file_no += 1) {
970 switch (file.kind) {932 switch (file.kind) {
971 .directory => {933 .directory => {
972 switch (file_no) {934 switch (file_no) {
...@@ -979,10 +941,10 @@ test Iterator {...@@ -979,10 +941,10 @@ test Iterator {
979 },941 },
980 .file => {942 .file => {
981 try testing.expectEqualStrings("example/a/file", file.name);943 try testing.expectEqualStrings("example/a/file", file.name);
982 // Read file content
983 var buf: [16]u8 = undefined;944 var buf: [16]u8 = undefined;
984 const n = try file.reader().readAll(&buf);945 var w: std.Io.Writer = .fixed(&buf);
985 try testing.expectEqualStrings("content\n", buf[0..n]);946 try it.streamRemaining(file, &w);
947 try testing.expectEqualStrings("content\n", w.buffered());
986 },948 },
987 .sym_link => {949 .sym_link => {
988 try testing.expectEqualStrings("example/b/symlink", file.name);950 try testing.expectEqualStrings("example/b/symlink", file.name);
...@@ -1013,14 +975,14 @@ test pipeToFileSystem {...@@ -1013,14 +975,14 @@ test pipeToFileSystem {
1013 // example/empty/975 // example/empty/
1014976
1015 const data = @embedFile("tar/testdata/example.tar");977 const data = @embedFile("tar/testdata/example.tar");
1016 var br: std.io.Reader = .fixed(data);978 var reader: std.Io.Reader = .fixed(data);
1017979
1018 var tmp = testing.tmpDir(.{ .no_follow = true });980 var tmp = testing.tmpDir(.{ .no_follow = true });
1019 defer tmp.cleanup();981 defer tmp.cleanup();
1020 const dir = tmp.dir;982 const dir = tmp.dir;
1021983
1022 // Save tar from reader to the file system `dir`984 // Save tar from reader to the file system `dir`
1023 pipeToFileSystem(dir, &br, .{985 pipeToFileSystem(dir, &reader, .{
1024 .mode_mode = .ignore,986 .mode_mode = .ignore,
1025 .strip_components = 1,987 .strip_components = 1,
1026 .exclude_empty_directories = true,988 .exclude_empty_directories = true,
...@@ -1044,7 +1006,7 @@ test pipeToFileSystem {...@@ -1044,7 +1006,7 @@ test pipeToFileSystem {
10441006
1045test "pipeToFileSystem root_dir" {1007test "pipeToFileSystem root_dir" {
1046 const data = @embedFile("tar/testdata/example.tar");1008 const data = @embedFile("tar/testdata/example.tar");
1047 var br: std.io.Reader = .fixed(data);1009 var reader: std.Io.Reader = .fixed(data);
10481010
1049 // with strip_components = 11011 // with strip_components = 1
1050 {1012 {
...@@ -1053,7 +1015,7 @@ test "pipeToFileSystem root_dir" {...@@ -1053,7 +1015,7 @@ test "pipeToFileSystem root_dir" {
1053 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1015 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1054 defer diagnostics.deinit();1016 defer diagnostics.deinit();
10551017
1056 pipeToFileSystem(tmp.dir, &br, .{1018 pipeToFileSystem(tmp.dir, &reader, .{
1057 .strip_components = 1,1019 .strip_components = 1,
1058 .diagnostics = &diagnostics,1020 .diagnostics = &diagnostics,
1059 }) catch |err| {1021 }) catch |err| {
...@@ -1069,13 +1031,13 @@ test "pipeToFileSystem root_dir" {...@@ -1069,13 +1031,13 @@ test "pipeToFileSystem root_dir" {
10691031
1070 // with strip_components = 01032 // with strip_components = 0
1071 {1033 {
1072 br = .fixed(data);1034 reader = .fixed(data);
1073 var tmp = testing.tmpDir(.{ .no_follow = true });1035 var tmp = testing.tmpDir(.{ .no_follow = true });
1074 defer tmp.cleanup();1036 defer tmp.cleanup();
1075 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1037 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1076 defer diagnostics.deinit();1038 defer diagnostics.deinit();
10771039
1078 pipeToFileSystem(tmp.dir, &br, .{1040 pipeToFileSystem(tmp.dir, &reader, .{
1079 .strip_components = 0,1041 .strip_components = 0,
1080 .diagnostics = &diagnostics,1042 .diagnostics = &diagnostics,
1081 }) catch |err| {1043 }) catch |err| {
...@@ -1092,42 +1054,42 @@ test "pipeToFileSystem root_dir" {...@@ -1092,42 +1054,42 @@ test "pipeToFileSystem root_dir" {
10921054
1093test "findRoot with single file archive" {1055test "findRoot with single file archive" {
1094 const data = @embedFile("tar/testdata/22752.tar");1056 const data = @embedFile("tar/testdata/22752.tar");
1095 var br: std.io.Reader = .fixed(data);1057 var reader: std.Io.Reader = .fixed(data);
10961058
1097 var tmp = testing.tmpDir(.{});1059 var tmp = testing.tmpDir(.{});
1098 defer tmp.cleanup();1060 defer tmp.cleanup();
10991061
1100 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1062 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1101 defer diagnostics.deinit();1063 defer diagnostics.deinit();
1102 try pipeToFileSystem(tmp.dir, &br, .{ .diagnostics = &diagnostics });1064 try pipeToFileSystem(tmp.dir, &reader, .{ .diagnostics = &diagnostics });
11031065
1104 try testing.expectEqualStrings("", diagnostics.root_dir);1066 try testing.expectEqualStrings("", diagnostics.root_dir);
1105}1067}
11061068
1107test "findRoot without explicit root dir" {1069test "findRoot without explicit root dir" {
1108 const data = @embedFile("tar/testdata/19820.tar");1070 const data = @embedFile("tar/testdata/19820.tar");
1109 var br: std.io.Reader = .fixed(data);1071 var reader: std.Io.Reader = .fixed(data);
11101072
1111 var tmp = testing.tmpDir(.{});1073 var tmp = testing.tmpDir(.{});
1112 defer tmp.cleanup();1074 defer tmp.cleanup();
11131075
1114 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1076 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1115 defer diagnostics.deinit();1077 defer diagnostics.deinit();
1116 try pipeToFileSystem(tmp.dir, &br, .{ .diagnostics = &diagnostics });1078 try pipeToFileSystem(tmp.dir, &reader, .{ .diagnostics = &diagnostics });
11171079
1118 try testing.expectEqualStrings("root", diagnostics.root_dir);1080 try testing.expectEqualStrings("root", diagnostics.root_dir);
1119}1081}
11201082
1121test "pipeToFileSystem strip_components" {1083test "pipeToFileSystem strip_components" {
1122 const data = @embedFile("tar/testdata/example.tar");1084 const data = @embedFile("tar/testdata/example.tar");
1123 var br: std.io.Reader = .fixed(data);1085 var reader: std.Io.Reader = .fixed(data);
11241086
1125 var tmp = testing.tmpDir(.{ .no_follow = true });1087 var tmp = testing.tmpDir(.{ .no_follow = true });
1126 defer tmp.cleanup();1088 defer tmp.cleanup();
1127 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };1089 var diagnostics: Diagnostics = .{ .allocator = testing.allocator };
1128 defer diagnostics.deinit();1090 defer diagnostics.deinit();
11291091
1130 pipeToFileSystem(tmp.dir, &br, .{1092 pipeToFileSystem(tmp.dir, &reader, .{
1131 .strip_components = 3,1093 .strip_components = 3,
1132 .diagnostics = &diagnostics,1094 .diagnostics = &diagnostics,
1133 }) catch |err| {1095 }) catch |err| {
...@@ -1181,12 +1143,12 @@ test "executable bit" {...@@ -1181,12 +1143,12 @@ test "executable bit" {
1181 const data = @embedFile("tar/testdata/example.tar");1143 const data = @embedFile("tar/testdata/example.tar");
11821144
1183 for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| {1145 for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| {
1184 var br: std.io.Reader = .fixed(data);1146 var reader: std.Io.Reader = .fixed(data);
11851147
1186 var tmp = testing.tmpDir(.{ .no_follow = true });1148 var tmp = testing.tmpDir(.{ .no_follow = true });
1187 //defer tmp.cleanup();1149 //defer tmp.cleanup();
11881150
1189 pipeToFileSystem(tmp.dir, &br, .{1151 pipeToFileSystem(tmp.dir, &reader, .{
1190 .strip_components = 1,1152 .strip_components = 1,
1191 .exclude_empty_directories = true,1153 .exclude_empty_directories = true,
1192 .mode_mode = opt,1154 .mode_mode = opt,
...@@ -1212,3 +1174,9 @@ test "executable bit" {...@@ -1212,3 +1174,9 @@ test "executable bit" {
1212 }1174 }
1213 }1175 }
1214}1176}
1177
1178test {
1179 _ = @import("tar/test.zig");
1180 _ = Writer;
1181 _ = Diagnostics;
1182}
lib/std/tar/Writer.zig+56-93
...@@ -14,7 +14,7 @@ pub const Options = struct {...@@ -14,7 +14,7 @@ pub const Options = struct {
14 mtime: u64 = 0,14 mtime: u64 = 0,
15};15};
1616
17underlying_writer: *std.io.Writer,17underlying_writer: *std.Io.Writer,
18prefix: []const u8 = "",18prefix: []const u8 = "",
19mtime_now: u64 = 0,19mtime_now: u64 = 0,
2020
...@@ -36,48 +36,47 @@ pub fn writeDir(w: *Writer, sub_path: []const u8, options: Options) Error!void {...@@ -36,48 +36,47 @@ pub fn writeDir(w: *Writer, sub_path: []const u8, options: Options) Error!void {
36 try w.writeHeader(.directory, sub_path, "", 0, options);36 try w.writeHeader(.directory, sub_path, "", 0, options);
37}37}
3838
39pub const WriteFileError = std.io.Writer.FileError || Error;39pub const WriteFileError = std.Io.Writer.FileError || Error || std.fs.File.GetEndPosError;
4040
41pub fn writeFile(41pub fn writeFile(
42 w: *Writer,42 w: *Writer,
43 sub_path: []const u8,43 sub_path: []const u8,
44 file: std.fs.File,44 file_reader: *std.fs.File.Reader,
45 stat: std.fs.File.Stat,45 stat_mtime: i128,
46) WriteFileError!void {46) WriteFileError!void {
47 const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s));47 const size = try file_reader.getSize();
48 const mtime: u64 = @intCast(@divFloor(stat_mtime, std.time.ns_per_s));
4849
49 var header: Header = .{};50 var header: Header = .{};
50 try w.setPath(&header, sub_path);51 try w.setPath(&header, sub_path);
51 try header.setSize(stat.size);52 try header.setSize(size);
52 try header.setMtime(mtime);53 try header.setMtime(mtime);
53 try header.updateChecksum();54 try header.updateChecksum();
5455
55 var vec: [1][]const u8 = .{@ptrCast((&header)[0..1])};56 try w.underlying_writer.writeAll(@ptrCast((&header)[0..1]));
56 try w.underlying_writer.writeFileAll(file, .{57 _ = try w.underlying_writer.sendFileAll(file_reader, .unlimited);
57 .limit = .limited(stat.size),58 try w.writePadding64(size);
58 .headers_and_trailers = &vec,
59 .headers_len = 1,
60 });
61 try w.writePadding(stat.size);
62}59}
6360
61pub const WriteFileStreamError = Error || std.Io.Reader.StreamError;
62
64/// Writes file reading file content from `reader`. Reads exactly `size` bytes63/// Writes file reading file content from `reader`. Reads exactly `size` bytes
65/// from `reader`, or returns `error.EndOfStream`.64/// from `reader`, or returns `error.EndOfStream`.
66pub fn writeFileStream(65pub fn writeFileStream(
67 w: *Writer,66 w: *Writer,
68 sub_path: []const u8,67 sub_path: []const u8,
69 size: usize,68 size: u64,
70 reader: *std.io.Reader,69 reader: *std.Io.Reader,
71 options: Options,70 options: Options,
72) std.io.Reader.StreamError!void {71) WriteFileStreamError!void {
73 try w.writeHeader(.regular, sub_path, "", @intCast(size), options);72 try w.writeHeader(.regular, sub_path, "", size, options);
74 try reader.readAll(w.underlying_writer, .limited(size));73 try reader.streamExact64(w.underlying_writer, size);
75 try w.writePadding(size);74 try w.writePadding64(size);
76}75}
7776
78/// Writes file using bytes buffer `content` for size and file content.77/// Writes file using bytes buffer `content` for size and file content.
79pub fn writeFileBytes(w: *Writer, sub_path: []const u8, content: []const u8, options: Options) Error!void {78pub fn writeFileBytes(w: *Writer, sub_path: []const u8, content: []const u8, options: Options) Error!void {
80 try w.writeHeader(.regular, sub_path, "", @intCast(content.len), options);79 try w.writeHeader(.regular, sub_path, "", content.len, options);
81 try w.underlying_writer.writeAll(content);80 try w.underlying_writer.writeAll(content);
82 try w.writePadding(content.len);81 try w.writePadding(content.len);
83}82}
...@@ -86,30 +85,6 @@ pub fn writeLink(w: *Writer, sub_path: []const u8, link_name: []const u8, option...@@ -86,30 +85,6 @@ pub fn writeLink(w: *Writer, sub_path: []const u8, link_name: []const u8, option
86 try w.writeHeader(.symbolic_link, sub_path, link_name, 0, options);85 try w.writeHeader(.symbolic_link, sub_path, link_name, 0, options);
87}86}
8887
89/// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and
90/// default for entry mode .
91pub fn writeEntry(w: *Writer, entry: std.fs.Dir.Walker.Entry) Error!void {
92 switch (entry.kind) {
93 .directory => {
94 try w.writeDir(entry.path, .{ .mtime = try entryMtime(entry) });
95 },
96 .file => {
97 var file = try entry.dir.openFile(entry.basename, .{});
98 defer file.close();
99 const stat = try file.stat();
100 try w.writeFile(entry.path, file, stat);
101 },
102 .sym_link => {
103 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
104 const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer);
105 try w.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) });
106 },
107 else => {
108 return error.UnsupportedWalkerEntryKind;
109 },
110 }
111}
112
113fn writeHeader(88fn writeHeader(
114 w: *Writer,89 w: *Writer,
115 typeflag: Header.FileType,90 typeflag: Header.FileType,
...@@ -121,7 +96,7 @@ fn writeHeader(...@@ -121,7 +96,7 @@ fn writeHeader(
121 var header = Header.init(typeflag);96 var header = Header.init(typeflag);
122 try w.setPath(&header, sub_path);97 try w.setPath(&header, sub_path);
123 try header.setSize(size);98 try header.setSize(size);
124 try header.setMtime(if (options.mtime != 0) options.mtime else w.mtimeNow());99 try header.setMtime(options.mtime);
125 if (options.mode != 0)100 if (options.mode != 0)
126 try header.setMode(options.mode);101 try header.setMode(options.mode);
127 if (typeflag == .symbolic_link)102 if (typeflag == .symbolic_link)
...@@ -132,17 +107,6 @@ fn writeHeader(...@@ -132,17 +107,6 @@ fn writeHeader(
132 try header.write(w.underlying_writer);107 try header.write(w.underlying_writer);
133}108}
134109
135fn mtimeNow(w: *Writer) u64 {
136 if (w.mtime_now == 0)
137 w.mtime_now = @intCast(std.time.timestamp());
138 return w.mtime_now;
139}
140
141fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 {
142 const stat = try entry.dir.statFile(entry.basename);
143 return @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
144}
145
146/// Writes path in posix header, if don't fit (in name+prefix; 100+155110/// Writes path in posix header, if don't fit (in name+prefix; 100+155
147/// bytes) writes it in gnu extended header.111/// bytes) writes it in gnu extended header.
148fn setPath(w: *Writer, header: *Header, sub_path: []const u8) Error!void {112fn setPath(w: *Writer, header: *Header, sub_path: []const u8) Error!void {
...@@ -172,8 +136,15 @@ fn writeExtendedHeader(w: *Writer, typeflag: Header.FileType, buffers: []const [...@@ -172,8 +136,15 @@ fn writeExtendedHeader(w: *Writer, typeflag: Header.FileType, buffers: []const [
172 try w.writePadding(len);136 try w.writePadding(len);
173}137}
174138
175fn writePadding(w: *Writer, bytes: usize) std.io.Writer.Error!void {139fn writePadding(w: *Writer, bytes: usize) std.Io.Writer.Error!void {
176 const pos = bytes % block_size;140 return writePaddingPos(w, bytes % block_size);
141}
142
143fn writePadding64(w: *Writer, bytes: u64) std.Io.Writer.Error!void {
144 return writePaddingPos(w, @intCast(bytes % block_size));
145}
146
147fn writePaddingPos(w: *Writer, pos: usize) std.Io.Writer.Error!void {
177 if (pos == 0) return;148 if (pos == 0) return;
178 try w.underlying_writer.splatByteAll(0, block_size - pos);149 try w.underlying_writer.splatByteAll(0, block_size - pos);
179}150}
...@@ -182,8 +153,8 @@ fn writePadding(w: *Writer, bytes: usize) std.io.Writer.Error!void {...@@ -182,8 +153,8 @@ fn writePadding(w: *Writer, bytes: usize) std.io.Writer.Error!void {
182/// "reasonable system must not assume that such a block exists when reading an153/// "reasonable system must not assume that such a block exists when reading an
183/// archive". Therefore, the Zig standard library recommends to not call this154/// archive". Therefore, the Zig standard library recommends to not call this
184/// function.155/// function.
185pub fn finishPedantically(w: *Writer) std.io.Writer.Error!void {156pub fn finishPedantically(w: *Writer) std.Io.Writer.Error!void {
186 try w.underlying_writer.writeSplatAll(&.{&.{0}}, block_size * 2);157 try w.underlying_writer.splatByteAll(0, block_size * 2);
187}158}
188159
189/// A struct that is exactly 512 bytes and matches tar file format. This is160/// A struct that is exactly 512 bytes and matches tar file format. This is
...@@ -277,7 +248,7 @@ pub const Header = extern struct {...@@ -277,7 +248,7 @@ pub const Header = extern struct {
277 try octal(&w.checksum, checksum);248 try octal(&w.checksum, checksum);
278 }249 }
279250
280 pub fn write(h: *Header, bw: *std.io.Writer) error{ OctalOverflow, WriteFailed }!void {251 pub fn write(h: *Header, bw: *std.Io.Writer) error{ OctalOverflow, WriteFailed }!void {
281 try h.updateChecksum();252 try h.updateChecksum();
282 try bw.writeAll(std.mem.asBytes(h));253 try bw.writeAll(std.mem.asBytes(h));
283 }254 }
...@@ -375,8 +346,8 @@ pub const Header = extern struct {...@@ -375,8 +346,8 @@ pub const Header = extern struct {
375 for (cases) |case| {346 for (cases) |case| {
376 var header = Header.init(.regular);347 var header = Header.init(.regular);
377 try header.setPath(case.in[0], case.in[1]);348 try header.setPath(case.in[0], case.in[1]);
378 try testing.expectEqualStrings(case.out[0], str(&header.prefix));349 try testing.expectEqualStrings(case.out[0], std.mem.sliceTo(&header.prefix, 0));
379 try testing.expectEqualStrings(case.out[1], str(&header.name));350 try testing.expectEqualStrings(case.out[1], std.mem.sliceTo(&header.name, 0));
380 }351 }
381352
382 const error_cases = [_]struct {353 const error_cases = [_]struct {
...@@ -399,14 +370,6 @@ pub const Header = extern struct {...@@ -399,14 +370,6 @@ pub const Header = extern struct {
399 );370 );
400 }371 }
401 }372 }
402
403 // Breaks string on first null character.
404 fn str(s: []const u8) []const u8 {
405 for (s, 0..) |c, i| {
406 if (c == 0) return s[0..i];
407 }
408 return s;
409 }
410};373};
411374
412test {375test {
...@@ -433,67 +396,67 @@ test "write files" {...@@ -433,67 +396,67 @@ test "write files" {
433 {396 {
434 const root = "root";397 const root = "root";
435398
436 var output: std.io.Writer.Allocating = .init(testing.allocator);399 var output: std.Io.Writer.Allocating = .init(testing.allocator);
437 var wrt: Writer = .{ .underlying_writer = &output.interface };400 var w: Writer = .{ .underlying_writer = &output.writer };
438 defer output.deinit();401 defer output.deinit();
439 try wrt.setRoot(root);402 try w.setRoot(root);
440 for (files) |file|403 for (files) |file|
441 try wrt.writeFileBytes(file.path, file.content, .{});404 try w.writeFileBytes(file.path, file.content, .{});
442405
443 var input: std.io.Reader = .fixed(output.getWritten());406 var input: std.Io.Reader = .fixed(output.getWritten());
444 var iter = std.tar.iterator(&input, .{407 var it: std.tar.Iterator = .init(&input, .{
445 .file_name_buffer = &file_name_buffer,408 .file_name_buffer = &file_name_buffer,
446 .link_name_buffer = &link_name_buffer,409 .link_name_buffer = &link_name_buffer,
447 });410 });
448411
449 // first entry is directory with prefix412 // first entry is directory with prefix
450 {413 {
451 const actual = (try iter.next()).?;414 const actual = (try it.next()).?;
452 try testing.expectEqualStrings(root, actual.name);415 try testing.expectEqualStrings(root, actual.name);
453 try testing.expectEqual(std.tar.FileKind.directory, actual.kind);416 try testing.expectEqual(std.tar.FileKind.directory, actual.kind);
454 }417 }
455418
456 var i: usize = 0;419 var i: usize = 0;
457 while (try iter.next()) |actual| {420 while (try it.next()) |actual| {
458 defer i += 1;421 defer i += 1;
459 const expected = files[i];422 const expected = files[i];
460 try testing.expectEqualStrings(root, actual.name[0..root.len]);423 try testing.expectEqualStrings(root, actual.name[0..root.len]);
461 try testing.expectEqual('/', actual.name[root.len..][0]);424 try testing.expectEqual('/', actual.name[root.len..][0]);
462 try testing.expectEqualStrings(expected.path, actual.name[root.len + 1 ..]);425 try testing.expectEqualStrings(expected.path, actual.name[root.len + 1 ..]);
463426
464 var content = std.ArrayList(u8).init(testing.allocator);427 var content: std.Io.Writer.Allocating = .init(testing.allocator);
465 defer content.deinit();428 defer content.deinit();
466 try actual.writeAll(content.writer());429 try it.streamRemaining(actual, &content.writer);
467 try testing.expectEqualSlices(u8, expected.content, content.items);430 try testing.expectEqualSlices(u8, expected.content, content.getWritten());
468 }431 }
469 }432 }
470 // without root433 // without root
471 {434 {
472 var output: std.io.Writer.Allocating = .init(testing.allocator);435 var output: std.Io.Writer.Allocating = .init(testing.allocator);
473 var wrt: Writer = .{ .underlying_writer = &output.interface };436 var w: Writer = .{ .underlying_writer = &output.writer };
474 defer output.deinit();437 defer output.deinit();
475 for (files) |file| {438 for (files) |file| {
476 var content: std.io.Reader = .fixed(file.content);439 var content: std.Io.Reader = .fixed(file.content);
477 try wrt.writeFileStream(file.path, file.content.len, &content, .{});440 try w.writeFileStream(file.path, file.content.len, &content, .{});
478 }441 }
479442
480 var input: std.io.Reader = .fixed(output.getWritten());443 var input: std.Io.Reader = .fixed(output.getWritten());
481 var iter = std.tar.iterator(&input, .{444 var it: std.tar.Iterator = .init(&input, .{
482 .file_name_buffer = &file_name_buffer,445 .file_name_buffer = &file_name_buffer,
483 .link_name_buffer = &link_name_buffer,446 .link_name_buffer = &link_name_buffer,
484 });447 });
485448
486 var i: usize = 0;449 var i: usize = 0;
487 while (try iter.next()) |actual| {450 while (try it.next()) |actual| {
488 defer i += 1;451 defer i += 1;
489 const expected = files[i];452 const expected = files[i];
490 try testing.expectEqualStrings(expected.path, actual.name);453 try testing.expectEqualStrings(expected.path, actual.name);
491454
492 var content = std.ArrayList(u8).init(testing.allocator);455 var content: std.Io.Writer.Allocating = .init(testing.allocator);
493 defer content.deinit();456 defer content.deinit();
494 try actual.writeAll(content.writer());457 try it.streamRemaining(actual, &content.writer);
495 try testing.expectEqualSlices(u8, expected.content, content.items);458 try testing.expectEqualSlices(u8, expected.content, content.getWritten());
496 }459 }
497 try wrt.finish();460 try w.finishPedantically();
498 }461 }
499}462}
lib/std/tar/test.zig+166-170
...@@ -18,31 +18,72 @@ const Case = struct {...@@ -18,31 +18,72 @@ const Case = struct {
18 err: ?anyerror = null, // parsing should fail with this error18 err: ?anyerror = null, // parsing should fail with this error
19};19};
2020
21const cases = [_]Case{21const gnu_case: Case = .{
22 .{22 .data = @embedFile("testdata/gnu.tar"),
23 .data = @embedFile("testdata/gnu.tar"),23 .files = &[_]Case.File{
24 .files = &[_]Case.File{24 .{
25 .{25 .name = "small.txt",
26 .name = "small.txt",26 .size = 5,
27 .size = 5,27 .mode = 0o640,
28 .mode = 0o640,
29 },
30 .{
31 .name = "small2.txt",
32 .size = 11,
33 .mode = 0o640,
34 },
35 },28 },
36 .chksums = &[_][]const u8{29 .{
37 "e38b27eaccb4391bdec553a7f3ae6b2f",30 .name = "small2.txt",
38 "c65bd2e50a56a2138bf1716f2fd56fe9",31 .size = 11,
32 .mode = 0o640,
33 },
34 },
35 .chksums = &[_][]const u8{
36 "e38b27eaccb4391bdec553a7f3ae6b2f",
37 "c65bd2e50a56a2138bf1716f2fd56fe9",
38 },
39};
40
41const gnu_multi_headers_case: Case = .{
42 .data = @embedFile("testdata/gnu-multi-hdrs.tar"),
43 .files = &[_]Case.File{
44 .{
45 .name = "GNU2/GNU2/long-path-name",
46 .link_name = "GNU4/GNU4/long-linkpath-name",
47 .kind = .sym_link,
39 },48 },
40 },49 },
41 .{50};
51
52const trailing_slash_case: Case = .{
53 .data = @embedFile("testdata/trailing-slash.tar"),
54 .files = &[_]Case.File{
55 .{
56 .name = "123456789/" ** 30,
57 .kind = .directory,
58 },
59 },
60};
61
62const writer_big_long_case: Case = .{
63 // Size in gnu extended format, and name in pax attribute.
64 .data = @embedFile("testdata/writer-big-long.tar"),
65 .files = &[_]Case.File{
66 .{
67 .name = "longname/" ** 15 ++ "16gig.txt",
68 .size = 16 * 1024 * 1024 * 1024,
69 .mode = 0o644,
70 .truncated = true,
71 },
72 },
73};
74
75const fuzz1_case: Case = .{
76 .data = @embedFile("testdata/fuzz1.tar"),
77 .err = error.TarInsufficientBuffer,
78};
79
80test "run test cases" {
81 try testCase(gnu_case);
82 try testCase(.{
42 .data = @embedFile("testdata/sparse-formats.tar"),83 .data = @embedFile("testdata/sparse-formats.tar"),
43 .err = error.TarUnsupportedHeader,84 .err = error.TarUnsupportedHeader,
44 },85 });
45 .{86 try testCase(.{
46 .data = @embedFile("testdata/star.tar"),87 .data = @embedFile("testdata/star.tar"),
47 .files = &[_]Case.File{88 .files = &[_]Case.File{
48 .{89 .{
...@@ -60,8 +101,8 @@ const cases = [_]Case{...@@ -60,8 +101,8 @@ const cases = [_]Case{
60 "e38b27eaccb4391bdec553a7f3ae6b2f",101 "e38b27eaccb4391bdec553a7f3ae6b2f",
61 "c65bd2e50a56a2138bf1716f2fd56fe9",102 "c65bd2e50a56a2138bf1716f2fd56fe9",
62 },103 },
63 },104 });
64 .{105 try testCase(.{
65 .data = @embedFile("testdata/v7.tar"),106 .data = @embedFile("testdata/v7.tar"),
66 .files = &[_]Case.File{107 .files = &[_]Case.File{
67 .{108 .{
...@@ -79,8 +120,8 @@ const cases = [_]Case{...@@ -79,8 +120,8 @@ const cases = [_]Case{
79 "e38b27eaccb4391bdec553a7f3ae6b2f",120 "e38b27eaccb4391bdec553a7f3ae6b2f",
80 "c65bd2e50a56a2138bf1716f2fd56fe9",121 "c65bd2e50a56a2138bf1716f2fd56fe9",
81 },122 },
82 },123 });
83 .{124 try testCase(.{
84 .data = @embedFile("testdata/pax.tar"),125 .data = @embedFile("testdata/pax.tar"),
85 .files = &[_]Case.File{126 .files = &[_]Case.File{
86 .{127 .{
...@@ -99,13 +140,13 @@ const cases = [_]Case{...@@ -99,13 +140,13 @@ const cases = [_]Case{
99 .chksums = &[_][]const u8{140 .chksums = &[_][]const u8{
100 "3c382e8f5b6631aa2db52643912ffd4a",141 "3c382e8f5b6631aa2db52643912ffd4a",
101 },142 },
102 },143 });
103 .{144 try testCase(.{
104 // pax attribute don't end with \n145 // pax attribute don't end with \n
105 .data = @embedFile("testdata/pax-bad-hdr-file.tar"),146 .data = @embedFile("testdata/pax-bad-hdr-file.tar"),
106 .err = error.PaxInvalidAttributeEnd,147 .err = error.PaxInvalidAttributeEnd,
107 },148 });
108 .{149 try testCase(.{
109 // size is in pax attribute150 // size is in pax attribute
110 .data = @embedFile("testdata/pax-pos-size-file.tar"),151 .data = @embedFile("testdata/pax-pos-size-file.tar"),
111 .files = &[_]Case.File{152 .files = &[_]Case.File{
...@@ -119,8 +160,8 @@ const cases = [_]Case{...@@ -119,8 +160,8 @@ const cases = [_]Case{
119 .chksums = &[_][]const u8{160 .chksums = &[_][]const u8{
120 "0afb597b283fe61b5d4879669a350556",161 "0afb597b283fe61b5d4879669a350556",
121 },162 },
122 },163 });
123 .{164 try testCase(.{
124 // has pax records which we are not interested in165 // has pax records which we are not interested in
125 .data = @embedFile("testdata/pax-records.tar"),166 .data = @embedFile("testdata/pax-records.tar"),
126 .files = &[_]Case.File{167 .files = &[_]Case.File{
...@@ -128,8 +169,8 @@ const cases = [_]Case{...@@ -128,8 +169,8 @@ const cases = [_]Case{
128 .name = "file",169 .name = "file",
129 },170 },
130 },171 },
131 },172 });
132 .{173 try testCase(.{
133 // has global records which we are ignoring174 // has global records which we are ignoring
134 .data = @embedFile("testdata/pax-global-records.tar"),175 .data = @embedFile("testdata/pax-global-records.tar"),
135 .files = &[_]Case.File{176 .files = &[_]Case.File{
...@@ -146,8 +187,8 @@ const cases = [_]Case{...@@ -146,8 +187,8 @@ const cases = [_]Case{
146 .name = "file4",187 .name = "file4",
147 },188 },
148 },189 },
149 },190 });
150 .{191 try testCase(.{
151 .data = @embedFile("testdata/nil-uid.tar"),192 .data = @embedFile("testdata/nil-uid.tar"),
152 .files = &[_]Case.File{193 .files = &[_]Case.File{
153 .{194 .{
...@@ -160,8 +201,8 @@ const cases = [_]Case{...@@ -160,8 +201,8 @@ const cases = [_]Case{
160 .chksums = &[_][]const u8{201 .chksums = &[_][]const u8{
161 "08d504674115e77a67244beac19668f5",202 "08d504674115e77a67244beac19668f5",
162 },203 },
163 },204 });
164 .{205 try testCase(.{
165 // has xattrs and pax records which we are ignoring206 // has xattrs and pax records which we are ignoring
166 .data = @embedFile("testdata/xattrs.tar"),207 .data = @embedFile("testdata/xattrs.tar"),
167 .files = &[_]Case.File{208 .files = &[_]Case.File{
...@@ -182,23 +223,14 @@ const cases = [_]Case{...@@ -182,23 +223,14 @@ const cases = [_]Case{
182 "e38b27eaccb4391bdec553a7f3ae6b2f",223 "e38b27eaccb4391bdec553a7f3ae6b2f",
183 "c65bd2e50a56a2138bf1716f2fd56fe9",224 "c65bd2e50a56a2138bf1716f2fd56fe9",
184 },225 },
185 },226 });
186 .{227 try testCase(gnu_multi_headers_case);
187 .data = @embedFile("testdata/gnu-multi-hdrs.tar"),228 try testCase(.{
188 .files = &[_]Case.File{
189 .{
190 .name = "GNU2/GNU2/long-path-name",
191 .link_name = "GNU4/GNU4/long-linkpath-name",
192 .kind = .sym_link,
193 },
194 },
195 },
196 .{
197 // has gnu type D (directory) and S (sparse) blocks229 // has gnu type D (directory) and S (sparse) blocks
198 .data = @embedFile("testdata/gnu-incremental.tar"),230 .data = @embedFile("testdata/gnu-incremental.tar"),
199 .err = error.TarUnsupportedHeader,231 .err = error.TarUnsupportedHeader,
200 },232 });
201 .{233 try testCase(.{
202 // should use values only from last pax header234 // should use values only from last pax header
203 .data = @embedFile("testdata/pax-multi-hdrs.tar"),235 .data = @embedFile("testdata/pax-multi-hdrs.tar"),
204 .files = &[_]Case.File{236 .files = &[_]Case.File{
...@@ -208,8 +240,8 @@ const cases = [_]Case{...@@ -208,8 +240,8 @@ const cases = [_]Case{
208 .kind = .sym_link,240 .kind = .sym_link,
209 },241 },
210 },242 },
211 },243 });
212 .{244 try testCase(.{
213 .data = @embedFile("testdata/gnu-long-nul.tar"),245 .data = @embedFile("testdata/gnu-long-nul.tar"),
214 .files = &[_]Case.File{246 .files = &[_]Case.File{
215 .{247 .{
...@@ -217,8 +249,8 @@ const cases = [_]Case{...@@ -217,8 +249,8 @@ const cases = [_]Case{
217 .mode = 0o644,249 .mode = 0o644,
218 },250 },
219 },251 },
220 },252 });
221 .{253 try testCase(.{
222 .data = @embedFile("testdata/gnu-utf8.tar"),254 .data = @embedFile("testdata/gnu-utf8.tar"),
223 .files = &[_]Case.File{255 .files = &[_]Case.File{
224 .{256 .{
...@@ -226,8 +258,8 @@ const cases = [_]Case{...@@ -226,8 +258,8 @@ const cases = [_]Case{
226 .mode = 0o644,258 .mode = 0o644,
227 },259 },
228 },260 },
229 },261 });
230 .{262 try testCase(.{
231 .data = @embedFile("testdata/gnu-not-utf8.tar"),263 .data = @embedFile("testdata/gnu-not-utf8.tar"),
232 .files = &[_]Case.File{264 .files = &[_]Case.File{
233 .{265 .{
...@@ -235,33 +267,33 @@ const cases = [_]Case{...@@ -235,33 +267,33 @@ const cases = [_]Case{
235 .mode = 0o644,267 .mode = 0o644,
236 },268 },
237 },269 },
238 },270 });
239 .{271 try testCase(.{
240 // null in pax key272 // null in pax key
241 .data = @embedFile("testdata/pax-nul-xattrs.tar"),273 .data = @embedFile("testdata/pax-nul-xattrs.tar"),
242 .err = error.PaxNullInKeyword,274 .err = error.PaxNullInKeyword,
243 },275 });
244 .{276 try testCase(.{
245 .data = @embedFile("testdata/pax-nul-path.tar"),277 .data = @embedFile("testdata/pax-nul-path.tar"),
246 .err = error.PaxNullInValue,278 .err = error.PaxNullInValue,
247 },279 });
248 .{280 try testCase(.{
249 .data = @embedFile("testdata/neg-size.tar"),281 .data = @embedFile("testdata/neg-size.tar"),
250 .err = error.TarHeader,282 .err = error.TarHeader,
251 },283 });
252 .{284 try testCase(.{
253 .data = @embedFile("testdata/issue10968.tar"),285 .data = @embedFile("testdata/issue10968.tar"),
254 .err = error.TarHeader,286 .err = error.TarHeader,
255 },287 });
256 .{288 try testCase(.{
257 .data = @embedFile("testdata/issue11169.tar"),289 .data = @embedFile("testdata/issue11169.tar"),
258 .err = error.TarHeader,290 .err = error.TarHeader,
259 },291 });
260 .{292 try testCase(.{
261 .data = @embedFile("testdata/issue12435.tar"),293 .data = @embedFile("testdata/issue12435.tar"),
262 .err = error.TarHeaderChksum,294 .err = error.TarHeaderChksum,
263 },295 });
264 .{296 try testCase(.{
265 // has magic with space at end instead of null297 // has magic with space at end instead of null
266 .data = @embedFile("testdata/invalid-go17.tar"),298 .data = @embedFile("testdata/invalid-go17.tar"),
267 .files = &[_]Case.File{299 .files = &[_]Case.File{
...@@ -269,8 +301,8 @@ const cases = [_]Case{...@@ -269,8 +301,8 @@ const cases = [_]Case{
269 .name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/foo",301 .name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/foo",
270 },302 },
271 },303 },
272 },304 });
273 .{305 try testCase(.{
274 .data = @embedFile("testdata/ustar-file-devs.tar"),306 .data = @embedFile("testdata/ustar-file-devs.tar"),
275 .files = &[_]Case.File{307 .files = &[_]Case.File{
276 .{308 .{
...@@ -278,17 +310,9 @@ const cases = [_]Case{...@@ -278,17 +310,9 @@ const cases = [_]Case{
278 .mode = 0o644,310 .mode = 0o644,
279 },311 },
280 },312 },
281 },313 });
282 .{314 try testCase(trailing_slash_case);
283 .data = @embedFile("testdata/trailing-slash.tar"),315 try testCase(.{
284 .files = &[_]Case.File{
285 .{
286 .name = "123456789/" ** 30,
287 .kind = .directory,
288 },
289 },
290 },
291 .{
292 // Has size in gnu extended format. To represent size bigger than 8 GB.316 // Has size in gnu extended format. To represent size bigger than 8 GB.
293 .data = @embedFile("testdata/writer-big.tar"),317 .data = @embedFile("testdata/writer-big.tar"),
294 .files = &[_]Case.File{318 .files = &[_]Case.File{
...@@ -299,119 +323,91 @@ const cases = [_]Case{...@@ -299,119 +323,91 @@ const cases = [_]Case{
299 .mode = 0o640,323 .mode = 0o640,
300 },324 },
301 },325 },
302 },326 });
303 .{327 try testCase(writer_big_long_case);
304 // Size in gnu extended format, and name in pax attribute.328 try testCase(fuzz1_case);
305 .data = @embedFile("testdata/writer-big-long.tar"),329 try testCase(.{
306 .files = &[_]Case.File{
307 .{
308 .name = "longname/" ** 15 ++ "16gig.txt",
309 .size = 16 * 1024 * 1024 * 1024,
310 .mode = 0o644,
311 .truncated = true,
312 },
313 },
314 },
315 .{
316 .data = @embedFile("testdata/fuzz1.tar"),
317 .err = error.TarInsufficientBuffer,
318 },
319 .{
320 .data = @embedFile("testdata/fuzz2.tar"),330 .data = @embedFile("testdata/fuzz2.tar"),
321 .err = error.PaxSizeAttrOverflow,331 .err = error.PaxSizeAttrOverflow,
322 },332 });
323};333}
324
325// used in test to calculate file chksum
326const Md5Writer = struct {
327 h: std.crypto.hash.Md5 = std.crypto.hash.Md5.init(.{}),
328
329 pub fn writeAll(self: *Md5Writer, buf: []const u8) !void {
330 self.h.update(buf);
331 }
332
333 pub fn writeByte(self: *Md5Writer, byte: u8) !void {
334 self.h.update(&[_]u8{byte});
335 }
336
337 pub fn chksum(self: *Md5Writer) [32]u8 {
338 var s = [_]u8{0} ** 16;
339 self.h.final(&s);
340 return std.fmt.bytesToHex(s, .lower);
341 }
342};
343334
344test "run test cases" {335fn testCase(case: Case) !void {
345 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;336 var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
346 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;337 var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined;
347338
348 for (cases) |case| {339 var br: std.io.Reader = .fixed(case.data);
349 var br: std.io.Reader = .fixed(case.data);340 var it: tar.Iterator = .init(&br, .{
350 var iter: tar.Iterator = .init(&br, .{341 .file_name_buffer = &file_name_buffer,
351 .file_name_buffer = &file_name_buffer,342 .link_name_buffer = &link_name_buffer,
352 .link_name_buffer = &link_name_buffer,343 });
353 });344 var i: usize = 0;
354 var i: usize = 0;345 while (it.next() catch |err| {
355 while (iter.next() catch |err| {346 if (case.err) |e| {
356 if (case.err) |e| {347 try testing.expectEqual(e, err);
357 try testing.expectEqual(e, err);348 return;
358 continue;349 } else {
359 } else {350 return err;
360 return err;351 }
361 }352 }) |actual| : (i += 1) {
362 }) |actual| : (i += 1) {353 const expected = case.files[i];
363 const expected = case.files[i];354 try testing.expectEqualStrings(expected.name, actual.name);
364 try testing.expectEqualStrings(expected.name, actual.name);355 try testing.expectEqual(expected.size, actual.size);
365 try testing.expectEqual(expected.size, actual.size);356 try testing.expectEqual(expected.kind, actual.kind);
366 try testing.expectEqual(expected.kind, actual.kind);357 try testing.expectEqual(expected.mode, actual.mode);
367 try testing.expectEqual(expected.mode, actual.mode);358 try testing.expectEqualStrings(expected.link_name, actual.link_name);
368 try testing.expectEqualStrings(expected.link_name, actual.link_name);
369359
370 if (case.chksums.len > i) {360 if (case.chksums.len > i) {
371 var md5writer = Md5Writer{};361 var aw: std.Io.Writer.Allocating = .init(std.testing.allocator);
372 try actual.writeAll(&md5writer);362 defer aw.deinit();
373 const chksum = md5writer.chksum();363 try it.streamRemaining(actual, &aw.writer);
374 try testing.expectEqualStrings(case.chksums[i], &chksum);364 const chksum = std.fmt.bytesToHex(std.crypto.hash.Md5.hashResult(aw.getWritten()), .lower);
375 } else {365 try testing.expectEqualStrings(case.chksums[i], &chksum);
376 if (expected.truncated) {366 } else {
377 iter.unread_file_bytes = 0;367 if (expected.truncated) {
378 }368 it.unread_file_bytes = 0;
379 }369 }
380 }370 }
381 try testing.expectEqual(case.files.len, i);
382 }371 }
372 try testing.expectEqual(case.files.len, i);
383}373}
384374
385test "pax/gnu long names with small buffer" {375test "pax/gnu long names with small buffer" {
376 try testLongNameCase(gnu_multi_headers_case);
377 try testLongNameCase(trailing_slash_case);
378 try testLongNameCase(.{
379 .data = @embedFile("testdata/fuzz1.tar"),
380 .err = error.TarInsufficientBuffer,
381 });
382}
383
384fn testLongNameCase(case: Case) !void {
386 // should fail with insufficient buffer error385 // should fail with insufficient buffer error
387386
388 var min_file_name_buffer: [256]u8 = undefined;387 var min_file_name_buffer: [256]u8 = undefined;
389 var min_link_name_buffer: [100]u8 = undefined;388 var min_link_name_buffer: [100]u8 = undefined;
390 const long_name_cases = [_]Case{ cases[11], cases[25], cases[28] };
391389
392 for (long_name_cases) |case| {390 var br: std.io.Reader = .fixed(case.data);
393 var br: std.io.Reader = .fixed(case.data);391 var iter: tar.Iterator = .init(&br, .{
394 var iter: tar.Iterator = .init(&br, .{392 .file_name_buffer = &min_file_name_buffer,
395 .file_name_buffer = &min_file_name_buffer,393 .link_name_buffer = &min_link_name_buffer,
396 .link_name_buffer = &min_link_name_buffer,394 });
397 });
398395
399 var iter_err: ?anyerror = null;396 var iter_err: ?anyerror = null;
400 while (iter.next() catch |err| brk: {397 while (iter.next() catch |err| brk: {
401 iter_err = err;398 iter_err = err;
402 break :brk null;399 break :brk null;
403 }) |_| {}400 }) |_| {}
404401
405 try testing.expect(iter_err != null);402 try testing.expect(iter_err != null);
406 try testing.expectEqual(error.TarInsufficientBuffer, iter_err.?);403 try testing.expectEqual(error.TarInsufficientBuffer, iter_err.?);
407 }
408}404}
409405
410test "insufficient buffer in Header name filed" {406test "insufficient buffer in Header name filed" {
411 var min_file_name_buffer: [9]u8 = undefined;407 var min_file_name_buffer: [9]u8 = undefined;
412 var min_link_name_buffer: [100]u8 = undefined;408 var min_link_name_buffer: [100]u8 = undefined;
413409
414 var br: std.io.Reader = .fixed(cases[0].data);410 var br: std.io.Reader = .fixed(gnu_case.data);
415 var iter: tar.Iterator = .init(&br, .{411 var iter: tar.Iterator = .init(&br, .{
416 .file_name_buffer = &min_file_name_buffer,412 .file_name_buffer = &min_file_name_buffer,
417 .link_name_buffer = &min_link_name_buffer,413 .link_name_buffer = &min_link_name_buffer,
lib/std/testing.zig+1
...@@ -34,6 +34,7 @@ pub var log_level = std.log.Level.warn;...@@ -34,6 +34,7 @@ pub var log_level = std.log.Level.warn;
3434
35// Disable printing in tests for simple backends.35// Disable printing in tests for simple backends.
36pub const backend_can_print = switch (builtin.zig_backend) {36pub const backend_can_print = switch (builtin.zig_backend) {
37 .stage2_aarch64,
37 .stage2_powerpc,38 .stage2_powerpc,
38 .stage2_riscv64,39 .stage2_riscv64,
39 .stage2_spirv,40 .stage2_spirv,
src/Compilation.zig+24-15
...@@ -1850,7 +1850,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1850,7 +1850,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1850 // approach, since the ubsan runtime uses quite a lot of the standard library1850 // approach, since the ubsan runtime uses quite a lot of the standard library
1851 // and this reduces unnecessary bloat.1851 // and this reduces unnecessary bloat.
1852 const ubsan_rt_strat: RtStrat = s: {1852 const ubsan_rt_strat: RtStrat = s: {
1853 const can_build_ubsan_rt = target_util.canBuildLibUbsanRt(target);1853 const can_build_ubsan_rt = target_util.canBuildLibUbsanRt(target, use_llvm, build_options.have_llvm);
1854 const want_ubsan_rt = options.want_ubsan_rt orelse (can_build_ubsan_rt and any_sanitize_c == .full and is_exe_or_dyn_lib);1854 const want_ubsan_rt = options.want_ubsan_rt orelse (can_build_ubsan_rt and any_sanitize_c == .full and is_exe_or_dyn_lib);
1855 if (!want_ubsan_rt) break :s .none;1855 if (!want_ubsan_rt) break :s .none;
1856 if (options.skip_linker_dependencies) break :s .none;1856 if (options.skip_linker_dependencies) break :s .none;
...@@ -4862,6 +4862,9 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4862,6 +4862,9 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
4862 };4862 };
4863 defer tar_file.close();4863 defer tar_file.close();
48644864
4865 var buffer: [1024]u8 = undefined;
4866 var tar_file_writer = tar_file.writer(&buffer);
4867
4865 var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, []const u8) = .empty;4868 var seen_table: std.AutoArrayHashMapUnmanaged(*Package.Module, []const u8) = .empty;
4866 defer seen_table.deinit(comp.gpa);4869 defer seen_table.deinit(comp.gpa);
48674870
...@@ -4871,7 +4874,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4871,7 +4874,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
4871 var i: usize = 0;4874 var i: usize = 0;
4872 while (i < seen_table.count()) : (i += 1) {4875 while (i < seen_table.count()) : (i += 1) {
4873 const mod = seen_table.keys()[i];4876 const mod = seen_table.keys()[i];
4874 try comp.docsCopyModule(mod, seen_table.values()[i], tar_file);4877 try comp.docsCopyModule(mod, seen_table.values()[i], &tar_file_writer);
48754878
4876 const deps = mod.deps.values();4879 const deps = mod.deps.values();
4877 try seen_table.ensureUnusedCapacity(comp.gpa, deps.len);4880 try seen_table.ensureUnusedCapacity(comp.gpa, deps.len);
...@@ -4879,24 +4882,29 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {...@@ -4879,24 +4882,29 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
4879 }4882 }
4880}4883}
48814884
4882fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8, tar_file: fs.File) !void {4885fn docsCopyModule(
4886 comp: *Compilation,
4887 module: *Package.Module,
4888 name: []const u8,
4889 tar_file_writer: *fs.File.Writer,
4890) !void {
4883 const root = module.root;4891 const root = module.root;
4884 var mod_dir = d: {4892 var mod_dir = d: {
4885 const root_dir, const sub_path = root.openInfo(comp.dirs);4893 const root_dir, const sub_path = root.openInfo(comp.dirs);
4886 break :d root_dir.openDir(sub_path, .{ .iterate = true });4894 break :d root_dir.openDir(sub_path, .{ .iterate = true });
4887 } catch |err| {4895 } catch |err| {
4888 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{f}': {s}", .{4896 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open directory '{f}': {t}", .{ root.fmt(comp), err });
4889 root.fmt(comp), @errorName(err),
4890 });
4891 };4897 };
4892 defer mod_dir.close();4898 defer mod_dir.close();
48934899
4894 var walker = try mod_dir.walk(comp.gpa);4900 var walker = try mod_dir.walk(comp.gpa);
4895 defer walker.deinit();4901 defer walker.deinit();
48964902
4897 var archiver = std.tar.writer(tar_file.deprecatedWriter().any());4903 var archiver: std.tar.Writer = .{ .underlying_writer = &tar_file_writer.interface };
4898 archiver.prefix = name;4904 archiver.prefix = name;
48994905
4906 var buffer: [1024]u8 = undefined;
4907
4900 while (try walker.next()) |entry| {4908 while (try walker.next()) |entry| {
4901 switch (entry.kind) {4909 switch (entry.kind) {
4902 .file => {4910 .file => {
...@@ -4907,14 +4915,17 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,...@@ -4907,14 +4915,17 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, name: []const u8,
4907 else => continue,4915 else => continue,
4908 }4916 }
4909 var file = mod_dir.openFile(entry.path, .{}) catch |err| {4917 var file = mod_dir.openFile(entry.path, .{}) catch |err| {
4910 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open '{f}{s}': {s}", .{4918 return comp.lockAndSetMiscFailure(.docs_copy, "unable to open {f}{s}: {t}", .{
4911 root.fmt(comp), entry.path, @errorName(err),4919 root.fmt(comp), entry.path, err,
4912 });4920 });
4913 };4921 };
4914 defer file.close();4922 defer file.close();
4915 archiver.writeFile(entry.path, file) catch |err| {4923 const stat = try file.stat();
4916 return comp.lockAndSetMiscFailure(.docs_copy, "unable to archive '{f}{s}': {s}", .{4924 var file_reader: fs.File.Reader = .initSize(file, &buffer, stat.size);
4917 root.fmt(comp), entry.path, @errorName(err),4925
4926 archiver.writeFile(entry.path, &file_reader, stat.mtime) catch |err| {
4927 return comp.lockAndSetMiscFailure(.docs_copy, "unable to archive {f}{s}: {t}", .{
4928 root.fmt(comp), entry.path, err,
4918 });4929 });
4919 };4930 };
4920 }4931 }
...@@ -4926,9 +4937,7 @@ fn workerDocsWasm(comp: *Compilation, parent_prog_node: std.Progress.Node) void...@@ -4926,9 +4937,7 @@ fn workerDocsWasm(comp: *Compilation, parent_prog_node: std.Progress.Node) void
49264937
4927 workerDocsWasmFallible(comp, prog_node) catch |err| switch (err) {4938 workerDocsWasmFallible(comp, prog_node) catch |err| switch (err) {
4928 error.SubCompilationFailed => return, // error reported already4939 error.SubCompilationFailed => return, // error reported already
4929 else => comp.lockAndSetMiscFailure(.docs_wasm, "unable to build autodocs: {s}", .{4940 else => comp.lockAndSetMiscFailure(.docs_wasm, "unable to build autodocs: {t}", .{err}),
4930 @errorName(err),
4931 }),
4932 };4941 };
4933}4942}
49344943
src/InternPool.zig+10-4
...@@ -7556,12 +7556,18 @@ fn extraFuncCoerced(ip: *const InternPool, extra: Local.Extra, extra_index: u32)...@@ -7556,12 +7556,18 @@ fn extraFuncCoerced(ip: *const InternPool, extra: Local.Extra, extra_index: u32)
7556fn indexToKeyBigInt(ip: *const InternPool, tid: Zcu.PerThread.Id, limb_index: u32, positive: bool) Key {7556fn indexToKeyBigInt(ip: *const InternPool, tid: Zcu.PerThread.Id, limb_index: u32, positive: bool) Key {
7557 const limbs_items = ip.getLocalShared(tid).getLimbs().view().items(.@"0");7557 const limbs_items = ip.getLocalShared(tid).getLimbs().view().items(.@"0");
7558 const int: Int = @bitCast(limbs_items[limb_index..][0..Int.limbs_items_len].*);7558 const int: Int = @bitCast(limbs_items[limb_index..][0..Int.limbs_items_len].*);
7559 const big_int: BigIntConst = .{
7560 .limbs = limbs_items[limb_index + Int.limbs_items_len ..][0..int.limbs_len],
7561 .positive = positive,
7562 };
7559 return .{ .int = .{7563 return .{ .int = .{
7560 .ty = int.ty,7564 .ty = int.ty,
7561 .storage = .{ .big_int = .{7565 .storage = if (big_int.toInt(u64)) |x|
7562 .limbs = limbs_items[limb_index + Int.limbs_items_len ..][0..int.limbs_len],7566 .{ .u64 = x }
7563 .positive = positive,7567 else |_| if (big_int.toInt(i64)) |x|
7564 } },7568 .{ .i64 = x }
7569 else |_|
7570 .{ .big_int = big_int },
7565 } };7571 } };
7566}7572}
75677573
src/Package/Fetch.zig+18-9
...@@ -1197,12 +1197,17 @@ fn unpackResource(...@@ -1197,12 +1197,17 @@ fn unpackResource(
1197 };1197 };
11981198
1199 switch (file_type) {1199 switch (file_type) {
1200 .tar => return try unpackTarball(f, tmp_directory.handle, resource.reader()),1200 .tar => {
1201 var adapter = resource.reader().adaptToNewApi();
1202 return unpackTarball(f, tmp_directory.handle, &adapter.new_interface);
1203 },
1201 .@"tar.gz" => {1204 .@"tar.gz" => {
1202 const reader = resource.reader();1205 const reader = resource.reader();
1203 var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader);1206 var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader);
1204 var dcp = std.compress.gzip.decompressor(br.reader());1207 var dcp = std.compress.gzip.decompressor(br.reader());
1205 return try unpackTarball(f, tmp_directory.handle, dcp.reader());1208 var adapter_buffer: [1024]u8 = undefined;
1209 var adapter = dcp.reader().adaptToNewApi(&adapter_buffer);
1210 return try unpackTarball(f, tmp_directory.handle, &adapter.new_interface);
1206 },1211 },
1207 .@"tar.xz" => {1212 .@"tar.xz" => {
1208 const gpa = f.arena.child_allocator;1213 const gpa = f.arena.child_allocator;
...@@ -1215,7 +1220,9 @@ fn unpackResource(...@@ -1215,7 +1220,9 @@ fn unpackResource(
1215 ));1220 ));
1216 };1221 };
1217 defer dcp.deinit();1222 defer dcp.deinit();
1218 return try unpackTarball(f, tmp_directory.handle, dcp.reader());1223 var adapter_buffer: [1024]u8 = undefined;
1224 var adapter = dcp.reader().adaptToNewApi(&adapter_buffer);
1225 return try unpackTarball(f, tmp_directory.handle, &adapter.new_interface);
1219 },1226 },
1220 .@"tar.zst" => {1227 .@"tar.zst" => {
1221 const window_size = std.compress.zstd.default_window_len;1228 const window_size = std.compress.zstd.default_window_len;
...@@ -1225,7 +1232,9 @@ fn unpackResource(...@@ -1225,7 +1232,9 @@ fn unpackResource(
1225 var dcp = std.compress.zstd.decompressor(br.reader(), .{1232 var dcp = std.compress.zstd.decompressor(br.reader(), .{
1226 .window_buffer = window_buffer,1233 .window_buffer = window_buffer,
1227 });1234 });
1228 return try unpackTarball(f, tmp_directory.handle, dcp.reader());1235 var adapter_buffer: [1024]u8 = undefined;
1236 var adapter = dcp.reader().adaptToNewApi(&adapter_buffer);
1237 return try unpackTarball(f, tmp_directory.handle, &adapter.new_interface);
1229 },1238 },
1230 .git_pack => return unpackGitPack(f, tmp_directory.handle, &resource.git) catch |err| switch (err) {1239 .git_pack => return unpackGitPack(f, tmp_directory.handle, &resource.git) catch |err| switch (err) {
1231 error.FetchFailed => return error.FetchFailed,1240 error.FetchFailed => return error.FetchFailed,
...@@ -1239,7 +1248,7 @@ fn unpackResource(...@@ -1239,7 +1248,7 @@ fn unpackResource(
1239 }1248 }
1240}1249}
12411250
1242fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackResult {1251fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: *std.Io.Reader) RunError!UnpackResult {
1243 const eb = &f.error_bundle;1252 const eb = &f.error_bundle;
1244 const arena = f.arena.allocator();1253 const arena = f.arena.allocator();
12451254
...@@ -1250,10 +1259,10 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackRes...@@ -1250,10 +1259,10 @@ fn unpackTarball(f: *Fetch, out_dir: fs.Dir, reader: anytype) RunError!UnpackRes
1250 .strip_components = 0,1259 .strip_components = 0,
1251 .mode_mode = .ignore,1260 .mode_mode = .ignore,
1252 .exclude_empty_directories = true,1261 .exclude_empty_directories = true,
1253 }) catch |err| return f.fail(f.location_tok, try eb.printString(1262 }) catch |err| return f.fail(
1254 "unable to unpack tarball to temporary directory: {s}",1263 f.location_tok,
1255 .{@errorName(err)},1264 try eb.printString("unable to unpack tarball to temporary directory: {t}", .{err}),
1256 ));1265 );
12571266
1258 var res: UnpackResult = .{ .root_dir = diagnostics.root_dir };1267 var res: UnpackResult = .{ .root_dir = diagnostics.root_dir };
1259 if (diagnostics.errors.items.len > 0) {1268 if (diagnostics.errors.items.len > 0) {
src/Sema.zig+5-4
...@@ -16522,7 +16522,7 @@ fn zirAsm(...@@ -16522,7 +16522,7 @@ fn zirAsm(
16522 break :empty try sema.structInitEmpty(block, clobbers_ty, src, src);16522 break :empty try sema.structInitEmpty(block, clobbers_ty, src, src);
16523 } else try sema.resolveInst(extra.data.clobbers); // Already coerced by AstGen.16523 } else try sema.resolveInst(extra.data.clobbers); // Already coerced by AstGen.
16524 const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber });16524 const clobbers_val = try sema.resolveConstDefinedValue(block, src, clobbers, .{ .simple = .clobber });
16525 needed_capacity += (asm_source.len + 3) / 4;16525 needed_capacity += asm_source.len / 4 + 1;
1652616526
16527 const gpa = sema.gpa;16527 const gpa = sema.gpa;
16528 try sema.air_extra.ensureUnusedCapacity(gpa, needed_capacity);16528 try sema.air_extra.ensureUnusedCapacity(gpa, needed_capacity);
...@@ -16562,7 +16562,8 @@ fn zirAsm(...@@ -16562,7 +16562,8 @@ fn zirAsm(
16562 {16562 {
16563 const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());16563 const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());
16564 @memcpy(buffer[0..asm_source.len], asm_source);16564 @memcpy(buffer[0..asm_source.len], asm_source);
16565 sema.air_extra.items.len += (asm_source.len + 3) / 4;16565 buffer[asm_source.len] = 0;
16566 sema.air_extra.items.len += asm_source.len / 4 + 1;
16566 }16567 }
16567 return asm_air;16568 return asm_air;
16568}16569}
...@@ -24846,7 +24847,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24846,7 +24847,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24846 },24847 },
24847 .@"packed" => {24848 .@"packed" => {
24848 const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) +24849 const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) +
24849 (if (zcu.typeToStruct(parent_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, field_index) else 0) -24850 (if (zcu.typeToStruct(parent_ty)) |struct_obj| zcu.structPackedFieldBitOffset(struct_obj, field_index) else 0) -
24850 actual_field_ptr_info.packed_offset.bit_offset), 8) catch24851 actual_field_ptr_info.packed_offset.bit_offset), 8) catch
24851 return sema.fail(block, inst_src, "pointer bit-offset mismatch", .{});24852 return sema.fail(block, inst_src, "pointer bit-offset mismatch", .{});
24852 actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (byte_offset > 0)24853 actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(if (byte_offset > 0)
...@@ -24873,7 +24874,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24873,7 +24874,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24873 // Logic lifted from type computation above - I'm just assuming it's correct.24874 // Logic lifted from type computation above - I'm just assuming it's correct.
24874 // `catch unreachable` since error case handled above.24875 // `catch unreachable` since error case handled above.
24875 const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) +24876 const byte_offset = std.math.divExact(u32, @abs(@as(i32, actual_parent_ptr_info.packed_offset.bit_offset) +
24876 pt.structPackedFieldBitOffset(zcu.typeToStruct(parent_ty).?, field_index) -24877 zcu.structPackedFieldBitOffset(zcu.typeToStruct(parent_ty).?, field_index) -
24877 actual_field_ptr_info.packed_offset.bit_offset), 8) catch unreachable;24878 actual_field_ptr_info.packed_offset.bit_offset), 8) catch unreachable;
24878 const parent_ptr_val = try sema.ptrSubtract(block, field_ptr_src, field_ptr_val, byte_offset, actual_parent_ptr_ty);24879 const parent_ptr_val = try sema.ptrSubtract(block, field_ptr_src, field_ptr_val, byte_offset, actual_parent_ptr_ty);
24879 break :result Air.internedToRef(parent_ptr_val.toIntern());24880 break :result Air.internedToRef(parent_ptr_val.toIntern());
src/Type.zig+1-1
...@@ -4163,7 +4163,7 @@ pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };...@@ -4163,7 +4163,7 @@ pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
4163pub fn smallestUnsignedBits(max: u64) u16 {4163pub fn smallestUnsignedBits(max: u64) u16 {
4164 return switch (max) {4164 return switch (max) {
4165 0 => 0,4165 0 => 0,
4166 else => 1 + std.math.log2_int(u64, max),4166 else => @as(u16, 1) + std.math.log2_int(u64, max),
4167 };4167 };
4168}4168}
41694169
src/Zcu.zig+24-5
...@@ -3891,6 +3891,29 @@ pub fn typeToPackedStruct(zcu: *const Zcu, ty: Type) ?InternPool.LoadedStructTyp...@@ -3891,6 +3891,29 @@ pub fn typeToPackedStruct(zcu: *const Zcu, ty: Type) ?InternPool.LoadedStructTyp
3891 return s;3891 return s;
3892}3892}
38933893
3894/// https://github.com/ziglang/zig/issues/17178 explored storing these bit offsets
3895/// into the packed struct InternPool data rather than computing this on the
3896/// fly, however it was found to perform worse when measured on real world
3897/// projects.
3898pub fn structPackedFieldBitOffset(
3899 zcu: *Zcu,
3900 struct_type: InternPool.LoadedStructType,
3901 field_index: u32,
3902) u16 {
3903 const ip = &zcu.intern_pool;
3904 assert(struct_type.layout == .@"packed");
3905 assert(struct_type.haveLayout(ip));
3906 var bit_sum: u64 = 0;
3907 for (0..struct_type.field_types.len) |i| {
3908 if (i == field_index) {
3909 return @intCast(bit_sum);
3910 }
3911 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
3912 bit_sum += field_ty.bitSize(zcu);
3913 }
3914 unreachable; // index out of bounds
3915}
3916
3894pub fn typeToUnion(zcu: *const Zcu, ty: Type) ?InternPool.LoadedUnionType {3917pub fn typeToUnion(zcu: *const Zcu, ty: Type) ?InternPool.LoadedUnionType {
3895 if (ty.ip_index == .none) return null;3918 if (ty.ip_index == .none) return null;
3896 const ip = &zcu.intern_pool;3919 const ip = &zcu.intern_pool;
...@@ -4436,11 +4459,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu...@@ -4436,11 +4459,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu
4436 else => false,4459 else => false,
4437 },4460 },
4438 .stage2_aarch64 => switch (cc) {4461 .stage2_aarch64 => switch (cc) {
4439 .aarch64_aapcs,4462 .aarch64_aapcs, .aarch64_aapcs_darwin, .naked => true,
4440 .aarch64_aapcs_darwin,
4441 .aarch64_aapcs_win,
4442 => |opts| opts.incoming_stack_alignment == null,
4443 .naked => true,
4444 else => false,4463 else => false,
4445 },4464 },
4446 .stage2_x86 => switch (cc) {4465 .stage2_x86 => switch (cc) {
src/Zcu/PerThread.zig+7-28
...@@ -3737,30 +3737,6 @@ pub fn intBitsForValue(pt: Zcu.PerThread, val: Value, sign: bool) u16 {...@@ -3737,30 +3737,6 @@ pub fn intBitsForValue(pt: Zcu.PerThread, val: Value, sign: bool) u16 {
3737 }3737 }
3738}3738}
37393739
3740/// https://github.com/ziglang/zig/issues/17178 explored storing these bit offsets
3741/// into the packed struct InternPool data rather than computing this on the
3742/// fly, however it was found to perform worse when measured on real world
3743/// projects.
3744pub fn structPackedFieldBitOffset(
3745 pt: Zcu.PerThread,
3746 struct_type: InternPool.LoadedStructType,
3747 field_index: u32,
3748) u16 {
3749 const zcu = pt.zcu;
3750 const ip = &zcu.intern_pool;
3751 assert(struct_type.layout == .@"packed");
3752 assert(struct_type.haveLayout(ip));
3753 var bit_sum: u64 = 0;
3754 for (0..struct_type.field_types.len) |i| {
3755 if (i == field_index) {
3756 return @intCast(bit_sum);
3757 }
3758 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
3759 bit_sum += field_ty.bitSize(zcu);
3760 }
3761 unreachable; // index out of bounds
3762}
3763
3764pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Error!Type {3740pub fn navPtrType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Allocator.Error!Type {
3765 const zcu = pt.zcu;3741 const zcu = pt.zcu;
3766 const ip = &zcu.intern_pool;3742 const ip = &zcu.intern_pool;
...@@ -4381,8 +4357,11 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e...@@ -4381,8 +4357,11 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
4381 try air.legalize(pt, features);4357 try air.legalize(pt, features);
4382 }4358 }
43834359
4384 var liveness: Air.Liveness = try .analyze(zcu, air.*, ip);4360 var liveness: ?Air.Liveness = if (codegen.wantsLiveness(pt, nav))
4385 defer liveness.deinit(gpa);4361 try .analyze(zcu, air.*, ip)
4362 else
4363 null;
4364 defer if (liveness) |*l| l.deinit(gpa);
43864365
4387 if (build_options.enable_debug_extensions and comp.verbose_air) {4366 if (build_options.enable_debug_extensions and comp.verbose_air) {
4388 const stderr = std.debug.lockStderrWriter(&.{});4367 const stderr = std.debug.lockStderrWriter(&.{});
...@@ -4392,12 +4371,12 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e...@@ -4392,12 +4371,12 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e
4392 stderr.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}) catch {};4371 stderr.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)}) catch {};
4393 }4372 }
43944373
4395 if (std.debug.runtime_safety) {4374 if (std.debug.runtime_safety) verify_liveness: {
4396 var verify: Air.Liveness.Verify = .{4375 var verify: Air.Liveness.Verify = .{
4397 .gpa = gpa,4376 .gpa = gpa,
4398 .zcu = zcu,4377 .zcu = zcu,
4399 .air = air.*,4378 .air = air.*,
4400 .liveness = liveness,4379 .liveness = liveness orelse break :verify_liveness,
4401 .intern_pool = ip,4380 .intern_pool = ip,
4402 };4381 };
4403 defer verify.deinit();4382 defer verify.deinit();
src/arch/aarch64/bits.zig deleted-2063
...@@ -1,2063 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4const testing = std.testing;
5
6/// Disjoint sets of registers. Every register must belong to
7/// exactly one register class.
8pub const RegisterClass = enum {
9 general_purpose,
10 stack_pointer,
11 floating_point,
12};
13
14/// Registers in the AArch64 instruction set
15pub const Register = enum(u8) {
16 // zig fmt: off
17 // 64-bit general-purpose registers
18 x0, x1, x2, x3, x4, x5, x6, x7,
19 x8, x9, x10, x11, x12, x13, x14, x15,
20 x16, x17, x18, x19, x20, x21, x22, x23,
21 x24, x25, x26, x27, x28, x29, x30, xzr,
22
23 // 32-bit general-purpose registers
24 w0, w1, w2, w3, w4, w5, w6, w7,
25 w8, w9, w10, w11, w12, w13, w14, w15,
26 w16, w17, w18, w19, w20, w21, w22, w23,
27 w24, w25, w26, w27, w28, w29, w30, wzr,
28
29 // Stack pointer
30 sp, wsp,
31
32 // 128-bit floating-point registers
33 q0, q1, q2, q3, q4, q5, q6, q7,
34 q8, q9, q10, q11, q12, q13, q14, q15,
35 q16, q17, q18, q19, q20, q21, q22, q23,
36 q24, q25, q26, q27, q28, q29, q30, q31,
37
38 // 64-bit floating-point registers
39 d0, d1, d2, d3, d4, d5, d6, d7,
40 d8, d9, d10, d11, d12, d13, d14, d15,
41 d16, d17, d18, d19, d20, d21, d22, d23,
42 d24, d25, d26, d27, d28, d29, d30, d31,
43
44 // 32-bit floating-point registers
45 s0, s1, s2, s3, s4, s5, s6, s7,
46 s8, s9, s10, s11, s12, s13, s14, s15,
47 s16, s17, s18, s19, s20, s21, s22, s23,
48 s24, s25, s26, s27, s28, s29, s30, s31,
49
50 // 16-bit floating-point registers
51 h0, h1, h2, h3, h4, h5, h6, h7,
52 h8, h9, h10, h11, h12, h13, h14, h15,
53 h16, h17, h18, h19, h20, h21, h22, h23,
54 h24, h25, h26, h27, h28, h29, h30, h31,
55
56 // 8-bit floating-point registers
57 b0, b1, b2, b3, b4, b5, b6, b7,
58 b8, b9, b10, b11, b12, b13, b14, b15,
59 b16, b17, b18, b19, b20, b21, b22, b23,
60 b24, b25, b26, b27, b28, b29, b30, b31,
61 // zig fmt: on
62
63 pub fn class(self: Register) RegisterClass {
64 return switch (@intFromEnum(self)) {
65 @intFromEnum(Register.x0)...@intFromEnum(Register.xzr) => .general_purpose,
66 @intFromEnum(Register.w0)...@intFromEnum(Register.wzr) => .general_purpose,
67
68 @intFromEnum(Register.sp) => .stack_pointer,
69 @intFromEnum(Register.wsp) => .stack_pointer,
70
71 @intFromEnum(Register.q0)...@intFromEnum(Register.q31) => .floating_point,
72 @intFromEnum(Register.d0)...@intFromEnum(Register.d31) => .floating_point,
73 @intFromEnum(Register.s0)...@intFromEnum(Register.s31) => .floating_point,
74 @intFromEnum(Register.h0)...@intFromEnum(Register.h31) => .floating_point,
75 @intFromEnum(Register.b0)...@intFromEnum(Register.b31) => .floating_point,
76 else => unreachable,
77 };
78 }
79
80 pub fn id(self: Register) u6 {
81 return switch (@intFromEnum(self)) {
82 @intFromEnum(Register.x0)...@intFromEnum(Register.xzr) => @as(u6, @intCast(@intFromEnum(self) - @intFromEnum(Register.x0))),
83 @intFromEnum(Register.w0)...@intFromEnum(Register.wzr) => @as(u6, @intCast(@intFromEnum(self) - @intFromEnum(Register.w0))),
84
85 @intFromEnum(Register.sp) => 32,
86 @intFromEnum(Register.wsp) => 32,
87
88 @intFromEnum(Register.q0)...@intFromEnum(Register.q31) => @as(u6, @intCast(@intFromEnum(self) - @intFromEnum(Register.q0) + 33)),
89 @intFromEnum(Register.d0)...@intFromEnum(Register.d31) => @as(u6, @intCast(@intFromEnum(self) - @intFromEnum(Register.d0) + 33)),
90 @intFromEnum(Register.s0)...@intFromEnum(Register.s31) => @as(u6, @intCast(@intFromEnum(self) - @intFromEnum(Register.s0) + 33)),
91 @intFromEnum(Register.h0)...@intFromEnum(Register.h31) => @as(u6, @intCast(@intFromEnum(self) - @intFromEnum(Register.h0) + 33)),
92 @intFromEnum(Register.b0)...@intFromEnum(Register.b31) => @as(u6, @intCast(@intFromEnum(self) - @intFromEnum(Register.b0) + 33)),
93 else => unreachable,
94 };
95 }
96
97 pub fn enc(self: Register) u5 {
98 return switch (@intFromEnum(self)) {
99 @intFromEnum(Register.x0)...@intFromEnum(Register.xzr) => @as(u5, @intCast(@intFromEnum(self) - @intFromEnum(Register.x0))),
100 @intFromEnum(Register.w0)...@intFromEnum(Register.wzr) => @as(u5, @intCast(@intFromEnum(self) - @intFromEnum(Register.w0))),
101
102 @intFromEnum(Register.sp) => 31,
103 @intFromEnum(Register.wsp) => 31,
104
105 @intFromEnum(Register.q0)...@intFromEnum(Register.q31) => @as(u5, @intCast(@intFromEnum(self) - @intFromEnum(Register.q0))),
106 @intFromEnum(Register.d0)...@intFromEnum(Register.d31) => @as(u5, @intCast(@intFromEnum(self) - @intFromEnum(Register.d0))),
107 @intFromEnum(Register.s0)...@intFromEnum(Register.s31) => @as(u5, @intCast(@intFromEnum(self) - @intFromEnum(Register.s0))),
108 @intFromEnum(Register.h0)...@intFromEnum(Register.h31) => @as(u5, @intCast(@intFromEnum(self) - @intFromEnum(Register.h0))),
109 @intFromEnum(Register.b0)...@intFromEnum(Register.b31) => @as(u5, @intCast(@intFromEnum(self) - @intFromEnum(Register.b0))),
110 else => unreachable,
111 };
112 }
113
114 /// Returns the bit-width of the register.
115 pub fn size(self: Register) u8 {
116 return switch (@intFromEnum(self)) {
117 @intFromEnum(Register.x0)...@intFromEnum(Register.xzr) => 64,
118 @intFromEnum(Register.w0)...@intFromEnum(Register.wzr) => 32,
119
120 @intFromEnum(Register.sp) => 64,
121 @intFromEnum(Register.wsp) => 32,
122
123 @intFromEnum(Register.q0)...@intFromEnum(Register.q31) => 128,
124 @intFromEnum(Register.d0)...@intFromEnum(Register.d31) => 64,
125 @intFromEnum(Register.s0)...@intFromEnum(Register.s31) => 32,
126 @intFromEnum(Register.h0)...@intFromEnum(Register.h31) => 16,
127 @intFromEnum(Register.b0)...@intFromEnum(Register.b31) => 8,
128 else => unreachable,
129 };
130 }
131
132 /// Convert from a general-purpose register to its 64 bit alias.
133 pub fn toX(self: Register) Register {
134 return switch (@intFromEnum(self)) {
135 @intFromEnum(Register.x0)...@intFromEnum(Register.xzr) => @as(
136 Register,
137 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.x0) + @intFromEnum(Register.x0)),
138 ),
139 @intFromEnum(Register.w0)...@intFromEnum(Register.wzr) => @as(
140 Register,
141 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.w0) + @intFromEnum(Register.x0)),
142 ),
143 else => unreachable,
144 };
145 }
146
147 /// Convert from a general-purpose register to its 32 bit alias.
148 pub fn toW(self: Register) Register {
149 return switch (@intFromEnum(self)) {
150 @intFromEnum(Register.x0)...@intFromEnum(Register.xzr) => @as(
151 Register,
152 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.x0) + @intFromEnum(Register.w0)),
153 ),
154 @intFromEnum(Register.w0)...@intFromEnum(Register.wzr) => @as(
155 Register,
156 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.w0) + @intFromEnum(Register.w0)),
157 ),
158 else => unreachable,
159 };
160 }
161
162 /// Convert from a floating-point register to its 128 bit alias.
163 pub fn toQ(self: Register) Register {
164 return switch (@intFromEnum(self)) {
165 @intFromEnum(Register.q0)...@intFromEnum(Register.q31) => @as(
166 Register,
167 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.q0) + @intFromEnum(Register.q0)),
168 ),
169 @intFromEnum(Register.d0)...@intFromEnum(Register.d31) => @as(
170 Register,
171 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.d0) + @intFromEnum(Register.q0)),
172 ),
173 @intFromEnum(Register.s0)...@intFromEnum(Register.s31) => @as(
174 Register,
175 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.s0) + @intFromEnum(Register.q0)),
176 ),
177 @intFromEnum(Register.h0)...@intFromEnum(Register.h31) => @as(
178 Register,
179 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.h0) + @intFromEnum(Register.q0)),
180 ),
181 @intFromEnum(Register.b0)...@intFromEnum(Register.b31) => @as(
182 Register,
183 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.b0) + @intFromEnum(Register.q0)),
184 ),
185 else => unreachable,
186 };
187 }
188
189 /// Convert from a floating-point register to its 64 bit alias.
190 pub fn toD(self: Register) Register {
191 return switch (@intFromEnum(self)) {
192 @intFromEnum(Register.q0)...@intFromEnum(Register.q31) => @as(
193 Register,
194 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.q0) + @intFromEnum(Register.d0)),
195 ),
196 @intFromEnum(Register.d0)...@intFromEnum(Register.d31) => @as(
197 Register,
198 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.d0) + @intFromEnum(Register.d0)),
199 ),
200 @intFromEnum(Register.s0)...@intFromEnum(Register.s31) => @as(
201 Register,
202 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.s0) + @intFromEnum(Register.d0)),
203 ),
204 @intFromEnum(Register.h0)...@intFromEnum(Register.h31) => @as(
205 Register,
206 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.h0) + @intFromEnum(Register.d0)),
207 ),
208 @intFromEnum(Register.b0)...@intFromEnum(Register.b31) => @as(
209 Register,
210 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.b0) + @intFromEnum(Register.d0)),
211 ),
212 else => unreachable,
213 };
214 }
215
216 /// Convert from a floating-point register to its 32 bit alias.
217 pub fn toS(self: Register) Register {
218 return switch (@intFromEnum(self)) {
219 @intFromEnum(Register.q0)...@intFromEnum(Register.q31) => @as(
220 Register,
221 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.q0) + @intFromEnum(Register.s0)),
222 ),
223 @intFromEnum(Register.d0)...@intFromEnum(Register.d31) => @as(
224 Register,
225 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.d0) + @intFromEnum(Register.s0)),
226 ),
227 @intFromEnum(Register.s0)...@intFromEnum(Register.s31) => @as(
228 Register,
229 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.s0) + @intFromEnum(Register.s0)),
230 ),
231 @intFromEnum(Register.h0)...@intFromEnum(Register.h31) => @as(
232 Register,
233 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.h0) + @intFromEnum(Register.s0)),
234 ),
235 @intFromEnum(Register.b0)...@intFromEnum(Register.b31) => @as(
236 Register,
237 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.b0) + @intFromEnum(Register.s0)),
238 ),
239 else => unreachable,
240 };
241 }
242
243 /// Convert from a floating-point register to its 16 bit alias.
244 pub fn toH(self: Register) Register {
245 return switch (@intFromEnum(self)) {
246 @intFromEnum(Register.q0)...@intFromEnum(Register.q31) => @as(
247 Register,
248 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.q0) + @intFromEnum(Register.h0)),
249 ),
250 @intFromEnum(Register.d0)...@intFromEnum(Register.d31) => @as(
251 Register,
252 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.d0) + @intFromEnum(Register.h0)),
253 ),
254 @intFromEnum(Register.s0)...@intFromEnum(Register.s31) => @as(
255 Register,
256 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.s0) + @intFromEnum(Register.h0)),
257 ),
258 @intFromEnum(Register.h0)...@intFromEnum(Register.h31) => @as(
259 Register,
260 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.h0) + @intFromEnum(Register.h0)),
261 ),
262 @intFromEnum(Register.b0)...@intFromEnum(Register.b31) => @as(
263 Register,
264 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.b0) + @intFromEnum(Register.h0)),
265 ),
266 else => unreachable,
267 };
268 }
269
270 /// Convert from a floating-point register to its 8 bit alias.
271 pub fn toB(self: Register) Register {
272 return switch (@intFromEnum(self)) {
273 @intFromEnum(Register.q0)...@intFromEnum(Register.q31) => @as(
274 Register,
275 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.q0) + @intFromEnum(Register.b0)),
276 ),
277 @intFromEnum(Register.d0)...@intFromEnum(Register.d31) => @as(
278 Register,
279 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.d0) + @intFromEnum(Register.b0)),
280 ),
281 @intFromEnum(Register.s0)...@intFromEnum(Register.s31) => @as(
282 Register,
283 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.s0) + @intFromEnum(Register.b0)),
284 ),
285 @intFromEnum(Register.h0)...@intFromEnum(Register.h31) => @as(
286 Register,
287 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.h0) + @intFromEnum(Register.b0)),
288 ),
289 @intFromEnum(Register.b0)...@intFromEnum(Register.b31) => @as(
290 Register,
291 @enumFromInt(@intFromEnum(self) - @intFromEnum(Register.b0) + @intFromEnum(Register.b0)),
292 ),
293 else => unreachable,
294 };
295 }
296
297 pub fn dwarfNum(self: Register) u5 {
298 return self.enc();
299 }
300};
301
302test "Register.enc" {
303 try testing.expectEqual(@as(u5, 0), Register.x0.enc());
304 try testing.expectEqual(@as(u5, 0), Register.w0.enc());
305
306 try testing.expectEqual(@as(u5, 31), Register.xzr.enc());
307 try testing.expectEqual(@as(u5, 31), Register.wzr.enc());
308
309 try testing.expectEqual(@as(u5, 31), Register.sp.enc());
310 try testing.expectEqual(@as(u5, 31), Register.sp.enc());
311}
312
313test "Register.size" {
314 try testing.expectEqual(@as(u8, 64), Register.x19.size());
315 try testing.expectEqual(@as(u8, 32), Register.w3.size());
316}
317
318test "Register.toX/toW" {
319 try testing.expectEqual(Register.x0, Register.w0.toX());
320 try testing.expectEqual(Register.x0, Register.x0.toX());
321
322 try testing.expectEqual(Register.w3, Register.w3.toW());
323 try testing.expectEqual(Register.w3, Register.x3.toW());
324}
325
326/// Represents an instruction in the AArch64 instruction set
327pub const Instruction = union(enum) {
328 move_wide_immediate: packed struct {
329 rd: u5,
330 imm16: u16,
331 hw: u2,
332 fixed: u6 = 0b100101,
333 opc: u2,
334 sf: u1,
335 },
336 pc_relative_address: packed struct {
337 rd: u5,
338 immhi: u19,
339 fixed: u5 = 0b10000,
340 immlo: u2,
341 op: u1,
342 },
343 load_store_register: packed struct {
344 rt: u5,
345 rn: u5,
346 offset: u12,
347 opc: u2,
348 op1: u2,
349 v: u1,
350 fixed: u3 = 0b111,
351 size: u2,
352 },
353 load_store_register_pair: packed struct {
354 rt1: u5,
355 rn: u5,
356 rt2: u5,
357 imm7: u7,
358 load: u1,
359 encoding: u2,
360 fixed: u5 = 0b101_0_0,
361 opc: u2,
362 },
363 load_literal: packed struct {
364 rt: u5,
365 imm19: u19,
366 fixed: u6 = 0b011_0_00,
367 opc: u2,
368 },
369 exception_generation: packed struct {
370 ll: u2,
371 op2: u3,
372 imm16: u16,
373 opc: u3,
374 fixed: u8 = 0b1101_0100,
375 },
376 unconditional_branch_register: packed struct {
377 op4: u5,
378 rn: u5,
379 op3: u6,
380 op2: u5,
381 opc: u4,
382 fixed: u7 = 0b1101_011,
383 },
384 unconditional_branch_immediate: packed struct {
385 imm26: u26,
386 fixed: u5 = 0b00101,
387 op: u1,
388 },
389 no_operation: packed struct {
390 fixed: u32 = 0b1101010100_0_00_011_0010_0000_000_11111,
391 },
392 logical_shifted_register: packed struct {
393 rd: u5,
394 rn: u5,
395 imm6: u6,
396 rm: u5,
397 n: u1,
398 shift: u2,
399 fixed: u5 = 0b01010,
400 opc: u2,
401 sf: u1,
402 },
403 add_subtract_immediate: packed struct {
404 rd: u5,
405 rn: u5,
406 imm12: u12,
407 sh: u1,
408 fixed: u6 = 0b100010,
409 s: u1,
410 op: u1,
411 sf: u1,
412 },
413 logical_immediate: packed struct {
414 rd: u5,
415 rn: u5,
416 imms: u6,
417 immr: u6,
418 n: u1,
419 fixed: u6 = 0b100100,
420 opc: u2,
421 sf: u1,
422 },
423 bitfield: packed struct {
424 rd: u5,
425 rn: u5,
426 imms: u6,
427 immr: u6,
428 n: u1,
429 fixed: u6 = 0b100110,
430 opc: u2,
431 sf: u1,
432 },
433 add_subtract_shifted_register: packed struct {
434 rd: u5,
435 rn: u5,
436 imm6: u6,
437 rm: u5,
438 fixed_1: u1 = 0b0,
439 shift: u2,
440 fixed_2: u5 = 0b01011,
441 s: u1,
442 op: u1,
443 sf: u1,
444 },
445 add_subtract_extended_register: packed struct {
446 rd: u5,
447 rn: u5,
448 imm3: u3,
449 option: u3,
450 rm: u5,
451 fixed: u8 = 0b01011_00_1,
452 s: u1,
453 op: u1,
454 sf: u1,
455 },
456 conditional_branch: struct {
457 cond: u4,
458 o0: u1,
459 imm19: u19,
460 o1: u1,
461 fixed: u7 = 0b0101010,
462 },
463 compare_and_branch: struct {
464 rt: u5,
465 imm19: u19,
466 op: u1,
467 fixed: u6 = 0b011010,
468 sf: u1,
469 },
470 conditional_select: struct {
471 rd: u5,
472 rn: u5,
473 op2: u2,
474 cond: u4,
475 rm: u5,
476 fixed: u8 = 0b11010100,
477 s: u1,
478 op: u1,
479 sf: u1,
480 },
481 data_processing_3_source: packed struct {
482 rd: u5,
483 rn: u5,
484 ra: u5,
485 o0: u1,
486 rm: u5,
487 op31: u3,
488 fixed: u5 = 0b11011,
489 op54: u2,
490 sf: u1,
491 },
492 data_processing_2_source: packed struct {
493 rd: u5,
494 rn: u5,
495 opcode: u6,
496 rm: u5,
497 fixed_1: u8 = 0b11010110,
498 s: u1,
499 fixed_2: u1 = 0b0,
500 sf: u1,
501 },
502
503 pub const Condition = enum(u4) {
504 /// Integer: Equal
505 /// Floating point: Equal
506 eq,
507 /// Integer: Not equal
508 /// Floating point: Not equal or unordered
509 ne,
510 /// Integer: Carry set
511 /// Floating point: Greater than, equal, or unordered
512 cs,
513 /// Integer: Carry clear
514 /// Floating point: Less than
515 cc,
516 /// Integer: Minus, negative
517 /// Floating point: Less than
518 mi,
519 /// Integer: Plus, positive or zero
520 /// Floating point: Greater than, equal, or unordered
521 pl,
522 /// Integer: Overflow
523 /// Floating point: Unordered
524 vs,
525 /// Integer: No overflow
526 /// Floating point: Ordered
527 vc,
528 /// Integer: Unsigned higher
529 /// Floating point: Greater than, or unordered
530 hi,
531 /// Integer: Unsigned lower or same
532 /// Floating point: Less than or equal
533 ls,
534 /// Integer: Signed greater than or equal
535 /// Floating point: Greater than or equal
536 ge,
537 /// Integer: Signed less than
538 /// Floating point: Less than, or unordered
539 lt,
540 /// Integer: Signed greater than
541 /// Floating point: Greater than
542 gt,
543 /// Integer: Signed less than or equal
544 /// Floating point: Less than, equal, or unordered
545 le,
546 /// Integer: Always
547 /// Floating point: Always
548 al,
549 /// Integer: Always
550 /// Floating point: Always
551 nv,
552
553 /// Converts a std.math.CompareOperator into a condition flag,
554 /// i.e. returns the condition that is true iff the result of the
555 /// comparison is true. Assumes signed comparison
556 pub fn fromCompareOperatorSigned(op: std.math.CompareOperator) Condition {
557 return switch (op) {
558 .gte => .ge,
559 .gt => .gt,
560 .neq => .ne,
561 .lt => .lt,
562 .lte => .le,
563 .eq => .eq,
564 };
565 }
566
567 /// Converts a std.math.CompareOperator into a condition flag,
568 /// i.e. returns the condition that is true iff the result of the
569 /// comparison is true. Assumes unsigned comparison
570 pub fn fromCompareOperatorUnsigned(op: std.math.CompareOperator) Condition {
571 return switch (op) {
572 .gte => .cs,
573 .gt => .hi,
574 .neq => .ne,
575 .lt => .cc,
576 .lte => .ls,
577 .eq => .eq,
578 };
579 }
580
581 /// Returns the condition which is true iff the given condition is
582 /// false (if such a condition exists)
583 pub fn negate(cond: Condition) Condition {
584 return switch (cond) {
585 .eq => .ne,
586 .ne => .eq,
587 .cs => .cc,
588 .cc => .cs,
589 .mi => .pl,
590 .pl => .mi,
591 .vs => .vc,
592 .vc => .vs,
593 .hi => .ls,
594 .ls => .hi,
595 .ge => .lt,
596 .lt => .ge,
597 .gt => .le,
598 .le => .gt,
599 .al => unreachable,
600 .nv => unreachable,
601 };
602 }
603 };
604
605 pub fn toU32(self: Instruction) u32 {
606 return switch (self) {
607 .move_wide_immediate => |v| @as(u32, @bitCast(v)),
608 .pc_relative_address => |v| @as(u32, @bitCast(v)),
609 .load_store_register => |v| @as(u32, @bitCast(v)),
610 .load_store_register_pair => |v| @as(u32, @bitCast(v)),
611 .load_literal => |v| @as(u32, @bitCast(v)),
612 .exception_generation => |v| @as(u32, @bitCast(v)),
613 .unconditional_branch_register => |v| @as(u32, @bitCast(v)),
614 .unconditional_branch_immediate => |v| @as(u32, @bitCast(v)),
615 .no_operation => |v| @as(u32, @bitCast(v)),
616 .logical_shifted_register => |v| @as(u32, @bitCast(v)),
617 .add_subtract_immediate => |v| @as(u32, @bitCast(v)),
618 .logical_immediate => |v| @as(u32, @bitCast(v)),
619 .bitfield => |v| @as(u32, @bitCast(v)),
620 .add_subtract_shifted_register => |v| @as(u32, @bitCast(v)),
621 .add_subtract_extended_register => |v| @as(u32, @bitCast(v)),
622 // TODO once packed structs work, this can be refactored
623 .conditional_branch => |v| @as(u32, v.cond) | (@as(u32, v.o0) << 4) | (@as(u32, v.imm19) << 5) | (@as(u32, v.o1) << 24) | (@as(u32, v.fixed) << 25),
624 .compare_and_branch => |v| @as(u32, v.rt) | (@as(u32, v.imm19) << 5) | (@as(u32, v.op) << 24) | (@as(u32, v.fixed) << 25) | (@as(u32, v.sf) << 31),
625 .conditional_select => |v| @as(u32, v.rd) | @as(u32, v.rn) << 5 | @as(u32, v.op2) << 10 | @as(u32, v.cond) << 12 | @as(u32, v.rm) << 16 | @as(u32, v.fixed) << 21 | @as(u32, v.s) << 29 | @as(u32, v.op) << 30 | @as(u32, v.sf) << 31,
626 .data_processing_3_source => |v| @as(u32, @bitCast(v)),
627 .data_processing_2_source => |v| @as(u32, @bitCast(v)),
628 };
629 }
630
631 fn moveWideImmediate(
632 opc: u2,
633 rd: Register,
634 imm16: u16,
635 shift: u6,
636 ) Instruction {
637 assert(shift % 16 == 0);
638 assert(!(rd.size() == 32 and shift > 16));
639 assert(!(rd.size() == 64 and shift > 48));
640
641 return Instruction{
642 .move_wide_immediate = .{
643 .rd = rd.enc(),
644 .imm16 = imm16,
645 .hw = @as(u2, @intCast(shift / 16)),
646 .opc = opc,
647 .sf = switch (rd.size()) {
648 32 => 0,
649 64 => 1,
650 else => unreachable, // unexpected register size
651 },
652 },
653 };
654 }
655
656 fn pcRelativeAddress(rd: Register, imm21: i21, op: u1) Instruction {
657 assert(rd.size() == 64);
658 const imm21_u = @as(u21, @bitCast(imm21));
659 return Instruction{
660 .pc_relative_address = .{
661 .rd = rd.enc(),
662 .immlo = @as(u2, @truncate(imm21_u)),
663 .immhi = @as(u19, @truncate(imm21_u >> 2)),
664 .op = op,
665 },
666 };
667 }
668
669 pub const LoadStoreOffsetImmediate = union(enum) {
670 post_index: i9,
671 pre_index: i9,
672 unsigned: u12,
673 };
674
675 pub const LoadStoreOffsetRegister = struct {
676 rm: u5,
677 shift: union(enum) {
678 uxtw: u2,
679 lsl: u2,
680 sxtw: u2,
681 sxtx: u2,
682 },
683 };
684
685 /// Represents the offset operand of a load or store instruction.
686 /// Data can be loaded from memory with either an immediate offset
687 /// or an offset that is stored in some register.
688 pub const LoadStoreOffset = union(enum) {
689 immediate: LoadStoreOffsetImmediate,
690 register: LoadStoreOffsetRegister,
691
692 pub const none = LoadStoreOffset{
693 .immediate = .{ .unsigned = 0 },
694 };
695
696 pub fn toU12(self: LoadStoreOffset) u12 {
697 return switch (self) {
698 .immediate => |imm_type| switch (imm_type) {
699 .post_index => |v| (@as(u12, @intCast(@as(u9, @bitCast(v)))) << 2) + 1,
700 .pre_index => |v| (@as(u12, @intCast(@as(u9, @bitCast(v)))) << 2) + 3,
701 .unsigned => |v| v,
702 },
703 .register => |r| switch (r.shift) {
704 .uxtw => |v| (@as(u12, @intCast(r.rm)) << 6) + (@as(u12, @intCast(v)) << 2) + 16 + 2050,
705 .lsl => |v| (@as(u12, @intCast(r.rm)) << 6) + (@as(u12, @intCast(v)) << 2) + 24 + 2050,
706 .sxtw => |v| (@as(u12, @intCast(r.rm)) << 6) + (@as(u12, @intCast(v)) << 2) + 48 + 2050,
707 .sxtx => |v| (@as(u12, @intCast(r.rm)) << 6) + (@as(u12, @intCast(v)) << 2) + 56 + 2050,
708 },
709 };
710 }
711
712 pub fn imm(offset: u12) LoadStoreOffset {
713 return .{
714 .immediate = .{ .unsigned = offset },
715 };
716 }
717
718 pub fn imm_post_index(offset: i9) LoadStoreOffset {
719 return .{
720 .immediate = .{ .post_index = offset },
721 };
722 }
723
724 pub fn imm_pre_index(offset: i9) LoadStoreOffset {
725 return .{
726 .immediate = .{ .pre_index = offset },
727 };
728 }
729
730 pub fn reg(rm: Register) LoadStoreOffset {
731 return .{
732 .register = .{
733 .rm = rm.enc(),
734 .shift = .{
735 .lsl = 0,
736 },
737 },
738 };
739 }
740
741 pub fn reg_uxtw(rm: Register, shift: u2) LoadStoreOffset {
742 assert(rm.size() == 32 and (shift == 0 or shift == 2));
743 return .{
744 .register = .{
745 .rm = rm.enc(),
746 .shift = .{
747 .uxtw = shift,
748 },
749 },
750 };
751 }
752
753 pub fn reg_lsl(rm: Register, shift: u2) LoadStoreOffset {
754 assert(rm.size() == 64 and (shift == 0 or shift == 3));
755 return .{
756 .register = .{
757 .rm = rm.enc(),
758 .shift = .{
759 .lsl = shift,
760 },
761 },
762 };
763 }
764
765 pub fn reg_sxtw(rm: Register, shift: u2) LoadStoreOffset {
766 assert(rm.size() == 32 and (shift == 0 or shift == 2));
767 return .{
768 .register = .{
769 .rm = rm.enc(),
770 .shift = .{
771 .sxtw = shift,
772 },
773 },
774 };
775 }
776
777 pub fn reg_sxtx(rm: Register, shift: u2) LoadStoreOffset {
778 assert(rm.size() == 64 and (shift == 0 or shift == 3));
779 return .{
780 .register = .{
781 .rm = rm.enc(),
782 .shift = .{
783 .sxtx = shift,
784 },
785 },
786 };
787 }
788 };
789
790 /// Which kind of load/store to perform
791 const LoadStoreVariant = enum {
792 /// 32 bits or 64 bits
793 str,
794 /// 8 bits, zero-extended
795 strb,
796 /// 16 bits, zero-extended
797 strh,
798 /// 32 bits or 64 bits
799 ldr,
800 /// 8 bits, zero-extended
801 ldrb,
802 /// 16 bits, zero-extended
803 ldrh,
804 /// 8 bits, sign extended
805 ldrsb,
806 /// 16 bits, sign extended
807 ldrsh,
808 /// 32 bits, sign extended
809 ldrsw,
810 };
811
812 fn loadStoreRegister(
813 rt: Register,
814 rn: Register,
815 offset: LoadStoreOffset,
816 variant: LoadStoreVariant,
817 ) Instruction {
818 assert(rn.size() == 64);
819 assert(rn.id() != Register.xzr.id());
820
821 const off = offset.toU12();
822
823 const op1: u2 = blk: {
824 switch (offset) {
825 .immediate => |imm| switch (imm) {
826 .unsigned => break :blk 0b01,
827 else => {},
828 },
829 else => {},
830 }
831 break :blk 0b00;
832 };
833
834 const opc: u2 = blk: {
835 switch (variant) {
836 .ldr, .ldrh, .ldrb => break :blk 0b01,
837 .str, .strh, .strb => break :blk 0b00,
838 .ldrsb,
839 .ldrsh,
840 => switch (rt.size()) {
841 32 => break :blk 0b11,
842 64 => break :blk 0b10,
843 else => unreachable, // unexpected register size
844 },
845 .ldrsw => break :blk 0b10,
846 }
847 };
848
849 const size: u2 = blk: {
850 switch (variant) {
851 .ldr, .str => switch (rt.size()) {
852 32 => break :blk 0b10,
853 64 => break :blk 0b11,
854 else => unreachable, // unexpected register size
855 },
856 .ldrsw => break :blk 0b10,
857 .ldrh, .ldrsh, .strh => break :blk 0b01,
858 .ldrb, .ldrsb, .strb => break :blk 0b00,
859 }
860 };
861
862 return Instruction{
863 .load_store_register = .{
864 .rt = rt.enc(),
865 .rn = rn.enc(),
866 .offset = off,
867 .opc = opc,
868 .op1 = op1,
869 .v = 0,
870 .size = size,
871 },
872 };
873 }
874
875 fn loadStoreRegisterPair(
876 rt1: Register,
877 rt2: Register,
878 rn: Register,
879 offset: i9,
880 encoding: u2,
881 load: bool,
882 ) Instruction {
883 assert(rn.size() == 64);
884 assert(rn.id() != Register.xzr.id());
885
886 switch (rt1.size()) {
887 32 => {
888 assert(-256 <= offset and offset <= 252);
889 const imm7 = @as(u7, @truncate(@as(u9, @bitCast(offset >> 2))));
890 return Instruction{
891 .load_store_register_pair = .{
892 .rt1 = rt1.enc(),
893 .rn = rn.enc(),
894 .rt2 = rt2.enc(),
895 .imm7 = imm7,
896 .load = @intFromBool(load),
897 .encoding = encoding,
898 .opc = 0b00,
899 },
900 };
901 },
902 64 => {
903 assert(-512 <= offset and offset <= 504);
904 const imm7 = @as(u7, @truncate(@as(u9, @bitCast(offset >> 3))));
905 return Instruction{
906 .load_store_register_pair = .{
907 .rt1 = rt1.enc(),
908 .rn = rn.enc(),
909 .rt2 = rt2.enc(),
910 .imm7 = imm7,
911 .load = @intFromBool(load),
912 .encoding = encoding,
913 .opc = 0b10,
914 },
915 };
916 },
917 else => unreachable, // unexpected register size
918 }
919 }
920
921 fn loadLiteral(rt: Register, imm19: u19) Instruction {
922 return Instruction{
923 .load_literal = .{
924 .rt = rt.enc(),
925 .imm19 = imm19,
926 .opc = switch (rt.size()) {
927 32 => 0b00,
928 64 => 0b01,
929 else => unreachable, // unexpected register size
930 },
931 },
932 };
933 }
934
935 fn exceptionGeneration(
936 opc: u3,
937 op2: u3,
938 ll: u2,
939 imm16: u16,
940 ) Instruction {
941 return Instruction{
942 .exception_generation = .{
943 .ll = ll,
944 .op2 = op2,
945 .imm16 = imm16,
946 .opc = opc,
947 },
948 };
949 }
950
951 fn unconditionalBranchRegister(
952 opc: u4,
953 op2: u5,
954 op3: u6,
955 rn: Register,
956 op4: u5,
957 ) Instruction {
958 assert(rn.size() == 64);
959
960 return Instruction{
961 .unconditional_branch_register = .{
962 .op4 = op4,
963 .rn = rn.enc(),
964 .op3 = op3,
965 .op2 = op2,
966 .opc = opc,
967 },
968 };
969 }
970
971 fn unconditionalBranchImmediate(
972 op: u1,
973 offset: i28,
974 ) Instruction {
975 return Instruction{
976 .unconditional_branch_immediate = .{
977 .imm26 = @as(u26, @bitCast(@as(i26, @intCast(offset >> 2)))),
978 .op = op,
979 },
980 };
981 }
982
983 pub const LogicalShiftedRegisterShift = enum(u2) { lsl, lsr, asr, ror };
984
985 fn logicalShiftedRegister(
986 opc: u2,
987 n: u1,
988 rd: Register,
989 rn: Register,
990 rm: Register,
991 shift: LogicalShiftedRegisterShift,
992 amount: u6,
993 ) Instruction {
994 assert(rd.size() == rn.size());
995 assert(rd.size() == rm.size());
996 if (rd.size() == 32) assert(amount < 32);
997
998 return Instruction{
999 .logical_shifted_register = .{
1000 .rd = rd.enc(),
1001 .rn = rn.enc(),
1002 .imm6 = amount,
1003 .rm = rm.enc(),
1004 .n = n,
1005 .shift = @intFromEnum(shift),
1006 .opc = opc,
1007 .sf = switch (rd.size()) {
1008 32 => 0b0,
1009 64 => 0b1,
1010 else => unreachable,
1011 },
1012 },
1013 };
1014 }
1015
1016 fn addSubtractImmediate(
1017 op: u1,
1018 s: u1,
1019 rd: Register,
1020 rn: Register,
1021 imm12: u12,
1022 shift: bool,
1023 ) Instruction {
1024 assert(rd.size() == rn.size());
1025 assert(rn.id() != Register.xzr.id());
1026
1027 return Instruction{
1028 .add_subtract_immediate = .{
1029 .rd = rd.enc(),
1030 .rn = rn.enc(),
1031 .imm12 = imm12,
1032 .sh = @intFromBool(shift),
1033 .s = s,
1034 .op = op,
1035 .sf = switch (rd.size()) {
1036 32 => 0b0,
1037 64 => 0b1,
1038 else => unreachable, // unexpected register size
1039 },
1040 },
1041 };
1042 }
1043
1044 fn logicalImmediate(
1045 opc: u2,
1046 rd: Register,
1047 rn: Register,
1048 imms: u6,
1049 immr: u6,
1050 n: u1,
1051 ) Instruction {
1052 assert(rd.size() == rn.size());
1053 assert(!(rd.size() == 32 and n != 0));
1054
1055 return Instruction{
1056 .logical_immediate = .{
1057 .rd = rd.enc(),
1058 .rn = rn.enc(),
1059 .imms = imms,
1060 .immr = immr,
1061 .n = n,
1062 .opc = opc,
1063 .sf = switch (rd.size()) {
1064 32 => 0b0,
1065 64 => 0b1,
1066 else => unreachable, // unexpected register size
1067 },
1068 },
1069 };
1070 }
1071
1072 fn initBitfield(
1073 opc: u2,
1074 n: u1,
1075 rd: Register,
1076 rn: Register,
1077 immr: u6,
1078 imms: u6,
1079 ) Instruction {
1080 assert(rd.size() == rn.size());
1081 assert(!(rd.size() == 64 and n != 1));
1082 assert(!(rd.size() == 32 and (n != 0 or immr >> 5 != 0 or immr >> 5 != 0)));
1083
1084 return Instruction{
1085 .bitfield = .{
1086 .rd = rd.enc(),
1087 .rn = rn.enc(),
1088 .imms = imms,
1089 .immr = immr,
1090 .n = n,
1091 .opc = opc,
1092 .sf = switch (rd.size()) {
1093 32 => 0b0,
1094 64 => 0b1,
1095 else => unreachable, // unexpected register size
1096 },
1097 },
1098 };
1099 }
1100
1101 pub const AddSubtractShiftedRegisterShift = enum(u2) { lsl, lsr, asr, _ };
1102
1103 fn addSubtractShiftedRegister(
1104 op: u1,
1105 s: u1,
1106 shift: AddSubtractShiftedRegisterShift,
1107 rd: Register,
1108 rn: Register,
1109 rm: Register,
1110 imm6: u6,
1111 ) Instruction {
1112 assert(rd.size() == rn.size());
1113 assert(rd.size() == rm.size());
1114
1115 return Instruction{
1116 .add_subtract_shifted_register = .{
1117 .rd = rd.enc(),
1118 .rn = rn.enc(),
1119 .imm6 = imm6,
1120 .rm = rm.enc(),
1121 .shift = @intFromEnum(shift),
1122 .s = s,
1123 .op = op,
1124 .sf = switch (rd.size()) {
1125 32 => 0b0,
1126 64 => 0b1,
1127 else => unreachable, // unexpected register size
1128 },
1129 },
1130 };
1131 }
1132
1133 pub const AddSubtractExtendedRegisterOption = enum(u3) {
1134 uxtb,
1135 uxth,
1136 uxtw,
1137 uxtx, // serves also as lsl
1138 sxtb,
1139 sxth,
1140 sxtw,
1141 sxtx,
1142 };
1143
1144 fn addSubtractExtendedRegister(
1145 op: u1,
1146 s: u1,
1147 rd: Register,
1148 rn: Register,
1149 rm: Register,
1150 extend: AddSubtractExtendedRegisterOption,
1151 imm3: u3,
1152 ) Instruction {
1153 return Instruction{
1154 .add_subtract_extended_register = .{
1155 .rd = rd.enc(),
1156 .rn = rn.enc(),
1157 .imm3 = imm3,
1158 .option = @intFromEnum(extend),
1159 .rm = rm.enc(),
1160 .s = s,
1161 .op = op,
1162 .sf = switch (rd.size()) {
1163 32 => 0b0,
1164 64 => 0b1,
1165 else => unreachable, // unexpected register size
1166 },
1167 },
1168 };
1169 }
1170
1171 fn conditionalBranch(
1172 o0: u1,
1173 o1: u1,
1174 cond: Condition,
1175 offset: i21,
1176 ) Instruction {
1177 assert(offset & 0b11 == 0b00);
1178
1179 return Instruction{
1180 .conditional_branch = .{
1181 .cond = @intFromEnum(cond),
1182 .o0 = o0,
1183 .imm19 = @as(u19, @bitCast(@as(i19, @intCast(offset >> 2)))),
1184 .o1 = o1,
1185 },
1186 };
1187 }
1188
1189 fn compareAndBranch(
1190 op: u1,
1191 rt: Register,
1192 offset: i21,
1193 ) Instruction {
1194 assert(offset & 0b11 == 0b00);
1195
1196 return Instruction{
1197 .compare_and_branch = .{
1198 .rt = rt.enc(),
1199 .imm19 = @as(u19, @bitCast(@as(i19, @intCast(offset >> 2)))),
1200 .op = op,
1201 .sf = switch (rt.size()) {
1202 32 => 0b0,
1203 64 => 0b1,
1204 else => unreachable, // unexpected register size
1205 },
1206 },
1207 };
1208 }
1209
1210 fn conditionalSelect(
1211 op2: u2,
1212 op: u1,
1213 s: u1,
1214 rd: Register,
1215 rn: Register,
1216 rm: Register,
1217 cond: Condition,
1218 ) Instruction {
1219 assert(rd.size() == rn.size());
1220 assert(rd.size() == rm.size());
1221
1222 return Instruction{
1223 .conditional_select = .{
1224 .rd = rd.enc(),
1225 .rn = rn.enc(),
1226 .op2 = op2,
1227 .cond = @intFromEnum(cond),
1228 .rm = rm.enc(),
1229 .s = s,
1230 .op = op,
1231 .sf = switch (rd.size()) {
1232 32 => 0b0,
1233 64 => 0b1,
1234 else => unreachable, // unexpected register size
1235 },
1236 },
1237 };
1238 }
1239
1240 fn dataProcessing3Source(
1241 op54: u2,
1242 op31: u3,
1243 o0: u1,
1244 rd: Register,
1245 rn: Register,
1246 rm: Register,
1247 ra: Register,
1248 ) Instruction {
1249 return Instruction{
1250 .data_processing_3_source = .{
1251 .rd = rd.enc(),
1252 .rn = rn.enc(),
1253 .ra = ra.enc(),
1254 .o0 = o0,
1255 .rm = rm.enc(),
1256 .op31 = op31,
1257 .op54 = op54,
1258 .sf = switch (rd.size()) {
1259 32 => 0b0,
1260 64 => 0b1,
1261 else => unreachable, // unexpected register size
1262 },
1263 },
1264 };
1265 }
1266
1267 fn dataProcessing2Source(
1268 s: u1,
1269 opcode: u6,
1270 rd: Register,
1271 rn: Register,
1272 rm: Register,
1273 ) Instruction {
1274 assert(rd.size() == rn.size());
1275 assert(rd.size() == rm.size());
1276
1277 return Instruction{
1278 .data_processing_2_source = .{
1279 .rd = rd.enc(),
1280 .rn = rn.enc(),
1281 .opcode = opcode,
1282 .rm = rm.enc(),
1283 .s = s,
1284 .sf = switch (rd.size()) {
1285 32 => 0b0,
1286 64 => 0b1,
1287 else => unreachable, // unexpected register size
1288 },
1289 },
1290 };
1291 }
1292
1293 // Helper functions for assembly syntax functions
1294
1295 // Move wide (immediate)
1296
1297 pub fn movn(rd: Register, imm16: u16, shift: u6) Instruction {
1298 return moveWideImmediate(0b00, rd, imm16, shift);
1299 }
1300
1301 pub fn movz(rd: Register, imm16: u16, shift: u6) Instruction {
1302 return moveWideImmediate(0b10, rd, imm16, shift);
1303 }
1304
1305 pub fn movk(rd: Register, imm16: u16, shift: u6) Instruction {
1306 return moveWideImmediate(0b11, rd, imm16, shift);
1307 }
1308
1309 // PC relative address
1310
1311 pub fn adr(rd: Register, imm21: i21) Instruction {
1312 return pcRelativeAddress(rd, imm21, 0b0);
1313 }
1314
1315 pub fn adrp(rd: Register, imm21: i21) Instruction {
1316 return pcRelativeAddress(rd, imm21, 0b1);
1317 }
1318
1319 // Load or store register
1320
1321 pub fn ldrLiteral(rt: Register, literal: u19) Instruction {
1322 return loadLiteral(rt, literal);
1323 }
1324
1325 pub fn ldr(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1326 return loadStoreRegister(rt, rn, offset, .ldr);
1327 }
1328
1329 pub fn ldrh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1330 return loadStoreRegister(rt, rn, offset, .ldrh);
1331 }
1332
1333 pub fn ldrb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1334 return loadStoreRegister(rt, rn, offset, .ldrb);
1335 }
1336
1337 pub fn ldrsb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1338 return loadStoreRegister(rt, rn, offset, .ldrsb);
1339 }
1340
1341 pub fn ldrsh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1342 return loadStoreRegister(rt, rn, offset, .ldrsh);
1343 }
1344
1345 pub fn ldrsw(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1346 return loadStoreRegister(rt, rn, offset, .ldrsw);
1347 }
1348
1349 pub fn str(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1350 return loadStoreRegister(rt, rn, offset, .str);
1351 }
1352
1353 pub fn strh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1354 return loadStoreRegister(rt, rn, offset, .strh);
1355 }
1356
1357 pub fn strb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
1358 return loadStoreRegister(rt, rn, offset, .strb);
1359 }
1360
1361 // Load or store pair of registers
1362
1363 pub const LoadStorePairOffset = struct {
1364 encoding: enum(u2) {
1365 post_index = 0b01,
1366 signed = 0b10,
1367 pre_index = 0b11,
1368 },
1369 offset: i9,
1370
1371 pub fn none() LoadStorePairOffset {
1372 return .{ .encoding = .signed, .offset = 0 };
1373 }
1374
1375 pub fn post_index(imm: i9) LoadStorePairOffset {
1376 return .{ .encoding = .post_index, .offset = imm };
1377 }
1378
1379 pub fn pre_index(imm: i9) LoadStorePairOffset {
1380 return .{ .encoding = .pre_index, .offset = imm };
1381 }
1382
1383 pub fn signed(imm: i9) LoadStorePairOffset {
1384 return .{ .encoding = .signed, .offset = imm };
1385 }
1386 };
1387
1388 pub fn ldp(rt1: Register, rt2: Register, rn: Register, offset: LoadStorePairOffset) Instruction {
1389 return loadStoreRegisterPair(rt1, rt2, rn, offset.offset, @intFromEnum(offset.encoding), true);
1390 }
1391
1392 pub fn ldnp(rt1: Register, rt2: Register, rn: Register, offset: i9) Instruction {
1393 return loadStoreRegisterPair(rt1, rt2, rn, offset, 0, true);
1394 }
1395
1396 pub fn stp(rt1: Register, rt2: Register, rn: Register, offset: LoadStorePairOffset) Instruction {
1397 return loadStoreRegisterPair(rt1, rt2, rn, offset.offset, @intFromEnum(offset.encoding), false);
1398 }
1399
1400 pub fn stnp(rt1: Register, rt2: Register, rn: Register, offset: i9) Instruction {
1401 return loadStoreRegisterPair(rt1, rt2, rn, offset, 0, false);
1402 }
1403
1404 // Exception generation
1405
1406 pub fn svc(imm16: u16) Instruction {
1407 return exceptionGeneration(0b000, 0b000, 0b01, imm16);
1408 }
1409
1410 pub fn hvc(imm16: u16) Instruction {
1411 return exceptionGeneration(0b000, 0b000, 0b10, imm16);
1412 }
1413
1414 pub fn smc(imm16: u16) Instruction {
1415 return exceptionGeneration(0b000, 0b000, 0b11, imm16);
1416 }
1417
1418 pub fn brk(imm16: u16) Instruction {
1419 return exceptionGeneration(0b001, 0b000, 0b00, imm16);
1420 }
1421
1422 pub fn hlt(imm16: u16) Instruction {
1423 return exceptionGeneration(0b010, 0b000, 0b00, imm16);
1424 }
1425
1426 // Unconditional branch (register)
1427
1428 pub fn br(rn: Register) Instruction {
1429 return unconditionalBranchRegister(0b0000, 0b11111, 0b000000, rn, 0b00000);
1430 }
1431
1432 pub fn blr(rn: Register) Instruction {
1433 return unconditionalBranchRegister(0b0001, 0b11111, 0b000000, rn, 0b00000);
1434 }
1435
1436 pub fn ret(rn: ?Register) Instruction {
1437 return unconditionalBranchRegister(0b0010, 0b11111, 0b000000, rn orelse .x30, 0b00000);
1438 }
1439
1440 // Unconditional branch (immediate)
1441
1442 pub fn b(offset: i28) Instruction {
1443 return unconditionalBranchImmediate(0, offset);
1444 }
1445
1446 pub fn bl(offset: i28) Instruction {
1447 return unconditionalBranchImmediate(1, offset);
1448 }
1449
1450 // Nop
1451
1452 pub fn nop() Instruction {
1453 return Instruction{ .no_operation = .{} };
1454 }
1455
1456 // Logical (shifted register)
1457
1458 pub fn andShiftedRegister(
1459 rd: Register,
1460 rn: Register,
1461 rm: Register,
1462 shift: LogicalShiftedRegisterShift,
1463 amount: u6,
1464 ) Instruction {
1465 return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount);
1466 }
1467
1468 pub fn bicShiftedRegister(
1469 rd: Register,
1470 rn: Register,
1471 rm: Register,
1472 shift: LogicalShiftedRegisterShift,
1473 amount: u6,
1474 ) Instruction {
1475 return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount);
1476 }
1477
1478 pub fn orrShiftedRegister(
1479 rd: Register,
1480 rn: Register,
1481 rm: Register,
1482 shift: LogicalShiftedRegisterShift,
1483 amount: u6,
1484 ) Instruction {
1485 return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount);
1486 }
1487
1488 pub fn ornShiftedRegister(
1489 rd: Register,
1490 rn: Register,
1491 rm: Register,
1492 shift: LogicalShiftedRegisterShift,
1493 amount: u6,
1494 ) Instruction {
1495 return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount);
1496 }
1497
1498 pub fn eorShiftedRegister(
1499 rd: Register,
1500 rn: Register,
1501 rm: Register,
1502 shift: LogicalShiftedRegisterShift,
1503 amount: u6,
1504 ) Instruction {
1505 return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount);
1506 }
1507
1508 pub fn eonShiftedRegister(
1509 rd: Register,
1510 rn: Register,
1511 rm: Register,
1512 shift: LogicalShiftedRegisterShift,
1513 amount: u6,
1514 ) Instruction {
1515 return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount);
1516 }
1517
1518 pub fn andsShiftedRegister(
1519 rd: Register,
1520 rn: Register,
1521 rm: Register,
1522 shift: LogicalShiftedRegisterShift,
1523 amount: u6,
1524 ) Instruction {
1525 return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount);
1526 }
1527
1528 pub fn bicsShiftedRegister(
1529 rd: Register,
1530 rn: Register,
1531 rm: Register,
1532 shift: LogicalShiftedRegisterShift,
1533 amount: u6,
1534 ) Instruction {
1535 return logicalShiftedRegister(0b11, 0b1, rd, rn, rm, shift, amount);
1536 }
1537
1538 // Add/subtract (immediate)
1539
1540 pub fn add(rd: Register, rn: Register, imm: u12, shift: bool) Instruction {
1541 return addSubtractImmediate(0b0, 0b0, rd, rn, imm, shift);
1542 }
1543
1544 pub fn adds(rd: Register, rn: Register, imm: u12, shift: bool) Instruction {
1545 return addSubtractImmediate(0b0, 0b1, rd, rn, imm, shift);
1546 }
1547
1548 pub fn sub(rd: Register, rn: Register, imm: u12, shift: bool) Instruction {
1549 return addSubtractImmediate(0b1, 0b0, rd, rn, imm, shift);
1550 }
1551
1552 pub fn subs(rd: Register, rn: Register, imm: u12, shift: bool) Instruction {
1553 return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift);
1554 }
1555
1556 // Logical (immediate)
1557
1558 pub fn andImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1559 return logicalImmediate(0b00, rd, rn, imms, immr, n);
1560 }
1561
1562 pub fn orrImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1563 return logicalImmediate(0b01, rd, rn, imms, immr, n);
1564 }
1565
1566 pub fn eorImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1567 return logicalImmediate(0b10, rd, rn, imms, immr, n);
1568 }
1569
1570 pub fn andsImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction {
1571 return logicalImmediate(0b11, rd, rn, imms, immr, n);
1572 }
1573
1574 // Bitfield
1575
1576 pub fn sbfm(rd: Register, rn: Register, immr: u6, imms: u6) Instruction {
1577 const n: u1 = switch (rd.size()) {
1578 32 => 0b0,
1579 64 => 0b1,
1580 else => unreachable, // unexpected register size
1581 };
1582 return initBitfield(0b00, n, rd, rn, immr, imms);
1583 }
1584
1585 pub fn bfm(rd: Register, rn: Register, immr: u6, imms: u6) Instruction {
1586 const n: u1 = switch (rd.size()) {
1587 32 => 0b0,
1588 64 => 0b1,
1589 else => unreachable, // unexpected register size
1590 };
1591 return initBitfield(0b01, n, rd, rn, immr, imms);
1592 }
1593
1594 pub fn ubfm(rd: Register, rn: Register, immr: u6, imms: u6) Instruction {
1595 const n: u1 = switch (rd.size()) {
1596 32 => 0b0,
1597 64 => 0b1,
1598 else => unreachable, // unexpected register size
1599 };
1600 return initBitfield(0b10, n, rd, rn, immr, imms);
1601 }
1602
1603 pub fn asrImmediate(rd: Register, rn: Register, shift: u6) Instruction {
1604 const imms = @as(u6, @intCast(rd.size() - 1));
1605 return sbfm(rd, rn, shift, imms);
1606 }
1607
1608 pub fn sbfx(rd: Register, rn: Register, lsb: u6, width: u7) Instruction {
1609 return sbfm(rd, rn, lsb, @as(u6, @intCast(lsb + width - 1)));
1610 }
1611
1612 pub fn sxtb(rd: Register, rn: Register) Instruction {
1613 return sbfm(rd, rn, 0, 7);
1614 }
1615
1616 pub fn sxth(rd: Register, rn: Register) Instruction {
1617 return sbfm(rd, rn, 0, 15);
1618 }
1619
1620 pub fn sxtw(rd: Register, rn: Register) Instruction {
1621 assert(rd.size() == 64);
1622 return sbfm(rd, rn, 0, 31);
1623 }
1624
1625 pub fn lslImmediate(rd: Register, rn: Register, shift: u6) Instruction {
1626 const size = @as(u6, @intCast(rd.size() - 1));
1627 return ubfm(rd, rn, size - shift + 1, size - shift);
1628 }
1629
1630 pub fn lsrImmediate(rd: Register, rn: Register, shift: u6) Instruction {
1631 const imms = @as(u6, @intCast(rd.size() - 1));
1632 return ubfm(rd, rn, shift, imms);
1633 }
1634
1635 pub fn ubfx(rd: Register, rn: Register, lsb: u6, width: u7) Instruction {
1636 return ubfm(rd, rn, lsb, @as(u6, @intCast(lsb + width - 1)));
1637 }
1638
1639 pub fn uxtb(rd: Register, rn: Register) Instruction {
1640 return ubfm(rd, rn, 0, 7);
1641 }
1642
1643 pub fn uxth(rd: Register, rn: Register) Instruction {
1644 return ubfm(rd, rn, 0, 15);
1645 }
1646
1647 // Add/subtract (shifted register)
1648
1649 pub fn addShiftedRegister(
1650 rd: Register,
1651 rn: Register,
1652 rm: Register,
1653 shift: AddSubtractShiftedRegisterShift,
1654 imm6: u6,
1655 ) Instruction {
1656 return addSubtractShiftedRegister(0b0, 0b0, shift, rd, rn, rm, imm6);
1657 }
1658
1659 pub fn addsShiftedRegister(
1660 rd: Register,
1661 rn: Register,
1662 rm: Register,
1663 shift: AddSubtractShiftedRegisterShift,
1664 imm6: u6,
1665 ) Instruction {
1666 return addSubtractShiftedRegister(0b0, 0b1, shift, rd, rn, rm, imm6);
1667 }
1668
1669 pub fn subShiftedRegister(
1670 rd: Register,
1671 rn: Register,
1672 rm: Register,
1673 shift: AddSubtractShiftedRegisterShift,
1674 imm6: u6,
1675 ) Instruction {
1676 return addSubtractShiftedRegister(0b1, 0b0, shift, rd, rn, rm, imm6);
1677 }
1678
1679 pub fn subsShiftedRegister(
1680 rd: Register,
1681 rn: Register,
1682 rm: Register,
1683 shift: AddSubtractShiftedRegisterShift,
1684 imm6: u6,
1685 ) Instruction {
1686 return addSubtractShiftedRegister(0b1, 0b1, shift, rd, rn, rm, imm6);
1687 }
1688
1689 // Add/subtract (extended register)
1690
1691 pub fn addExtendedRegister(
1692 rd: Register,
1693 rn: Register,
1694 rm: Register,
1695 extend: AddSubtractExtendedRegisterOption,
1696 imm3: u3,
1697 ) Instruction {
1698 return addSubtractExtendedRegister(0b0, 0b0, rd, rn, rm, extend, imm3);
1699 }
1700
1701 pub fn addsExtendedRegister(
1702 rd: Register,
1703 rn: Register,
1704 rm: Register,
1705 extend: AddSubtractExtendedRegisterOption,
1706 imm3: u3,
1707 ) Instruction {
1708 return addSubtractExtendedRegister(0b0, 0b1, rd, rn, rm, extend, imm3);
1709 }
1710
1711 pub fn subExtendedRegister(
1712 rd: Register,
1713 rn: Register,
1714 rm: Register,
1715 extend: AddSubtractExtendedRegisterOption,
1716 imm3: u3,
1717 ) Instruction {
1718 return addSubtractExtendedRegister(0b1, 0b0, rd, rn, rm, extend, imm3);
1719 }
1720
1721 pub fn subsExtendedRegister(
1722 rd: Register,
1723 rn: Register,
1724 rm: Register,
1725 extend: AddSubtractExtendedRegisterOption,
1726 imm3: u3,
1727 ) Instruction {
1728 return addSubtractExtendedRegister(0b1, 0b1, rd, rn, rm, extend, imm3);
1729 }
1730
1731 // Conditional branch
1732
1733 pub fn bCond(cond: Condition, offset: i21) Instruction {
1734 return conditionalBranch(0b0, 0b0, cond, offset);
1735 }
1736
1737 // Compare and branch
1738
1739 pub fn cbz(rt: Register, offset: i21) Instruction {
1740 return compareAndBranch(0b0, rt, offset);
1741 }
1742
1743 pub fn cbnz(rt: Register, offset: i21) Instruction {
1744 return compareAndBranch(0b1, rt, offset);
1745 }
1746
1747 // Conditional select
1748
1749 pub fn csel(rd: Register, rn: Register, rm: Register, cond: Condition) Instruction {
1750 return conditionalSelect(0b00, 0b0, 0b0, rd, rn, rm, cond);
1751 }
1752
1753 pub fn csinc(rd: Register, rn: Register, rm: Register, cond: Condition) Instruction {
1754 return conditionalSelect(0b01, 0b0, 0b0, rd, rn, rm, cond);
1755 }
1756
1757 pub fn csinv(rd: Register, rn: Register, rm: Register, cond: Condition) Instruction {
1758 return conditionalSelect(0b00, 0b1, 0b0, rd, rn, rm, cond);
1759 }
1760
1761 pub fn csneg(rd: Register, rn: Register, rm: Register, cond: Condition) Instruction {
1762 return conditionalSelect(0b01, 0b1, 0b0, rd, rn, rm, cond);
1763 }
1764
1765 // Data processing (3 source)
1766
1767 pub fn madd(rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
1768 return dataProcessing3Source(0b00, 0b000, 0b0, rd, rn, rm, ra);
1769 }
1770
1771 pub fn smaddl(rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
1772 assert(rd.size() == 64 and rn.size() == 32 and rm.size() == 32 and ra.size() == 64);
1773 return dataProcessing3Source(0b00, 0b001, 0b0, rd, rn, rm, ra);
1774 }
1775
1776 pub fn umaddl(rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
1777 assert(rd.size() == 64 and rn.size() == 32 and rm.size() == 32 and ra.size() == 64);
1778 return dataProcessing3Source(0b00, 0b101, 0b0, rd, rn, rm, ra);
1779 }
1780
1781 pub fn msub(rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
1782 return dataProcessing3Source(0b00, 0b000, 0b1, rd, rn, rm, ra);
1783 }
1784
1785 pub fn mul(rd: Register, rn: Register, rm: Register) Instruction {
1786 return madd(rd, rn, rm, .xzr);
1787 }
1788
1789 pub fn smull(rd: Register, rn: Register, rm: Register) Instruction {
1790 return smaddl(rd, rn, rm, .xzr);
1791 }
1792
1793 pub fn smulh(rd: Register, rn: Register, rm: Register) Instruction {
1794 assert(rd.size() == 64);
1795 return dataProcessing3Source(0b00, 0b010, 0b0, rd, rn, rm, .xzr);
1796 }
1797
1798 pub fn umull(rd: Register, rn: Register, rm: Register) Instruction {
1799 return umaddl(rd, rn, rm, .xzr);
1800 }
1801
1802 pub fn umulh(rd: Register, rn: Register, rm: Register) Instruction {
1803 assert(rd.size() == 64);
1804 return dataProcessing3Source(0b00, 0b110, 0b0, rd, rn, rm, .xzr);
1805 }
1806
1807 pub fn mneg(rd: Register, rn: Register, rm: Register) Instruction {
1808 return msub(rd, rn, rm, .xzr);
1809 }
1810
1811 // Data processing (2 source)
1812
1813 pub fn udiv(rd: Register, rn: Register, rm: Register) Instruction {
1814 return dataProcessing2Source(0b0, 0b000010, rd, rn, rm);
1815 }
1816
1817 pub fn sdiv(rd: Register, rn: Register, rm: Register) Instruction {
1818 return dataProcessing2Source(0b0, 0b000011, rd, rn, rm);
1819 }
1820
1821 pub fn lslv(rd: Register, rn: Register, rm: Register) Instruction {
1822 return dataProcessing2Source(0b0, 0b001000, rd, rn, rm);
1823 }
1824
1825 pub fn lsrv(rd: Register, rn: Register, rm: Register) Instruction {
1826 return dataProcessing2Source(0b0, 0b001001, rd, rn, rm);
1827 }
1828
1829 pub fn asrv(rd: Register, rn: Register, rm: Register) Instruction {
1830 return dataProcessing2Source(0b0, 0b001010, rd, rn, rm);
1831 }
1832
1833 pub const asrRegister = asrv;
1834 pub const lslRegister = lslv;
1835 pub const lsrRegister = lsrv;
1836};
1837
1838test {
1839 testing.refAllDecls(@This());
1840}
1841
1842test "serialize instructions" {
1843 const Testcase = struct {
1844 inst: Instruction,
1845 expected: u32,
1846 };
1847
1848 const testcases = [_]Testcase{
1849 .{ // orr x0, xzr, x1
1850 .inst = Instruction.orrShiftedRegister(.x0, .xzr, .x1, .lsl, 0),
1851 .expected = 0b1_01_01010_00_0_00001_000000_11111_00000,
1852 },
1853 .{ // orn x0, xzr, x1
1854 .inst = Instruction.ornShiftedRegister(.x0, .xzr, .x1, .lsl, 0),
1855 .expected = 0b1_01_01010_00_1_00001_000000_11111_00000,
1856 },
1857 .{ // movz x1, #4
1858 .inst = Instruction.movz(.x1, 4, 0),
1859 .expected = 0b1_10_100101_00_0000000000000100_00001,
1860 },
1861 .{ // movz x1, #4, lsl 16
1862 .inst = Instruction.movz(.x1, 4, 16),
1863 .expected = 0b1_10_100101_01_0000000000000100_00001,
1864 },
1865 .{ // movz x1, #4, lsl 32
1866 .inst = Instruction.movz(.x1, 4, 32),
1867 .expected = 0b1_10_100101_10_0000000000000100_00001,
1868 },
1869 .{ // movz x1, #4, lsl 48
1870 .inst = Instruction.movz(.x1, 4, 48),
1871 .expected = 0b1_10_100101_11_0000000000000100_00001,
1872 },
1873 .{ // movz w1, #4
1874 .inst = Instruction.movz(.w1, 4, 0),
1875 .expected = 0b0_10_100101_00_0000000000000100_00001,
1876 },
1877 .{ // movz w1, #4, lsl 16
1878 .inst = Instruction.movz(.w1, 4, 16),
1879 .expected = 0b0_10_100101_01_0000000000000100_00001,
1880 },
1881 .{ // svc #0
1882 .inst = Instruction.svc(0),
1883 .expected = 0b1101_0100_000_0000000000000000_00001,
1884 },
1885 .{ // svc #0x80 ; typical on Darwin
1886 .inst = Instruction.svc(0x80),
1887 .expected = 0b1101_0100_000_0000000010000000_00001,
1888 },
1889 .{ // ret
1890 .inst = Instruction.ret(null),
1891 .expected = 0b1101_011_00_10_11111_0000_00_11110_00000,
1892 },
1893 .{ // bl #0x10
1894 .inst = Instruction.bl(0x10),
1895 .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100,
1896 },
1897 .{ // ldr x2, [x1]
1898 .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.none),
1899 .expected = 0b11_111_0_01_01_000000000000_00001_00010,
1900 },
1901 .{ // ldr x2, [x1, #1]!
1902 .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_pre_index(1)),
1903 .expected = 0b11_111_0_00_01_0_000000001_11_00001_00010,
1904 },
1905 .{ // ldr x2, [x1], #-1
1906 .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_post_index(-1)),
1907 .expected = 0b11_111_0_00_01_0_111111111_01_00001_00010,
1908 },
1909 .{ // ldr x2, [x1], (x3)
1910 .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)),
1911 .expected = 0b11_111_0_00_01_1_00011_011_0_10_00001_00010,
1912 },
1913 .{ // ldr x2, label
1914 .inst = Instruction.ldrLiteral(.x2, 0x1),
1915 .expected = 0b01_011_0_00_0000000000000000001_00010,
1916 },
1917 .{ // ldrh x7, [x4], #0xaa
1918 .inst = Instruction.ldrh(.x7, .x4, Instruction.LoadStoreOffset.imm_post_index(0xaa)),
1919 .expected = 0b01_111_0_00_01_0_010101010_01_00100_00111,
1920 },
1921 .{ // ldrb x9, [x15, #0xff]!
1922 .inst = Instruction.ldrb(.x9, .x15, Instruction.LoadStoreOffset.imm_pre_index(0xff)),
1923 .expected = 0b00_111_0_00_01_0_011111111_11_01111_01001,
1924 },
1925 .{ // str x2, [x1]
1926 .inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.none),
1927 .expected = 0b11_111_0_01_00_000000000000_00001_00010,
1928 },
1929 .{ // str x2, [x1], (x3)
1930 .inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)),
1931 .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,
1932 },
1933 .{ // strh w0, [x1]
1934 .inst = Instruction.strh(.w0, .x1, Instruction.LoadStoreOffset.none),
1935 .expected = 0b01_111_0_01_00_000000000000_00001_00000,
1936 },
1937 .{ // strb w8, [x9]
1938 .inst = Instruction.strb(.w8, .x9, Instruction.LoadStoreOffset.none),
1939 .expected = 0b00_111_0_01_00_000000000000_01001_01000,
1940 },
1941 .{ // adr x2, #0x8
1942 .inst = Instruction.adr(.x2, 0x8),
1943 .expected = 0b0_00_10000_0000000000000000010_00010,
1944 },
1945 .{ // adr x2, -#0x8
1946 .inst = Instruction.adr(.x2, -0x8),
1947 .expected = 0b0_00_10000_1111111111111111110_00010,
1948 },
1949 .{ // adrp x2, #0x8
1950 .inst = Instruction.adrp(.x2, 0x8),
1951 .expected = 0b1_00_10000_0000000000000000010_00010,
1952 },
1953 .{ // adrp x2, -#0x8
1954 .inst = Instruction.adrp(.x2, -0x8),
1955 .expected = 0b1_00_10000_1111111111111111110_00010,
1956 },
1957 .{ // stp x1, x2, [sp, #8]
1958 .inst = Instruction.stp(.x1, .x2, .sp, Instruction.LoadStorePairOffset.signed(8)),
1959 .expected = 0b10_101_0_010_0_0000001_00010_11111_00001,
1960 },
1961 .{ // ldp x1, x2, [sp, #8]
1962 .inst = Instruction.ldp(.x1, .x2, .sp, Instruction.LoadStorePairOffset.signed(8)),
1963 .expected = 0b10_101_0_010_1_0000001_00010_11111_00001,
1964 },
1965 .{ // stp x1, x2, [sp, #-16]!
1966 .inst = Instruction.stp(.x1, .x2, .sp, Instruction.LoadStorePairOffset.pre_index(-16)),
1967 .expected = 0b10_101_0_011_0_1111110_00010_11111_00001,
1968 },
1969 .{ // ldp x1, x2, [sp], #16
1970 .inst = Instruction.ldp(.x1, .x2, .sp, Instruction.LoadStorePairOffset.post_index(16)),
1971 .expected = 0b10_101_0_001_1_0000010_00010_11111_00001,
1972 },
1973 .{ // and x0, x4, x2
1974 .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0),
1975 .expected = 0b1_00_01010_00_0_00010_000000_00100_00000,
1976 },
1977 .{ // and x0, x4, x2, lsl #0x8
1978 .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0x8),
1979 .expected = 0b1_00_01010_00_0_00010_001000_00100_00000,
1980 },
1981 .{ // add x0, x10, #10
1982 .inst = Instruction.add(.x0, .x10, 10, false),
1983 .expected = 0b1_0_0_100010_0_0000_0000_1010_01010_00000,
1984 },
1985 .{ // subs x0, x5, #11, lsl #12
1986 .inst = Instruction.subs(.x0, .x5, 11, true),
1987 .expected = 0b1_1_1_100010_1_0000_0000_1011_00101_00000,
1988 },
1989 .{ // b.hi #-4
1990 .inst = Instruction.bCond(.hi, -4),
1991 .expected = 0b0101010_0_1111111111111111111_0_1000,
1992 },
1993 .{ // cbz x10, #40
1994 .inst = Instruction.cbz(.x10, 40),
1995 .expected = 0b1_011010_0_0000000000000001010_01010,
1996 },
1997 .{ // add x0, x1, x2, lsl #5
1998 .inst = Instruction.addShiftedRegister(.x0, .x1, .x2, .lsl, 5),
1999 .expected = 0b1_0_0_01011_00_0_00010_000101_00001_00000,
2000 },
2001 .{ // csinc x1, x2, x4, eq
2002 .inst = Instruction.csinc(.x1, .x2, .x4, .eq),
2003 .expected = 0b1_0_0_11010100_00100_0000_0_1_00010_00001,
2004 },
2005 .{ // mul x1, x4, x9
2006 .inst = Instruction.mul(.x1, .x4, .x9),
2007 .expected = 0b1_00_11011_000_01001_0_11111_00100_00001,
2008 },
2009 .{ // eor x3, x5, #1
2010 .inst = Instruction.eorImmediate(.x3, .x5, 0b000000, 0b000000, 0b1),
2011 .expected = 0b1_10_100100_1_000000_000000_00101_00011,
2012 },
2013 .{ // lslv x6, x9, x10
2014 .inst = Instruction.lslv(.x6, .x9, .x10),
2015 .expected = 0b1_0_0_11010110_01010_0010_00_01001_00110,
2016 },
2017 .{ // lsl x4, x2, #42
2018 .inst = Instruction.lslImmediate(.x4, .x2, 42),
2019 .expected = 0b1_10_100110_1_010110_010101_00010_00100,
2020 },
2021 .{ // lsl x4, x2, #63
2022 .inst = Instruction.lslImmediate(.x4, .x2, 63),
2023 .expected = 0b1_10_100110_1_000001_000000_00010_00100,
2024 },
2025 .{ // lsr x4, x2, #42
2026 .inst = Instruction.lsrImmediate(.x4, .x2, 42),
2027 .expected = 0b1_10_100110_1_101010_111111_00010_00100,
2028 },
2029 .{ // lsr x4, x2, #63
2030 .inst = Instruction.lsrImmediate(.x4, .x2, 63),
2031 .expected = 0b1_10_100110_1_111111_111111_00010_00100,
2032 },
2033 .{ // umull x0, w0, w1
2034 .inst = Instruction.umull(.x0, .w0, .w1),
2035 .expected = 0b1_00_11011_1_01_00001_0_11111_00000_00000,
2036 },
2037 .{ // smull x0, w0, w1
2038 .inst = Instruction.smull(.x0, .w0, .w1),
2039 .expected = 0b1_00_11011_0_01_00001_0_11111_00000_00000,
2040 },
2041 .{ // tst x0, #0xffffffff00000000
2042 .inst = Instruction.andsImmediate(.xzr, .x0, 0b011111, 0b100000, 0b1),
2043 .expected = 0b1_11_100100_1_100000_011111_00000_11111,
2044 },
2045 .{ // umulh x0, x1, x2
2046 .inst = Instruction.umulh(.x0, .x1, .x2),
2047 .expected = 0b1_00_11011_1_10_00010_0_11111_00001_00000,
2048 },
2049 .{ // smulh x0, x1, x2
2050 .inst = Instruction.smulh(.x0, .x1, .x2),
2051 .expected = 0b1_00_11011_0_10_00010_0_11111_00001_00000,
2052 },
2053 .{ // adds x0, x1, x2, sxtx
2054 .inst = Instruction.addsExtendedRegister(.x0, .x1, .x2, .sxtx, 0),
2055 .expected = 0b1_0_1_01011_00_1_00010_111_000_00001_00000,
2056 },
2057 };
2058
2059 for (testcases) |case| {
2060 const actual = case.inst.toU32();
2061 try testing.expectEqual(case.expected, actual);
2062 }
2063}
src/arch/riscv64/CodeGen.zig+5-5
...@@ -745,7 +745,7 @@ pub fn generate(...@@ -745,7 +745,7 @@ pub fn generate(
745 src_loc: Zcu.LazySrcLoc,745 src_loc: Zcu.LazySrcLoc,
746 func_index: InternPool.Index,746 func_index: InternPool.Index,
747 air: *const Air,747 air: *const Air,
748 liveness: *const Air.Liveness,748 liveness: *const ?Air.Liveness,
749) CodeGenError!Mir {749) CodeGenError!Mir {
750 const zcu = pt.zcu;750 const zcu = pt.zcu;
751 const gpa = zcu.gpa;751 const gpa = zcu.gpa;
...@@ -768,7 +768,7 @@ pub fn generate(...@@ -768,7 +768,7 @@ pub fn generate(
768 .pt = pt,768 .pt = pt,
769 .mod = mod,769 .mod = mod,
770 .bin_file = bin_file,770 .bin_file = bin_file,
771 .liveness = liveness.*,771 .liveness = liveness.*.?,
772 .target = &mod.resolved_target.result,772 .target = &mod.resolved_target.result,
773 .owner = .{ .nav_index = func.owner_nav },773 .owner = .{ .nav_index = func.owner_nav },
774 .args = undefined, // populated after `resolveCallingConventionValues`774 .args = undefined, // populated after `resolveCallingConventionValues`
...@@ -4585,7 +4585,7 @@ fn structFieldPtr(func: *Func, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -4585,7 +4585,7 @@ fn structFieldPtr(func: *Func, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
4585 const field_offset: i32 = switch (container_ty.containerLayout(zcu)) {4585 const field_offset: i32 = switch (container_ty.containerLayout(zcu)) {
4586 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, zcu)),4586 .auto, .@"extern" => @intCast(container_ty.structFieldOffset(index, zcu)),
4587 .@"packed" => @divExact(@as(i32, ptr_container_ty.ptrInfo(zcu).packed_offset.bit_offset) +4587 .@"packed" => @divExact(@as(i32, ptr_container_ty.ptrInfo(zcu).packed_offset.bit_offset) +
4588 (if (zcu.typeToStruct(container_ty)) |struct_obj| pt.structPackedFieldBitOffset(struct_obj, index) else 0) -4588 (if (zcu.typeToStruct(container_ty)) |struct_obj| zcu.structPackedFieldBitOffset(struct_obj, index) else 0) -
4589 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),4589 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
4590 };4590 };
45914591
...@@ -4616,7 +4616,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -4616,7 +4616,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void {
4616 const field_off: u32 = switch (struct_ty.containerLayout(zcu)) {4616 const field_off: u32 = switch (struct_ty.containerLayout(zcu)) {
4617 .auto, .@"extern" => @intCast(struct_ty.structFieldOffset(index, zcu) * 8),4617 .auto, .@"extern" => @intCast(struct_ty.structFieldOffset(index, zcu) * 8),
4618 .@"packed" => if (zcu.typeToStruct(struct_ty)) |struct_type|4618 .@"packed" => if (zcu.typeToStruct(struct_ty)) |struct_type|
4619 pt.structPackedFieldBitOffset(struct_type, index)4619 zcu.structPackedFieldBitOffset(struct_type, index)
4620 else4620 else
4621 0,4621 0,
4622 };4622 };
...@@ -8060,7 +8060,7 @@ fn airAggregateInit(func: *Func, inst: Air.Inst.Index) !void {...@@ -8060,7 +8060,7 @@ fn airAggregateInit(func: *Func, inst: Air.Inst.Index) !void {
80608060
8061 const elem_abi_size: u32 = @intCast(elem_ty.abiSize(zcu));8061 const elem_abi_size: u32 = @intCast(elem_ty.abiSize(zcu));
8062 const elem_abi_bits = elem_abi_size * 8;8062 const elem_abi_bits = elem_abi_size * 8;
8063 const elem_off = pt.structPackedFieldBitOffset(struct_obj, elem_i);8063 const elem_off = zcu.structPackedFieldBitOffset(struct_obj, elem_i);
8064 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);8064 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);
8065 const elem_bit_off = elem_off % elem_abi_bits;8065 const elem_bit_off = elem_off % elem_abi_bits;
8066 const elem_mcv = try func.resolveInst(elem);8066 const elem_mcv = try func.resolveInst(elem);
src/arch/sparc64/CodeGen.zig+2-2
...@@ -267,7 +267,7 @@ pub fn generate(...@@ -267,7 +267,7 @@ pub fn generate(
267 src_loc: Zcu.LazySrcLoc,267 src_loc: Zcu.LazySrcLoc,
268 func_index: InternPool.Index,268 func_index: InternPool.Index,
269 air: *const Air,269 air: *const Air,
270 liveness: *const Air.Liveness,270 liveness: *const ?Air.Liveness,
271) CodeGenError!Mir {271) CodeGenError!Mir {
272 const zcu = pt.zcu;272 const zcu = pt.zcu;
273 const gpa = zcu.gpa;273 const gpa = zcu.gpa;
...@@ -288,7 +288,7 @@ pub fn generate(...@@ -288,7 +288,7 @@ pub fn generate(
288 .gpa = gpa,288 .gpa = gpa,
289 .pt = pt,289 .pt = pt,
290 .air = air.*,290 .air = air.*,
291 .liveness = liveness.*,291 .liveness = liveness.*.?,
292 .target = target,292 .target = target,
293 .bin_file = lf,293 .bin_file = lf,
294 .func_index = func_index,294 .func_index = func_index,
src/arch/wasm/CodeGen.zig+5-5
...@@ -1174,7 +1174,7 @@ pub fn generate(...@@ -1174,7 +1174,7 @@ pub fn generate(
1174 src_loc: Zcu.LazySrcLoc,1174 src_loc: Zcu.LazySrcLoc,
1175 func_index: InternPool.Index,1175 func_index: InternPool.Index,
1176 air: *const Air,1176 air: *const Air,
1177 liveness: *const Air.Liveness,1177 liveness: *const ?Air.Liveness,
1178) Error!Mir {1178) Error!Mir {
1179 _ = src_loc;1179 _ = src_loc;
1180 _ = bin_file;1180 _ = bin_file;
...@@ -1195,7 +1195,7 @@ pub fn generate(...@@ -1195,7 +1195,7 @@ pub fn generate(
1195 .gpa = gpa,1195 .gpa = gpa,
1196 .pt = pt,1196 .pt = pt,
1197 .air = air.*,1197 .air = air.*,
1198 .liveness = liveness.*,1198 .liveness = liveness.*.?,
1199 .owner_nav = cg.owner_nav,1199 .owner_nav = cg.owner_nav,
1200 .target = target,1200 .target = target,
1201 .ptr_size = switch (target.cpu.arch) {1201 .ptr_size = switch (target.cpu.arch) {
...@@ -3777,7 +3777,7 @@ fn structFieldPtr(...@@ -3777,7 +3777,7 @@ fn structFieldPtr(
3777 break :offset @as(u32, 0);3777 break :offset @as(u32, 0);
3778 }3778 }
3779 const struct_type = zcu.typeToStruct(struct_ty).?;3779 const struct_type = zcu.typeToStruct(struct_ty).?;
3780 break :offset @divExact(pt.structPackedFieldBitOffset(struct_type, index) + struct_ptr_ty_info.packed_offset.bit_offset, 8);3780 break :offset @divExact(zcu.structPackedFieldBitOffset(struct_type, index) + struct_ptr_ty_info.packed_offset.bit_offset, 8);
3781 },3781 },
3782 .@"union" => 0,3782 .@"union" => 0,
3783 else => unreachable,3783 else => unreachable,
...@@ -3813,7 +3813,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -3813,7 +3813,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3813 .@"packed" => switch (struct_ty.zigTypeTag(zcu)) {3813 .@"packed" => switch (struct_ty.zigTypeTag(zcu)) {
3814 .@"struct" => result: {3814 .@"struct" => result: {
3815 const packed_struct = zcu.typeToPackedStruct(struct_ty).?;3815 const packed_struct = zcu.typeToPackedStruct(struct_ty).?;
3816 const offset = pt.structPackedFieldBitOffset(packed_struct, field_index);3816 const offset = zcu.structPackedFieldBitOffset(packed_struct, field_index);
3817 const backing_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip));3817 const backing_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip));
3818 const host_bits = backing_ty.intInfo(zcu).bits;3818 const host_bits = backing_ty.intInfo(zcu).bits;
38193819
...@@ -5697,7 +5697,7 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -5697,7 +5697,7 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5697 .auto, .@"extern" => parent_ty.structFieldOffset(field_index, zcu),5697 .auto, .@"extern" => parent_ty.structFieldOffset(field_index, zcu),
5698 .@"packed" => offset: {5698 .@"packed" => offset: {
5699 const parent_ptr_offset = parent_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset;5699 const parent_ptr_offset = parent_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset;
5700 const field_offset = if (zcu.typeToStruct(parent_ty)) |loaded_struct| pt.structPackedFieldBitOffset(loaded_struct, field_index) else 0;5700 const field_offset = if (zcu.typeToStruct(parent_ty)) |loaded_struct| zcu.structPackedFieldBitOffset(loaded_struct, field_index) else 0;
5701 const field_ptr_offset = field_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset;5701 const field_ptr_offset = field_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset;
5702 break :offset @divExact(parent_ptr_offset + field_offset - field_ptr_offset, 8);5702 break :offset @divExact(parent_ptr_offset + field_offset - field_ptr_offset, 8);
5703 },5703 },
src/arch/x86_64/CodeGen.zig+20-31
...@@ -878,7 +878,7 @@ pub fn generate(...@@ -878,7 +878,7 @@ pub fn generate(
878 src_loc: Zcu.LazySrcLoc,878 src_loc: Zcu.LazySrcLoc,
879 func_index: InternPool.Index,879 func_index: InternPool.Index,
880 air: *const Air,880 air: *const Air,
881 liveness: *const Air.Liveness,881 liveness: *const ?Air.Liveness,
882) codegen.CodeGenError!Mir {882) codegen.CodeGenError!Mir {
883 _ = bin_file;883 _ = bin_file;
884 const zcu = pt.zcu;884 const zcu = pt.zcu;
...@@ -894,7 +894,7 @@ pub fn generate(...@@ -894,7 +894,7 @@ pub fn generate(
894 .gpa = gpa,894 .gpa = gpa,
895 .pt = pt,895 .pt = pt,
896 .air = air.*,896 .air = air.*,
897 .liveness = liveness.*,897 .liveness = liveness.*.?,
898 .target = &mod.resolved_target.result,898 .target = &mod.resolved_target.result,
899 .mod = mod,899 .mod = mod,
900 .owner = .{ .nav_index = func.owner_nav },900 .owner = .{ .nav_index = func.owner_nav },
...@@ -100674,11 +100674,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -100674,11 +100674,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100674 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;100674 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
100675 const struct_field = cg.air.extraData(Air.StructField, ty_pl.payload).data;100675 const struct_field = cg.air.extraData(Air.StructField, ty_pl.payload).data;
100676 var ops = try cg.tempsFromOperands(inst, .{struct_field.struct_operand});100676 var ops = try cg.tempsFromOperands(inst, .{struct_field.struct_operand});
100677 try ops[0].toOffset(cg.fieldOffset(100677 try ops[0].toOffset(@intCast(codegen.fieldOffset(
100678 cg.typeOf(struct_field.struct_operand),100678 cg.typeOf(struct_field.struct_operand),
100679 ty_pl.ty.toType(),100679 ty_pl.ty.toType(),
100680 struct_field.field_index,100680 struct_field.field_index,
100681 ), cg);100681 zcu,
100682 )), cg);
100682 try ops[0].finish(inst, &.{struct_field.struct_operand}, &ops, cg);100683 try ops[0].finish(inst, &.{struct_field.struct_operand}, &ops, cg);
100683 },100684 },
100684 .struct_field_ptr_index_0,100685 .struct_field_ptr_index_0,
...@@ -100688,7 +100689,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -100688,7 +100689,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100688 => |air_tag| {100689 => |air_tag| {
100689 const ty_op = air_datas[@intFromEnum(inst)].ty_op;100690 const ty_op = air_datas[@intFromEnum(inst)].ty_op;
100690 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});100691 var ops = try cg.tempsFromOperands(inst, .{ty_op.operand});
100691 try ops[0].toOffset(cg.fieldOffset(100692 try ops[0].toOffset(@intCast(codegen.fieldOffset(
100692 cg.typeOf(ty_op.operand),100693 cg.typeOf(ty_op.operand),
100693 ty_op.ty.toType(),100694 ty_op.ty.toType(),
100694 switch (air_tag) {100695 switch (air_tag) {
...@@ -100698,7 +100699,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -100698,7 +100699,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
100698 .struct_field_ptr_index_2 => 2,100699 .struct_field_ptr_index_2 => 2,
100699 .struct_field_ptr_index_3 => 3,100700 .struct_field_ptr_index_3 => 3,
100700 },100701 },
100701 ), cg);100702 zcu,
100703 )), cg);
100702 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);100704 try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg);
100703 },100705 },
100704 .struct_field_val => {100706 .struct_field_val => {
...@@ -168108,11 +168110,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168108,11 +168110,12 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168108 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;168110 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
168109 const field_parent_ptr = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;168111 const field_parent_ptr = cg.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
168110 var ops = try cg.tempsFromOperands(inst, .{field_parent_ptr.field_ptr});168112 var ops = try cg.tempsFromOperands(inst, .{field_parent_ptr.field_ptr});
168111 try ops[0].toOffset(-cg.fieldOffset(168113 try ops[0].toOffset(-@as(i32, @intCast(codegen.fieldOffset(
168112 ty_pl.ty.toType(),168114 ty_pl.ty.toType(),
168113 cg.typeOf(field_parent_ptr.field_ptr),168115 cg.typeOf(field_parent_ptr.field_ptr),
168114 field_parent_ptr.field_index,168116 field_parent_ptr.field_index,
168115 ), cg);168117 zcu,
168118 ))), cg);
168116 try ops[0].finish(inst, &.{field_parent_ptr.field_ptr}, &ops, cg);168119 try ops[0].finish(inst, &.{field_parent_ptr.field_ptr}, &ops, cg);
168117 },168120 },
168118 .wasm_memory_size, .wasm_memory_grow => unreachable,168121 .wasm_memory_size, .wasm_memory_grow => unreachable,
...@@ -174809,18 +174812,6 @@ fn airStore(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {...@@ -174809,18 +174812,6 @@ fn airStore(self: *CodeGen, inst: Air.Inst.Index, safety: bool) !void {
174809 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });174812 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });
174810}174813}
174811174814
174812fn fieldOffset(self: *CodeGen, ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32) i32 {
174813 const pt = self.pt;
174814 const zcu = pt.zcu;
174815 const agg_ty = ptr_agg_ty.childType(zcu);
174816 return switch (agg_ty.containerLayout(zcu)) {
174817 .auto, .@"extern" => @intCast(agg_ty.structFieldOffset(field_index, zcu)),
174818 .@"packed" => @divExact(@as(i32, ptr_agg_ty.ptrInfo(zcu).packed_offset.bit_offset) +
174819 (if (zcu.typeToStruct(agg_ty)) |loaded_struct| pt.structPackedFieldBitOffset(loaded_struct, field_index) else 0) -
174820 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
174821 };
174822}
174823
174824fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue {174815fn genUnOp(self: *CodeGen, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue {
174825 const pt = self.pt;174816 const pt = self.pt;
174826 const zcu = pt.zcu;174817 const zcu = pt.zcu;
...@@ -184575,7 +184566,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -184575,7 +184566,7 @@ fn airAggregateInit(self: *CodeGen, inst: Air.Inst.Index) !void {
184575 }184566 }
184576 const elem_abi_size: u32 = @intCast(elem_ty.abiSize(zcu));184567 const elem_abi_size: u32 = @intCast(elem_ty.abiSize(zcu));
184577 const elem_abi_bits = elem_abi_size * 8;184568 const elem_abi_bits = elem_abi_size * 8;
184578 const elem_off = pt.structPackedFieldBitOffset(loaded_struct, elem_i);184569 const elem_off = zcu.structPackedFieldBitOffset(loaded_struct, elem_i);
184579 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);184570 const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size);
184580 const elem_bit_off = elem_off % elem_abi_bits;184571 const elem_bit_off = elem_off % elem_abi_bits;
184581 const elem_mcv = try self.resolveInst(elem);184572 const elem_mcv = try self.resolveInst(elem);
...@@ -185625,21 +185616,19 @@ fn resolveCallingConventionValues(...@@ -185625,21 +185616,19 @@ fn resolveCallingConventionValues(
185625fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {185616fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
185626 @branchHint(.cold);185617 @branchHint(.cold);
185627 const zcu = cg.pt.zcu;185618 const zcu = cg.pt.zcu;
185628 switch (cg.owner) {185619 return switch (cg.owner) {
185629 .nav_index => |i| return zcu.codegenFail(i, format, args),185620 .nav_index => |i| zcu.codegenFail(i, format, args),
185630 .lazy_sym => |s| return zcu.codegenFailType(s.ty, format, args),185621 .lazy_sym => |s| zcu.codegenFailType(s.ty, format, args),
185631 }185622 };
185632 return error.CodegenFail;
185633}185623}
185634185624
185635fn failMsg(cg: *CodeGen, msg: *Zcu.ErrorMsg) error{ OutOfMemory, CodegenFail } {185625fn failMsg(cg: *CodeGen, msg: *Zcu.ErrorMsg) error{ OutOfMemory, CodegenFail } {
185636 @branchHint(.cold);185626 @branchHint(.cold);
185637 const zcu = cg.pt.zcu;185627 const zcu = cg.pt.zcu;
185638 switch (cg.owner) {185628 return switch (cg.owner) {
185639 .nav_index => |i| return zcu.codegenFailMsg(i, msg),185629 .nav_index => |i| zcu.codegenFailMsg(i, msg),
185640 .lazy_sym => |s| return zcu.codegenFailTypeMsg(s.ty, msg),185630 .lazy_sym => |s| zcu.codegenFailTypeMsg(s.ty, msg),
185641 }185631 };
185642 return error.CodegenFail;
185643}185632}
185644185633
185645fn parseRegName(name: []const u8) ?Register {185634fn parseRegName(name: []const u8) ?Register {
src/codegen.zig+48-13
...@@ -23,6 +23,8 @@ const Zir = std.zig.Zir;...@@ -23,6 +23,8 @@ const Zir = std.zig.Zir;
23const Alignment = InternPool.Alignment;23const Alignment = InternPool.Alignment;
24const dev = @import("dev.zig");24const dev = @import("dev.zig");
2525
26pub const aarch64 = @import("codegen/aarch64.zig");
27
26pub const CodeGenError = GenerateSymbolError || error{28pub const CodeGenError = GenerateSymbolError || error{
27 /// Indicates the error is already stored in Zcu `failed_codegen`.29 /// Indicates the error is already stored in Zcu `failed_codegen`.
28 CodegenFail,30 CodegenFail,
...@@ -49,7 +51,7 @@ fn devFeatureForBackend(backend: std.builtin.CompilerBackend) dev.Feature {...@@ -49,7 +51,7 @@ fn devFeatureForBackend(backend: std.builtin.CompilerBackend) dev.Feature {
49fn importBackend(comptime backend: std.builtin.CompilerBackend) type {51fn importBackend(comptime backend: std.builtin.CompilerBackend) type {
50 return switch (backend) {52 return switch (backend) {
51 .other, .stage1 => unreachable,53 .other, .stage1 => unreachable,
52 .stage2_aarch64 => unreachable,54 .stage2_aarch64 => aarch64,
53 .stage2_arm => unreachable,55 .stage2_arm => unreachable,
54 .stage2_c => @import("codegen/c.zig"),56 .stage2_c => @import("codegen/c.zig"),
55 .stage2_llvm => @import("codegen/llvm.zig"),57 .stage2_llvm => @import("codegen/llvm.zig"),
...@@ -72,6 +74,7 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*co...@@ -72,6 +74,7 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*co
72 .stage2_c,74 .stage2_c,
73 .stage2_wasm,75 .stage2_wasm,
74 .stage2_x86_64,76 .stage2_x86_64,
77 .stage2_aarch64,
75 .stage2_x86,78 .stage2_x86,
76 .stage2_riscv64,79 .stage2_riscv64,
77 .stage2_sparc64,80 .stage2_sparc64,
...@@ -83,20 +86,29 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*co...@@ -83,20 +86,29 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*co
83 }86 }
84}87}
8588
89pub fn wantsLiveness(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) bool {
90 const zcu = pt.zcu;
91 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
92 return switch (target_util.zigBackend(target, zcu.comp.config.use_llvm)) {
93 else => true,
94 .stage2_aarch64 => false,
95 };
96}
97
86/// Every code generation backend has a different MIR representation. However, we want to pass98/// Every code generation backend has a different MIR representation. However, we want to pass
87/// MIR from codegen to the linker *regardless* of which backend is in use. So, we use this: a99/// MIR from codegen to the linker *regardless* of which backend is in use. So, we use this: a
88/// union of all MIR types. The active tag is known from the backend in use; see `AnyMir.tag`.100/// union of all MIR types. The active tag is known from the backend in use; see `AnyMir.tag`.
89pub const AnyMir = union {101pub const AnyMir = union {
90 riscv64: @import("arch/riscv64/Mir.zig"),102 aarch64: if (dev.env.supports(.aarch64_backend)) @import("codegen/aarch64/Mir.zig") else noreturn,
91 sparc64: @import("arch/sparc64/Mir.zig"),103 riscv64: if (dev.env.supports(.riscv64_backend)) @import("arch/riscv64/Mir.zig") else noreturn,
92 x86_64: @import("arch/x86_64/Mir.zig"),104 sparc64: if (dev.env.supports(.sparc64_backend)) @import("arch/sparc64/Mir.zig") else noreturn,
93 wasm: @import("arch/wasm/Mir.zig"),105 x86_64: if (dev.env.supports(.x86_64_backend)) @import("arch/x86_64/Mir.zig") else noreturn,
94 c: @import("codegen/c.zig").Mir,106 wasm: if (dev.env.supports(.wasm_backend)) @import("arch/wasm/Mir.zig") else noreturn,
107 c: if (dev.env.supports(.c_backend)) @import("codegen/c.zig").Mir else noreturn,
95108
96 pub inline fn tag(comptime backend: std.builtin.CompilerBackend) []const u8 {109 pub inline fn tag(comptime backend: std.builtin.CompilerBackend) []const u8 {
97 return switch (backend) {110 return switch (backend) {
98 .stage2_aarch64 => "aarch64",111 .stage2_aarch64 => "aarch64",
99 .stage2_arm => "arm",
100 .stage2_riscv64 => "riscv64",112 .stage2_riscv64 => "riscv64",
101 .stage2_sparc64 => "sparc64",113 .stage2_sparc64 => "sparc64",
102 .stage2_x86_64 => "x86_64",114 .stage2_x86_64 => "x86_64",
...@@ -111,7 +123,8 @@ pub const AnyMir = union {...@@ -111,7 +123,8 @@ pub const AnyMir = union {
111 const backend = target_util.zigBackend(&zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm);123 const backend = target_util.zigBackend(&zcu.root_mod.resolved_target.result, zcu.comp.config.use_llvm);
112 switch (backend) {124 switch (backend) {
113 else => unreachable,125 else => unreachable,
114 inline .stage2_riscv64,126 inline .stage2_aarch64,
127 .stage2_riscv64,
115 .stage2_sparc64,128 .stage2_sparc64,
116 .stage2_x86_64,129 .stage2_x86_64,
117 .stage2_wasm,130 .stage2_wasm,
...@@ -132,14 +145,15 @@ pub fn generateFunction(...@@ -132,14 +145,15 @@ pub fn generateFunction(
132 src_loc: Zcu.LazySrcLoc,145 src_loc: Zcu.LazySrcLoc,
133 func_index: InternPool.Index,146 func_index: InternPool.Index,
134 air: *const Air,147 air: *const Air,
135 liveness: *const Air.Liveness,148 liveness: *const ?Air.Liveness,
136) CodeGenError!AnyMir {149) CodeGenError!AnyMir {
137 const zcu = pt.zcu;150 const zcu = pt.zcu;
138 const func = zcu.funcInfo(func_index);151 const func = zcu.funcInfo(func_index);
139 const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;152 const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
140 switch (target_util.zigBackend(target, false)) {153 switch (target_util.zigBackend(target, false)) {
141 else => unreachable,154 else => unreachable,
142 inline .stage2_riscv64,155 inline .stage2_aarch64,
156 .stage2_riscv64,
143 .stage2_sparc64,157 .stage2_sparc64,
144 .stage2_x86_64,158 .stage2_x86_64,
145 .stage2_wasm,159 .stage2_wasm,
...@@ -174,7 +188,8 @@ pub fn emitFunction(...@@ -174,7 +188,8 @@ pub fn emitFunction(
174 const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;188 const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result;
175 switch (target_util.zigBackend(target, zcu.comp.config.use_llvm)) {189 switch (target_util.zigBackend(target, zcu.comp.config.use_llvm)) {
176 else => unreachable,190 else => unreachable,
177 inline .stage2_riscv64,191 inline .stage2_aarch64,
192 .stage2_riscv64,
178 .stage2_sparc64,193 .stage2_sparc64,
179 .stage2_x86_64,194 .stage2_x86_64,
180 => |backend| {195 => |backend| {
...@@ -419,7 +434,7 @@ pub fn generateSymbolInner(...@@ -419,7 +434,7 @@ pub fn generateSymbolInner(
419 const int_tag_ty = ty.intTagType(zcu);434 const int_tag_ty = ty.intTagType(zcu);
420 try generateSymbolInner(bin_file, pt, src_loc, try pt.getCoerced(.fromInterned(enum_tag.int), int_tag_ty), bw, reloc_parent);435 try generateSymbolInner(bin_file, pt, src_loc, try pt.getCoerced(.fromInterned(enum_tag.int), int_tag_ty), bw, reloc_parent);
421 },436 },
422 .float => |float| switch (float.storage) {437 .float => |float| storage: switch (float.storage) {
423 .f16 => |f16_val| try bw.writeInt(u16, @bitCast(f16_val), endian),438 .f16 => |f16_val| try bw.writeInt(u16, @bitCast(f16_val), endian),
424 .f32 => |f32_val| try bw.writeInt(u32, @bitCast(f32_val), endian),439 .f32 => |f32_val| try bw.writeInt(u32, @bitCast(f32_val), endian),
425 .f64 => |f64_val| try bw.writeInt(u64, @bitCast(f64_val), endian),440 .f64 => |f64_val| try bw.writeInt(u64, @bitCast(f64_val), endian),
...@@ -428,7 +443,13 @@ pub fn generateSymbolInner(...@@ -428,7 +443,13 @@ pub fn generateSymbolInner(
428 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;443 const abi_size = math.cast(usize, ty.abiSize(zcu)) orelse return error.Overflow;
429 try bw.splatByteAll(0, abi_size - 10);444 try bw.splatByteAll(0, abi_size - 10);
430 },445 },
431 .f128 => |f128_val| try bw.writeInt(u128, @bitCast(f128_val), endian),446 .f128 => |f128_val| switch (Type.fromInterned(float.ty).floatBits(target)) {
447 else => unreachable,
448 16 => continue :storage .{ .f16 = @floatCast(f128_val) },
449 32 => continue :storage .{ .f32 = @floatCast(f128_val) },
450 64 => continue :storage .{ .f64 = @floatCast(f128_val) },
451 128 => try bw.writeInt(u128, @bitCast(f128_val), target, endian),
452 },
432 },453 },
433 .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), bw, reloc_parent, 0),454 .ptr => try lowerPtr(bin_file, pt, src_loc, val.toIntern(), bw, reloc_parent, 0),
434 .slice => |slice| {455 .slice => |slice| {
...@@ -1196,3 +1217,17 @@ pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Zcu) u64 {...@@ -1196,3 +1217,17 @@ pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Zcu) u64 {
1196 return 0;1217 return 0;
1197 }1218 }
1198}1219}
1220
1221pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu: *Zcu) u64 {
1222 const agg_ty = ptr_agg_ty.childType(zcu);
1223 return switch (agg_ty.containerLayout(zcu)) {
1224 .auto, .@"extern" => agg_ty.structFieldOffset(field_index, zcu),
1225 .@"packed" => @divExact(@as(u64, ptr_agg_ty.ptrInfo(zcu).packed_offset.bit_offset) +
1226 (if (zcu.typeToPackedStruct(agg_ty)) |loaded_struct| zcu.structPackedFieldBitOffset(loaded_struct, field_index) else 0) -
1227 ptr_field_ty.ptrInfo(zcu).packed_offset.bit_offset, 8),
1228 };
1229}
1230
1231test {
1232 _ = aarch64;
1233}
src/codegen/aarch64.zig created+194
...@@ -0,0 +1,194 @@
1pub const abi = @import("aarch64/abi.zig");
2pub const Assemble = @import("aarch64/Assemble.zig");
3pub const Disassemble = @import("aarch64/Disassemble.zig");
4pub const encoding = @import("aarch64/encoding.zig");
5pub const Mir = @import("aarch64/Mir.zig");
6pub const Select = @import("aarch64/Select.zig");
7
8pub fn legalizeFeatures(_: *const std.Target) ?*Air.Legalize.Features {
9 return null;
10}
11
12pub fn generate(
13 _: *link.File,
14 pt: Zcu.PerThread,
15 _: Zcu.LazySrcLoc,
16 func_index: InternPool.Index,
17 air: *const Air,
18 liveness: *const ?Air.Liveness,
19) !Mir {
20 const zcu = pt.zcu;
21 const gpa = zcu.gpa;
22 const func = zcu.funcInfo(func_index);
23 const func_type = zcu.intern_pool.indexToKey(func.ty).func_type;
24 assert(liveness.* == null);
25
26 const mod = zcu.navFileScope(func.owner_nav).mod.?;
27 var isel: Select = .{
28 .pt = pt,
29 .target = &mod.resolved_target.result,
30 .air = air.*,
31 .nav_index = zcu.funcInfo(func_index).owner_nav,
32
33 .def_order = .empty,
34 .blocks = .empty,
35 .loops = .empty,
36 .active_loops = .empty,
37 .loop_live = .{
38 .set = .empty,
39 .list = .empty,
40 },
41 .dom_start = 0,
42 .dom_len = 0,
43 .dom = .empty,
44
45 .saved_registers = comptime .initEmpty(),
46 .instructions = .empty,
47 .literals = .empty,
48 .nav_relocs = .empty,
49 .uav_relocs = .empty,
50 .global_relocs = .empty,
51 .literal_relocs = .empty,
52
53 .returns = false,
54 .va_list = undefined,
55 .stack_size = 0,
56 .stack_align = .@"16",
57
58 .live_registers = comptime .initFill(.free),
59 .live_values = .empty,
60 .values = .empty,
61 };
62 defer isel.deinit();
63
64 const air_main_body = air.getMainBody();
65 var param_it: Select.CallAbiIterator = .init;
66 const air_args = for (air_main_body, 0..) |air_inst_index, body_index| {
67 if (air.instructions.items(.tag)[@intFromEnum(air_inst_index)] != .arg) break air_main_body[0..body_index];
68 const param_ty = air.instructions.items(.data)[@intFromEnum(air_inst_index)].arg.ty.toType();
69 const param_vi = try param_it.param(&isel, param_ty);
70 tracking_log.debug("${d} <- %{d}", .{ @intFromEnum(param_vi.?), @intFromEnum(air_inst_index) });
71 try isel.live_values.putNoClobber(gpa, air_inst_index, param_vi.?);
72 } else unreachable;
73
74 const saved_gra_start = if (mod.strip) param_it.ngrn else Select.CallAbiIterator.ngrn_start;
75 const saved_gra_end = if (func_type.is_var_args) Select.CallAbiIterator.ngrn_end else param_it.ngrn;
76 const saved_gra_len = @intFromEnum(saved_gra_end) - @intFromEnum(saved_gra_start);
77
78 const saved_vra_start = if (mod.strip) param_it.nsrn else Select.CallAbiIterator.nsrn_start;
79 const saved_vra_end = if (func_type.is_var_args) Select.CallAbiIterator.nsrn_end else param_it.nsrn;
80 const saved_vra_len = @intFromEnum(saved_vra_end) - @intFromEnum(saved_vra_start);
81
82 const frame_record = 2;
83 const named_stack_args: Select.Value.Indirect = .{
84 .base = .fp,
85 .offset = 8 * std.mem.alignForward(u7, frame_record + saved_gra_len, 2),
86 };
87 isel.va_list = .{
88 .__stack = named_stack_args.withOffset(param_it.nsaa),
89 .__gr_top = named_stack_args,
90 .__vr_top = .{ .base = .fp, .offset = 0 },
91 };
92
93 // translate arg locations from caller-based to callee-based
94 for (air_args) |air_inst_index| {
95 assert(air.instructions.items(.tag)[@intFromEnum(air_inst_index)] == .arg);
96 const arg_vi = isel.live_values.get(air_inst_index).?;
97 const passed_vi = switch (arg_vi.parent(&isel)) {
98 .unallocated, .stack_slot => arg_vi,
99 .value, .constant => unreachable,
100 .address => |address_vi| address_vi,
101 };
102 switch (passed_vi.parent(&isel)) {
103 .unallocated => if (!mod.strip) {
104 var part_it = arg_vi.parts(&isel);
105 const first_passed_part_vi = part_it.next() orelse passed_vi;
106 const hint_ra = first_passed_part_vi.hint(&isel).?;
107 passed_vi.setParent(&isel, .{ .stack_slot = if (hint_ra.isVector())
108 isel.va_list.__vr_top.withOffset(@as(i8, -16) *
109 (@intFromEnum(saved_vra_end) - @intFromEnum(hint_ra)))
110 else
111 isel.va_list.__gr_top.withOffset(@as(i8, -8) *
112 (@intFromEnum(saved_gra_end) - @intFromEnum(hint_ra))) });
113 },
114 .stack_slot => |stack_slot| {
115 assert(stack_slot.base == .sp);
116 passed_vi.setParent(&isel, .{
117 .stack_slot = named_stack_args.withOffset(stack_slot.offset),
118 });
119 },
120 .address, .value, .constant => unreachable,
121 }
122 }
123
124 ret: {
125 var ret_it: Select.CallAbiIterator = .init;
126 const ret_vi = try ret_it.ret(&isel, .fromInterned(func_type.return_type)) orelse break :ret;
127 tracking_log.debug("${d} <- %main", .{@intFromEnum(ret_vi)});
128 try isel.live_values.putNoClobber(gpa, Select.Block.main, ret_vi);
129 }
130
131 assert(!(try isel.blocks.getOrPut(gpa, Select.Block.main)).found_existing);
132 try isel.analyze(air_main_body);
133 try isel.finishAnalysis();
134 isel.verify(false);
135
136 isel.blocks.values()[0] = .{
137 .live_registers = isel.live_registers,
138 .target_label = @intCast(isel.instructions.items.len),
139 };
140 try isel.body(air_main_body);
141 if (isel.live_values.fetchRemove(Select.Block.main)) |ret_vi| {
142 switch (ret_vi.value.parent(&isel)) {
143 .unallocated, .stack_slot => {},
144 .value, .constant => unreachable,
145 .address => |address_vi| try address_vi.liveIn(
146 &isel,
147 address_vi.hint(&isel).?,
148 comptime &.initFill(.free),
149 ),
150 }
151 ret_vi.value.deref(&isel);
152 }
153 isel.verify(true);
154
155 const prologue = isel.instructions.items.len;
156 const epilogue = try isel.layout(
157 param_it,
158 func_type.is_var_args,
159 saved_gra_len,
160 saved_vra_len,
161 mod,
162 );
163
164 const instructions = try isel.instructions.toOwnedSlice(gpa);
165 var mir: Mir = .{
166 .prologue = instructions[prologue..epilogue],
167 .body = instructions[0..prologue],
168 .epilogue = instructions[epilogue..],
169 .literals = &.{},
170 .nav_relocs = &.{},
171 .uav_relocs = &.{},
172 .global_relocs = &.{},
173 .literal_relocs = &.{},
174 };
175 errdefer mir.deinit(gpa);
176 mir.literals = try isel.literals.toOwnedSlice(gpa);
177 mir.nav_relocs = try isel.nav_relocs.toOwnedSlice(gpa);
178 mir.uav_relocs = try isel.uav_relocs.toOwnedSlice(gpa);
179 mir.global_relocs = try isel.global_relocs.toOwnedSlice(gpa);
180 mir.literal_relocs = try isel.literal_relocs.toOwnedSlice(gpa);
181 return mir;
182}
183
184test {
185 _ = Assemble;
186}
187
188const Air = @import("../Air.zig");
189const assert = std.debug.assert;
190const InternPool = @import("../InternPool.zig");
191const link = @import("../link.zig");
192const std = @import("std");
193const tracking_log = std.log.scoped(.tracking);
194const Zcu = @import("../Zcu.zig");
src/codegen/aarch64/Assemble.zig created+1653
...@@ -0,0 +1,1653 @@
1source: [*:0]const u8,
2operands: std.StringHashMapUnmanaged(Operand),
3
4pub const Operand = union(enum) {
5 register: aarch64.encoding.Register,
6};
7
8pub fn nextInstruction(as: *Assemble) !?Instruction {
9 @setEvalBranchQuota(37_000);
10 comptime var ct_token_buf: [token_buf_len]u8 = undefined;
11 var token_buf: [token_buf_len]u8 = undefined;
12 const original_source = while (true) {
13 const original_source = as.source;
14 const source_token = try as.nextToken(&token_buf, .{});
15 if (source_token.len == 0) return null;
16 if (source_token[0] != '\n') break original_source;
17 };
18 log.debug(
19 \\.
20 \\=========================
21 \\= Assembling "{f}"
22 \\=========================
23 \\
24 , .{std.zig.fmtString(std.mem.span(original_source))});
25 inline for (instructions) |instruction| {
26 next_pattern: {
27 as.source = original_source;
28 var symbols: Symbols: {
29 const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields;
30 var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined;
31 for (&symbol_fields, symbols) |*symbol_field, symbol| symbol_field.* = .{
32 .name = symbol.name,
33 .type = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage(),
34 .default_value_ptr = null,
35 .is_comptime = false,
36 .alignment = 0,
37 };
38 break :Symbols @Type(.{ .@"struct" = .{
39 .layout = .auto,
40 .fields = &symbol_fields,
41 .decls = &.{},
42 .is_tuple = false,
43 } });
44 } = undefined;
45 comptime var pattern_as: Assemble = .{ .source = instruction.pattern, .operands = undefined };
46 inline while (true) {
47 const pattern_token = comptime pattern_as.nextToken(&ct_token_buf, .{ .placeholders = true }) catch |err|
48 @compileError(@errorName(err) ++ " while parsing '" ++ instruction.pattern ++ "'");
49 const source_token = try as.nextToken(&token_buf, .{ .operands = true });
50 log.debug("\"{f}\" -> \"{f}\"", .{
51 std.zig.fmtString(pattern_token),
52 std.zig.fmtString(source_token),
53 });
54 if (pattern_token.len == 0) {
55 if (source_token.len > 0 and source_token[0] != '\n') break :next_pattern;
56 const encode = @field(Instruction, @tagName(instruction.encode[0]));
57 const Encode = @TypeOf(encode);
58 var args: std.meta.ArgsTuple(Encode) = undefined;
59 inline for (&args, @typeInfo(Encode).@"fn".params, 1..instruction.encode.len) |*arg, param, encode_index|
60 arg.* = zonCast(param.type.?, instruction.encode[encode_index], symbols);
61 return @call(.auto, encode, args);
62 } else if (pattern_token[0] == '<') {
63 const symbol_name = comptime pattern_token[1 .. std.mem.indexOfScalarPos(u8, pattern_token, 1, '|') orelse
64 pattern_token.len - 1];
65 const symbol = &@field(symbols, symbol_name);
66 symbol.* = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse break :next_pattern;
67 log.debug("{s} = {any}", .{ symbol_name, symbol.* });
68 } else if (!std.ascii.eqlIgnoreCase(pattern_token, source_token)) break :next_pattern;
69 }
70 }
71 log.debug("'{s}' not matched...", .{instruction.pattern});
72 }
73 as.source = original_source;
74 log.debug("Nothing matched!\n", .{});
75 return error.InvalidSyntax;
76}
77
78fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result {
79 const ZonValue = @TypeOf(zon_value);
80 const Symbols = @TypeOf(symbols);
81 switch (@typeInfo(ZonValue)) {
82 .void, .bool, .int, .float, .pointer, .comptime_float, .comptime_int, .@"enum" => return zon_value,
83 .@"struct" => |zon_struct| switch (@typeInfo(Result)) {
84 .@"struct" => |result_struct| {
85 comptime var used_zon_fields = 0;
86 var result: Result = undefined;
87 inline for (result_struct.fields) |result_field| @field(result, result_field.name) = if (@hasField(ZonValue, result_field.name)) result: {
88 used_zon_fields += 1;
89 break :result zonCast(@FieldType(Result, result_field.name), @field(zon_value, result_field.name), symbols);
90 } else result_field.defaultValue() orelse @compileError(std.fmt.comptimePrint("missing zon field '{s}': {} <- {any}", .{ result_field.name, Result, zon_value }));
91 if (used_zon_fields != zon_struct.fields.len) @compileError(std.fmt.comptimePrint("unused zon field: {} <- {any}", .{ Result, zon_value }));
92 return result;
93 },
94 .@"union" => {
95 if (zon_struct.fields.len != 1) @compileError(std.fmt.comptimePrint("{} <- {any}", .{ Result, zon_value }));
96 const field_name = zon_struct.fields[0].name;
97 return @unionInit(
98 Result,
99 field_name,
100 zonCast(@FieldType(Result, field_name), @field(zon_value, field_name), symbols),
101 );
102 },
103 else => @compileError(std.fmt.comptimePrint("unsupported zon type: {} <- {any}", .{ Result, zon_value })),
104 },
105 .enum_literal => if (@hasField(Symbols, @tagName(zon_value))) {
106 const symbol = @field(symbols, @tagName(zon_value));
107 const Symbol = @TypeOf(symbol);
108 switch (@typeInfo(Result)) {
109 .@"enum" => switch (@typeInfo(Symbol)) {
110 .int => |symbol_int| {
111 var buf: [
112 std.fmt.count("{d}", .{switch (symbol_int.signedness) {
113 .signed => std.math.minInt(Symbol),
114 .unsigned => std.math.maxInt(Symbol),
115 }})
116 ]u8 = undefined;
117 return std.meta.stringToEnum(Result, std.fmt.bufPrint(&buf, "{d}", .{symbol}) catch unreachable).?;
118 },
119 else => return symbol,
120 },
121 else => return symbol,
122 }
123 } else return if (@hasDecl(Result, @tagName(zon_value))) @field(Result, @tagName(zon_value)) else zon_value,
124 else => @compileError(std.fmt.comptimePrint("unsupported zon type: {} <- {any}", .{ Result, zon_value })),
125 }
126}
127
128const token_buf_len = "v31.b[15]".len;
129fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct {
130 operands: bool = false,
131 placeholders: bool = false,
132}) ![]const u8 {
133 const invalid_syntax: u8 = 1;
134 while (true) c: switch (as.source[0]) {
135 0 => return as.source[0..0],
136 '\t', '\n' + 1...'\r', ' ' => as.source = as.source[1..],
137 '\n', '!', '#', ',', '[', ']' => {
138 defer as.source = as.source[1..];
139 return as.source[0..1];
140 },
141 '%' => if (opts.operands) {
142 if (as.source[1] != '[') continue :c invalid_syntax;
143 const name_start: usize = 2;
144 var index = name_start;
145 while (switch (as.source[index]) {
146 else => true,
147 ':', ']' => false,
148 }) index += 1;
149 const operand = as.operands.get(as.source[name_start..index]) orelse continue :c invalid_syntax;
150 const modifier = modifier: switch (as.source[index]) {
151 else => unreachable,
152 ':' => {
153 index += 1;
154 const modifier_start = index;
155 while (switch (as.source[index]) {
156 else => true,
157 ']' => false,
158 }) index += 1;
159 break :modifier as.source[modifier_start..index];
160 },
161 ']' => "",
162 };
163 assert(as.source[index] == ']');
164 const modified_operand: Operand = if (std.mem.eql(u8, modifier, ""))
165 operand
166 else if (std.mem.eql(u8, modifier, "w")) switch (operand) {
167 .register => |reg| .{ .register = reg.alias.w() },
168 } else if (std.mem.eql(u8, modifier, "x")) switch (operand) {
169 .register => |reg| .{ .register = reg.alias.x() },
170 } else if (std.mem.eql(u8, modifier, "b")) switch (operand) {
171 .register => |reg| .{ .register = reg.alias.b() },
172 } else if (std.mem.eql(u8, modifier, "h")) switch (operand) {
173 .register => |reg| .{ .register = reg.alias.h() },
174 } else if (std.mem.eql(u8, modifier, "s")) switch (operand) {
175 .register => |reg| .{ .register = reg.alias.s() },
176 } else if (std.mem.eql(u8, modifier, "d")) switch (operand) {
177 .register => |reg| .{ .register = reg.alias.d() },
178 } else if (std.mem.eql(u8, modifier, "q")) switch (operand) {
179 .register => |reg| .{ .register = reg.alias.q() },
180 } else if (std.mem.eql(u8, modifier, "Z")) switch (operand) {
181 .register => |reg| .{ .register = reg.alias.z() },
182 } else continue :c invalid_syntax;
183 switch (modified_operand) {
184 .register => |reg| {
185 as.source = as.source[index + 1 ..];
186 return std.fmt.bufPrint(buf, "{f}", .{reg.fmt()}) catch unreachable;
187 },
188 }
189 } else continue :c invalid_syntax,
190 '-', '0'...'9', 'A'...'Z', '_', 'a'...'z' => {
191 var index: usize = 1;
192 while (switch (as.source[index]) {
193 '0'...'9', 'A'...'Z', '_', 'a'...'z' => true,
194 else => false,
195 }) index += 1;
196 defer as.source = as.source[index..];
197 return as.source[0..index];
198 },
199 '<' => if (opts.placeholders) {
200 var index: usize = 1;
201 while (switch (as.source[index]) {
202 0 => return error.UnterminatedPlaceholder,
203 '>' => false,
204 else => true,
205 }) index += 1;
206 defer as.source = as.source[index + 1 ..];
207 return as.source[0 .. index + 1];
208 } else continue :c invalid_syntax,
209 else => {
210 if (!@inComptime()) log.debug("invalid token \"{f}\"", .{std.zig.fmtString(std.mem.span(as.source))});
211 return error.InvalidSyntax;
212 },
213 };
214}
215
216const SymbolSpec = union(enum) {
217 reg: struct { format: aarch64.encoding.Register.Format, allow_sp: bool = false },
218 imm: struct {
219 type: std.builtin.Type.Int,
220 multiple_of: comptime_int = 1,
221 max_valid: ?comptime_int = null,
222 },
223 extend: struct { size: aarch64.encoding.Register.IntegerSize },
224 shift: struct { allow_ror: bool = true },
225 barrier: struct { only_sy: bool = false },
226
227 fn Storage(comptime spec: SymbolSpec) type {
228 return switch (spec) {
229 .reg => aarch64.encoding.Register,
230 .imm => |imm| @Type(.{ .int = imm.type }),
231 .extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,
232 .shift => Instruction.DataProcessingRegister.Shift.Op,
233 .barrier => Instruction.BranchExceptionGeneratingSystem.Barriers.Option,
234 };
235 }
236
237 fn parse(comptime spec: SymbolSpec, token: []const u8) ?Storage(spec) {
238 const Result = Storage(spec);
239 switch (spec) {
240 .reg => |reg_spec| {
241 var buf: [token_buf_len]u8 = undefined;
242 const reg = Result.parse(std.ascii.lowerString(&buf, token[0..@min(token.len, buf.len)])) orelse {
243 log.debug("invalid register: \"{f}\"", .{std.zig.fmtString(token)});
244 return null;
245 };
246 if (reg.format.integer != reg_spec.format.integer) {
247 log.debug("invalid register size: \"{f}\"", .{std.zig.fmtString(token)});
248 return null;
249 }
250 if (reg.alias == if (reg_spec.allow_sp) .zr else .sp) {
251 log.debug("invalid register usage: \"{f}\"", .{std.zig.fmtString(token)});
252 return null;
253 }
254 return reg;
255 },
256 .imm => |imm_spec| {
257 const imm = std.fmt.parseInt(Result, token, 0) catch {
258 log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)});
259 return null;
260 };
261 if (@rem(imm, imm_spec.multiple_of) != 0) {
262 log.debug("invalid immediate usage: \"{f}\"", .{std.zig.fmtString(token)});
263 return null;
264 }
265 if (imm_spec.max_valid) |max_valid| if (imm > max_valid) {
266 log.debug("out of range immediate: \"{f}\"", .{std.zig.fmtString(token)});
267 return null;
268 };
269 return imm;
270 },
271 .extend => |extend_spec| {
272 const Option = Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option;
273 var buf: [
274 max_len: {
275 var max_len = 0;
276 for (@typeInfo(Option).@"enum".fields) |field| max_len = @max(max_len, field.name.len);
277 break :max_len max_len;
278 } + 1
279 ]u8 = undefined;
280 const extend = std.meta.stringToEnum(Option, std.ascii.lowerString(
281 &buf,
282 token[0..@min(token.len, buf.len)],
283 )) orelse {
284 log.debug("invalid extend: \"{f}\"", .{std.zig.fmtString(token)});
285 return null;
286 };
287 if (extend.sf() != extend_spec.size) {
288 log.debug("invalid extend: \"{f}\"", .{std.zig.fmtString(token)});
289 return null;
290 }
291 return extend;
292 },
293 .shift => |shift_spec| {
294 const ShiftOp = Instruction.DataProcessingRegister.Shift.Op;
295 var buf: [
296 max_len: {
297 var max_len = 0;
298 for (@typeInfo(ShiftOp).@"enum".fields) |field| max_len = @max(max_len, field.name.len);
299 break :max_len max_len;
300 } + 1
301 ]u8 = undefined;
302 const shift = std.meta.stringToEnum(ShiftOp, std.ascii.lowerString(
303 &buf,
304 token[0..@min(token.len, buf.len)],
305 )) orelse {
306 log.debug("invalid shift: \"{f}\"", .{std.zig.fmtString(token)});
307 return null;
308 };
309 if (!shift_spec.allow_ror and shift == .ror) {
310 log.debug("invalid shift usage: \"{f}\"", .{std.zig.fmtString(token)});
311 return null;
312 }
313 return shift;
314 },
315 .barrier => |barrier_spec| {
316 const Option = Instruction.BranchExceptionGeneratingSystem.Barriers.Option;
317 var buf: [
318 max_len: {
319 var max_len = 0;
320 for (@typeInfo(Option).@"enum".fields) |field| max_len = @max(max_len, field.name.len);
321 break :max_len max_len;
322 } + 1
323 ]u8 = undefined;
324 const barrier = std.meta.stringToEnum(Option, std.ascii.lowerString(
325 &buf,
326 token[0..@min(token.len, buf.len)],
327 )) orelse {
328 log.debug("invalid barrier: \"{f}\"", .{std.zig.fmtString(token)});
329 return null;
330 };
331 if (barrier_spec.only_sy and barrier != .sy) {
332 log.debug("invalid barrier: \"{f}\"", .{std.zig.fmtString(token)});
333 return null;
334 }
335 return barrier;
336 },
337 }
338 }
339};
340
341test "add sub" {
342 var as: Assemble = .{
343 .source =
344 \\ add w0, w0, w1
345 \\ add w2, w3, w4
346 \\ add wsp, w5, w6
347 \\ add w7, wsp, w8
348 \\ add wsp, wsp, w9
349 \\ add w10, w10, wzr
350 \\ add w11, w12, wzr
351 \\ add wsp, w13, wzr
352 \\ add w14, wsp, wzr
353 \\ add wsp, wsp, wzr
354 \\
355 \\ add x0, x0, x1
356 \\ add x2, x3, x4
357 \\ add sp, x5, x6
358 \\ add x7, sp, x8
359 \\ add sp, sp, x9
360 \\ add x10, x10, xzr
361 \\ add x11, x12, xzr
362 \\ add sp, x13, xzr
363 \\ add x14, sp, xzr
364 \\ add sp, sp, xzr
365 \\
366 \\ add w0, w0, w1
367 \\ add w2, w3, w4, uxtb #0
368 \\ add wsp, w5, w6, uxth #1
369 \\ add w7, wsp, w8, uxtw #0
370 \\ add wsp, wsp, w9, uxtw #2
371 \\ add w10, w10, wzr, uxtw #3
372 \\ add w11, w12, wzr, sxtb #4
373 \\ add wsp, w13, wzr, sxth #0
374 \\ add w14, wsp, wzr, sxtw #1
375 \\ add wsp, wsp, wzr, sxtw #2
376 \\
377 \\ add x0, x0, x1
378 \\ add x2, x3, w4, uxtb #0
379 \\ add sp, x5, w6, uxth #1
380 \\ add x7, sp, w8, uxtw #2
381 \\ add sp, sp, x9, uxtx #0
382 \\ add x10, x10, xzr, uxtx #3
383 \\ add x11, x12, wzr, sxtb #4
384 \\ add sp, x13, wzr, sxth #0
385 \\ add x14, sp, wzr, sxtw #1
386 \\ add sp, sp, xzr, sxtx #2
387 \\
388 \\ add w0, w0, #0
389 \\ add w0, w1, #1, lsl #0
390 \\ add wsp, w2, #2, lsl #12
391 \\ add w3, wsp, #3, lsl #0
392 \\ add wsp, wsp, #4095, lsl #12
393 \\ add w0, w1, #0
394 \\ add w2, w3, #0, lsl #0
395 \\ add w4, wsp, #0
396 \\ add w5, wsp, #0, lsl #0
397 \\ add wsp, w6, #0
398 \\ add wsp, w7, #0, lsl #0
399 \\ add wsp, wsp, #0
400 \\ add wsp, wsp, #0, lsl #0
401 \\
402 \\ add x0, x0, #0
403 \\ add x0, x1, #1, lsl #0
404 \\ add sp, x2, #2, lsl #12
405 \\ add x3, sp, #3, lsl #0
406 \\ add sp, sp, #4095, lsl #12
407 \\ add x0, x1, #0
408 \\ add x2, x3, #0, lsl #0
409 \\ add x4, sp, #0
410 \\ add x5, sp, #0, lsl #0
411 \\ add sp, x6, #0
412 \\ add sp, x7, #0, lsl #0
413 \\ add sp, sp, #0
414 \\ add sp, sp, #0, lsl #0
415 \\
416 \\ add w0, w0, w0
417 \\ add w1, w1, w2, lsl #0
418 \\ add w3, w4, w5, lsl #1
419 \\ add w6, w6, wzr, lsl #31
420 \\ add w7, wzr, w8, lsr #0
421 \\ add w9, wzr, wzr, lsr #30
422 \\ add wzr, w10, w11, lsr #31
423 \\ add wzr, w12, wzr, asr #0x0
424 \\ add wzr, wzr, w13, asr #0x10
425 \\ add wzr, wzr, wzr, asr #0x1f
426 \\
427 \\ add x0, x0, x0
428 \\ add x1, x1, x2, lsl #0
429 \\ add x3, x4, x5, lsl #1
430 \\ add x6, x6, xzr, lsl #63
431 \\ add x7, xzr, x8, lsr #0
432 \\ add x9, xzr, xzr, lsr #62
433 \\ add xzr, x10, x11, lsr #63
434 \\ add xzr, x12, xzr, asr #0x0
435 \\ add xzr, xzr, x13, asr #0x1F
436 \\ add xzr, xzr, xzr, asr #0x3f
437 \\
438 \\ sub w0, w0, w1
439 \\ sub w2, w3, w4
440 \\ sub wsp, w5, w6
441 \\ sub w7, wsp, w8
442 \\ sub wsp, wsp, w9
443 \\ sub w10, w10, wzr
444 \\ sub w11, w12, wzr
445 \\ sub wsp, w13, wzr
446 \\ sub w14, wsp, wzr
447 \\ sub wsp, wsp, wzr
448 \\
449 \\ sub x0, x0, x1
450 \\ sub x2, x3, x4
451 \\ sub sp, x5, x6
452 \\ sub x7, sp, x8
453 \\ sub sp, sp, x9
454 \\ sub x10, x10, xzr
455 \\ sub x11, x12, xzr
456 \\ sub sp, x13, xzr
457 \\ sub x14, sp, xzr
458 \\ sub sp, sp, xzr
459 \\
460 \\ sub w0, w0, w1
461 \\ sub w2, w3, w4, uxtb #0
462 \\ sub wsp, w5, w6, uxth #1
463 \\ sub w7, wsp, w8, uxtw #0
464 \\ sub wsp, wsp, w9, uxtw #2
465 \\ sub w10, w10, wzr, uxtw #3
466 \\ sub w11, w12, wzr, sxtb #4
467 \\ sub wsp, w13, wzr, sxth #0
468 \\ sub w14, wsp, wzr, sxtw #1
469 \\ sub wsp, wsp, wzr, sxtw #2
470 \\
471 \\ sub x0, x0, x1
472 \\ sub x2, x3, w4, uxtb #0
473 \\ sub sp, x5, w6, uxth #1
474 \\ sub x7, sp, w8, uxtw #2
475 \\ sub sp, sp, x9, uxtx #0
476 \\ sub x10, x10, xzr, uxtx #3
477 \\ sub x11, x12, wzr, sxtb #4
478 \\ sub sp, x13, wzr, sxth #0
479 \\ sub x14, sp, wzr, sxtw #1
480 \\ sub sp, sp, xzr, sxtx #2
481 \\
482 \\ sub w0, w0, #0
483 \\ sub w0, w1, #1, lsl #0
484 \\ sub wsp, w2, #2, lsl #12
485 \\ sub w3, wsp, #3, lsl #0
486 \\ sub wsp, wsp, #4095, lsl #12
487 \\ sub w0, w1, #0
488 \\ sub w2, w3, #0, lsl #0
489 \\ sub w4, wsp, #0
490 \\ sub w5, wsp, #0, lsl #0
491 \\ sub wsp, w6, #0
492 \\ sub wsp, w7, #0, lsl #0
493 \\ sub wsp, wsp, #0
494 \\ sub wsp, wsp, #0, lsl #0
495 \\
496 \\ sub x0, x0, #0
497 \\ sub x0, x1, #1, lsl #0
498 \\ sub sp, x2, #2, lsl #12
499 \\ sub x3, sp, #3, lsl #0
500 \\ sub sp, sp, #4095, lsl #12
501 \\ sub x0, x1, #0
502 \\ sub x2, x3, #0, lsl #0
503 \\ sub x4, sp, #0
504 \\ sub x5, sp, #0, lsl #0
505 \\ sub sp, x6, #0
506 \\ sub sp, x7, #0, lsl #0
507 \\ sub sp, sp, #0
508 \\ sub sp, sp, #0, lsl #0
509 \\
510 \\ sub w0, w0, w0
511 \\ sub w1, w1, w2, lsl #0
512 \\ sub w3, w4, w5, lsl #1
513 \\ sub w6, w6, wzr, lsl #31
514 \\ sub w7, wzr, w8, lsr #0
515 \\ sub w9, wzr, wzr, lsr #30
516 \\ sub wzr, w10, w11, lsr #31
517 \\ sub wzr, w12, wzr, asr #0x0
518 \\ sub wzr, wzr, w13, asr #0x10
519 \\ sub wzr, wzr, wzr, asr #0x1f
520 \\
521 \\ sub x0, x0, x0
522 \\ sub x1, x1, x2, lsl #0
523 \\ sub x3, x4, x5, lsl #1
524 \\ sub x6, x6, xzr, lsl #63
525 \\ sub x7, xzr, x8, lsr #0
526 \\ sub x9, xzr, xzr, lsr #62
527 \\ sub xzr, x10, x11, lsr #63
528 \\ sub xzr, x12, xzr, asr #0x0
529 \\ sub xzr, xzr, x13, asr #0x1F
530 \\ sub xzr, xzr, xzr, asr #0x3f
531 \\
532 \\ neg w0, w0
533 \\ neg w1, w2, lsl #0
534 \\ neg w3, wzr, lsl #7
535 \\ neg wzr, w4, lsr #14
536 \\ neg wzr, wzr, asr #21
537 \\
538 \\ neg x0, x0
539 \\ neg x1, x2, lsl #0
540 \\ neg x3, xzr, lsl #11
541 \\ neg xzr, x4, lsr #22
542 \\ neg xzr, xzr, asr #33
543 ,
544 .operands = .empty,
545 };
546
547 try std.testing.expectFmt("add w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
548 try std.testing.expectFmt("add w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
549 try std.testing.expectFmt("add wsp, w5, w6", "{f}", .{(try as.nextInstruction()).?});
550 try std.testing.expectFmt("add w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
551 try std.testing.expectFmt("add wsp, wsp, w9", "{f}", .{(try as.nextInstruction()).?});
552 try std.testing.expectFmt("add w10, w10, wzr", "{f}", .{(try as.nextInstruction()).?});
553 try std.testing.expectFmt("add w11, w12, wzr", "{f}", .{(try as.nextInstruction()).?});
554 try std.testing.expectFmt("add wsp, w13, wzr", "{f}", .{(try as.nextInstruction()).?});
555 try std.testing.expectFmt("add w14, wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
556 try std.testing.expectFmt("add wsp, wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
557
558 try std.testing.expectFmt("add x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
559 try std.testing.expectFmt("add x2, x3, x4", "{f}", .{(try as.nextInstruction()).?});
560 try std.testing.expectFmt("add sp, x5, x6", "{f}", .{(try as.nextInstruction()).?});
561 try std.testing.expectFmt("add x7, sp, x8", "{f}", .{(try as.nextInstruction()).?});
562 try std.testing.expectFmt("add sp, sp, x9", "{f}", .{(try as.nextInstruction()).?});
563 try std.testing.expectFmt("add x10, x10, xzr", "{f}", .{(try as.nextInstruction()).?});
564 try std.testing.expectFmt("add x11, x12, xzr", "{f}", .{(try as.nextInstruction()).?});
565 try std.testing.expectFmt("add sp, x13, xzr", "{f}", .{(try as.nextInstruction()).?});
566 try std.testing.expectFmt("add x14, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
567 try std.testing.expectFmt("add sp, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
568
569 try std.testing.expectFmt("add w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
570 try std.testing.expectFmt("add w2, w3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
571 try std.testing.expectFmt("add wsp, w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
572 try std.testing.expectFmt("add w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
573 try std.testing.expectFmt("add wsp, wsp, w9, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
574 try std.testing.expectFmt("add w10, w10, wzr, uxtw #3", "{f}", .{(try as.nextInstruction()).?});
575 try std.testing.expectFmt("add w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
576 try std.testing.expectFmt("add wsp, w13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
577 try std.testing.expectFmt("add w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
578 try std.testing.expectFmt("add wsp, wsp, wzr, sxtw #2", "{f}", .{(try as.nextInstruction()).?});
579
580 try std.testing.expectFmt("add x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
581 try std.testing.expectFmt("add x2, x3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
582 try std.testing.expectFmt("add sp, x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
583 try std.testing.expectFmt("add x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
584 try std.testing.expectFmt("add sp, sp, x9", "{f}", .{(try as.nextInstruction()).?});
585 try std.testing.expectFmt("add x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
586 try std.testing.expectFmt("add x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
587 try std.testing.expectFmt("add sp, x13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
588 try std.testing.expectFmt("add x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
589 try std.testing.expectFmt("add sp, sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
590
591 try std.testing.expectFmt("add w0, w0, #0x0", "{f}", .{(try as.nextInstruction()).?});
592 try std.testing.expectFmt("add w0, w1, #0x1", "{f}", .{(try as.nextInstruction()).?});
593 try std.testing.expectFmt("add wsp, w2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
594 try std.testing.expectFmt("add w3, wsp, #0x3", "{f}", .{(try as.nextInstruction()).?});
595 try std.testing.expectFmt("add wsp, wsp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
596 try std.testing.expectFmt("add w0, w1, #0x0", "{f}", .{(try as.nextInstruction()).?});
597 try std.testing.expectFmt("add w2, w3, #0x0", "{f}", .{(try as.nextInstruction()).?});
598 try std.testing.expectFmt("mov w4, wsp", "{f}", .{(try as.nextInstruction()).?});
599 try std.testing.expectFmt("mov w5, wsp", "{f}", .{(try as.nextInstruction()).?});
600 try std.testing.expectFmt("mov wsp, w6", "{f}", .{(try as.nextInstruction()).?});
601 try std.testing.expectFmt("mov wsp, w7", "{f}", .{(try as.nextInstruction()).?});
602 try std.testing.expectFmt("mov wsp, wsp", "{f}", .{(try as.nextInstruction()).?});
603 try std.testing.expectFmt("mov wsp, wsp", "{f}", .{(try as.nextInstruction()).?});
604
605 try std.testing.expectFmt("add x0, x0, #0x0", "{f}", .{(try as.nextInstruction()).?});
606 try std.testing.expectFmt("add x0, x1, #0x1", "{f}", .{(try as.nextInstruction()).?});
607 try std.testing.expectFmt("add sp, x2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
608 try std.testing.expectFmt("add x3, sp, #0x3", "{f}", .{(try as.nextInstruction()).?});
609 try std.testing.expectFmt("add sp, sp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
610 try std.testing.expectFmt("add x0, x1, #0x0", "{f}", .{(try as.nextInstruction()).?});
611 try std.testing.expectFmt("add x2, x3, #0x0", "{f}", .{(try as.nextInstruction()).?});
612 try std.testing.expectFmt("mov x4, sp", "{f}", .{(try as.nextInstruction()).?});
613 try std.testing.expectFmt("mov x5, sp", "{f}", .{(try as.nextInstruction()).?});
614 try std.testing.expectFmt("mov sp, x6", "{f}", .{(try as.nextInstruction()).?});
615 try std.testing.expectFmt("mov sp, x7", "{f}", .{(try as.nextInstruction()).?});
616 try std.testing.expectFmt("mov sp, sp", "{f}", .{(try as.nextInstruction()).?});
617 try std.testing.expectFmt("mov sp, sp", "{f}", .{(try as.nextInstruction()).?});
618
619 try std.testing.expectFmt("add w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
620 try std.testing.expectFmt("add w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
621 try std.testing.expectFmt("add w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
622 try std.testing.expectFmt("add w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
623 try std.testing.expectFmt("add w7, wzr, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
624 try std.testing.expectFmt("add w9, wzr, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
625 try std.testing.expectFmt("add wzr, w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
626 try std.testing.expectFmt("add wzr, w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
627 try std.testing.expectFmt("add wzr, wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
628 try std.testing.expectFmt("add wzr, wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
629
630 try std.testing.expectFmt("add x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
631 try std.testing.expectFmt("add x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
632 try std.testing.expectFmt("add x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
633 try std.testing.expectFmt("add x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
634 try std.testing.expectFmt("add x7, xzr, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
635 try std.testing.expectFmt("add x9, xzr, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
636 try std.testing.expectFmt("add xzr, x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
637 try std.testing.expectFmt("add xzr, x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
638 try std.testing.expectFmt("add xzr, xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
639 try std.testing.expectFmt("add xzr, xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
640
641 try std.testing.expectFmt("sub w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
642 try std.testing.expectFmt("sub w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
643 try std.testing.expectFmt("sub wsp, w5, w6", "{f}", .{(try as.nextInstruction()).?});
644 try std.testing.expectFmt("sub w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
645 try std.testing.expectFmt("sub wsp, wsp, w9", "{f}", .{(try as.nextInstruction()).?});
646 try std.testing.expectFmt("sub w10, w10, wzr", "{f}", .{(try as.nextInstruction()).?});
647 try std.testing.expectFmt("sub w11, w12, wzr", "{f}", .{(try as.nextInstruction()).?});
648 try std.testing.expectFmt("sub wsp, w13, wzr", "{f}", .{(try as.nextInstruction()).?});
649 try std.testing.expectFmt("sub w14, wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
650 try std.testing.expectFmt("sub wsp, wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
651
652 try std.testing.expectFmt("sub x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
653 try std.testing.expectFmt("sub x2, x3, x4", "{f}", .{(try as.nextInstruction()).?});
654 try std.testing.expectFmt("sub sp, x5, x6", "{f}", .{(try as.nextInstruction()).?});
655 try std.testing.expectFmt("sub x7, sp, x8", "{f}", .{(try as.nextInstruction()).?});
656 try std.testing.expectFmt("sub sp, sp, x9", "{f}", .{(try as.nextInstruction()).?});
657 try std.testing.expectFmt("sub x10, x10, xzr", "{f}", .{(try as.nextInstruction()).?});
658 try std.testing.expectFmt("sub x11, x12, xzr", "{f}", .{(try as.nextInstruction()).?});
659 try std.testing.expectFmt("sub sp, x13, xzr", "{f}", .{(try as.nextInstruction()).?});
660 try std.testing.expectFmt("sub x14, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
661 try std.testing.expectFmt("sub sp, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
662
663 try std.testing.expectFmt("sub w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
664 try std.testing.expectFmt("sub w2, w3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
665 try std.testing.expectFmt("sub wsp, w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
666 try std.testing.expectFmt("sub w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
667 try std.testing.expectFmt("sub wsp, wsp, w9, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
668 try std.testing.expectFmt("sub w10, w10, wzr, uxtw #3", "{f}", .{(try as.nextInstruction()).?});
669 try std.testing.expectFmt("sub w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
670 try std.testing.expectFmt("sub wsp, w13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
671 try std.testing.expectFmt("sub w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
672 try std.testing.expectFmt("sub wsp, wsp, wzr, sxtw #2", "{f}", .{(try as.nextInstruction()).?});
673
674 try std.testing.expectFmt("sub x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
675 try std.testing.expectFmt("sub x2, x3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
676 try std.testing.expectFmt("sub sp, x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
677 try std.testing.expectFmt("sub x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
678 try std.testing.expectFmt("sub sp, sp, x9", "{f}", .{(try as.nextInstruction()).?});
679 try std.testing.expectFmt("sub x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
680 try std.testing.expectFmt("sub x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
681 try std.testing.expectFmt("sub sp, x13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
682 try std.testing.expectFmt("sub x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
683 try std.testing.expectFmt("sub sp, sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
684
685 try std.testing.expectFmt("sub w0, w0, #0x0", "{f}", .{(try as.nextInstruction()).?});
686 try std.testing.expectFmt("sub w0, w1, #0x1", "{f}", .{(try as.nextInstruction()).?});
687 try std.testing.expectFmt("sub wsp, w2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
688 try std.testing.expectFmt("sub w3, wsp, #0x3", "{f}", .{(try as.nextInstruction()).?});
689 try std.testing.expectFmt("sub wsp, wsp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
690 try std.testing.expectFmt("sub w0, w1, #0x0", "{f}", .{(try as.nextInstruction()).?});
691 try std.testing.expectFmt("sub w2, w3, #0x0", "{f}", .{(try as.nextInstruction()).?});
692 try std.testing.expectFmt("sub w4, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
693 try std.testing.expectFmt("sub w5, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
694 try std.testing.expectFmt("sub wsp, w6, #0x0", "{f}", .{(try as.nextInstruction()).?});
695 try std.testing.expectFmt("sub wsp, w7, #0x0", "{f}", .{(try as.nextInstruction()).?});
696 try std.testing.expectFmt("sub wsp, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
697 try std.testing.expectFmt("sub wsp, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
698
699 try std.testing.expectFmt("sub x0, x0, #0x0", "{f}", .{(try as.nextInstruction()).?});
700 try std.testing.expectFmt("sub x0, x1, #0x1", "{f}", .{(try as.nextInstruction()).?});
701 try std.testing.expectFmt("sub sp, x2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
702 try std.testing.expectFmt("sub x3, sp, #0x3", "{f}", .{(try as.nextInstruction()).?});
703 try std.testing.expectFmt("sub sp, sp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
704 try std.testing.expectFmt("sub x0, x1, #0x0", "{f}", .{(try as.nextInstruction()).?});
705 try std.testing.expectFmt("sub x2, x3, #0x0", "{f}", .{(try as.nextInstruction()).?});
706 try std.testing.expectFmt("sub x4, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
707 try std.testing.expectFmt("sub x5, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
708 try std.testing.expectFmt("sub sp, x6, #0x0", "{f}", .{(try as.nextInstruction()).?});
709 try std.testing.expectFmt("sub sp, x7, #0x0", "{f}", .{(try as.nextInstruction()).?});
710 try std.testing.expectFmt("sub sp, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
711 try std.testing.expectFmt("sub sp, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
712
713 try std.testing.expectFmt("sub w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
714 try std.testing.expectFmt("sub w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
715 try std.testing.expectFmt("sub w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
716 try std.testing.expectFmt("sub w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
717 try std.testing.expectFmt("neg w7, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
718 try std.testing.expectFmt("neg w9, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
719 try std.testing.expectFmt("sub wzr, w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
720 try std.testing.expectFmt("sub wzr, w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
721 try std.testing.expectFmt("neg wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
722 try std.testing.expectFmt("neg wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
723
724 try std.testing.expectFmt("sub x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
725 try std.testing.expectFmt("sub x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
726 try std.testing.expectFmt("sub x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
727 try std.testing.expectFmt("sub x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
728 try std.testing.expectFmt("neg x7, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
729 try std.testing.expectFmt("neg x9, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
730 try std.testing.expectFmt("sub xzr, x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
731 try std.testing.expectFmt("sub xzr, x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
732 try std.testing.expectFmt("neg xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
733 try std.testing.expectFmt("neg xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
734
735 try std.testing.expectFmt("neg w0, w0", "{f}", .{(try as.nextInstruction()).?});
736 try std.testing.expectFmt("neg w1, w2", "{f}", .{(try as.nextInstruction()).?});
737 try std.testing.expectFmt("neg w3, wzr, lsl #7", "{f}", .{(try as.nextInstruction()).?});
738 try std.testing.expectFmt("neg wzr, w4, lsr #14", "{f}", .{(try as.nextInstruction()).?});
739 try std.testing.expectFmt("neg wzr, wzr, asr #21", "{f}", .{(try as.nextInstruction()).?});
740
741 try std.testing.expectFmt("neg x0, x0", "{f}", .{(try as.nextInstruction()).?});
742 try std.testing.expectFmt("neg x1, x2", "{f}", .{(try as.nextInstruction()).?});
743 try std.testing.expectFmt("neg x3, xzr, lsl #11", "{f}", .{(try as.nextInstruction()).?});
744 try std.testing.expectFmt("neg xzr, x4, lsr #22", "{f}", .{(try as.nextInstruction()).?});
745 try std.testing.expectFmt("neg xzr, xzr, asr #33", "{f}", .{(try as.nextInstruction()).?});
746
747 try std.testing.expect(null == try as.nextInstruction());
748}
749test "bitfield" {
750 var as: Assemble = .{
751 .source =
752 \\sbfm w0, w0, #0, #31
753 \\sbfm w0, w0, #31, #0
754 \\
755 \\sbfm x0, x0, #0, #63
756 \\sbfm x0, x0, #63, #0
757 \\
758 \\bfm w0, w0, #0, #31
759 \\bfm w0, w0, #31, #0
760 \\
761 \\bfm x0, x0, #0, #63
762 \\bfm x0, x0, #63, #0
763 \\
764 \\ubfm w0, w0, #0, #31
765 \\ubfm w0, w0, #31, #0
766 \\
767 \\ubfm x0, x0, #0, #63
768 \\ubfm x0, x0, #63, #0
769 ,
770 .operands = .empty,
771 };
772
773 try std.testing.expectFmt("sbfm w0, w0, #0, #31", "{f}", .{(try as.nextInstruction()).?});
774 try std.testing.expectFmt("sbfm w0, w0, #31, #0", "{f}", .{(try as.nextInstruction()).?});
775
776 try std.testing.expectFmt("sbfm x0, x0, #0, #63", "{f}", .{(try as.nextInstruction()).?});
777 try std.testing.expectFmt("sbfm x0, x0, #63, #0", "{f}", .{(try as.nextInstruction()).?});
778
779 try std.testing.expectFmt("bfm w0, w0, #0, #31", "{f}", .{(try as.nextInstruction()).?});
780 try std.testing.expectFmt("bfm w0, w0, #31, #0", "{f}", .{(try as.nextInstruction()).?});
781
782 try std.testing.expectFmt("bfm x0, x0, #0, #63", "{f}", .{(try as.nextInstruction()).?});
783 try std.testing.expectFmt("bfm x0, x0, #63, #0", "{f}", .{(try as.nextInstruction()).?});
784
785 try std.testing.expectFmt("ubfm w0, w0, #0, #31", "{f}", .{(try as.nextInstruction()).?});
786 try std.testing.expectFmt("ubfm w0, w0, #31, #0", "{f}", .{(try as.nextInstruction()).?});
787
788 try std.testing.expectFmt("ubfm x0, x0, #0, #63", "{f}", .{(try as.nextInstruction()).?});
789 try std.testing.expectFmt("ubfm x0, x0, #63, #0", "{f}", .{(try as.nextInstruction()).?});
790
791 try std.testing.expect(null == try as.nextInstruction());
792}
793test "branch register" {
794 var as: Assemble = .{
795 .source =
796 \\ret
797 \\br x30
798 \\blr x30
799 \\ret x30
800 \\br x29
801 \\blr x29
802 \\ret x29
803 \\br x2
804 \\blr x1
805 \\ret x0
806 ,
807 .operands = .empty,
808 };
809
810 try std.testing.expectFmt("ret", "{f}", .{(try as.nextInstruction()).?});
811 try std.testing.expectFmt("br x30", "{f}", .{(try as.nextInstruction()).?});
812 try std.testing.expectFmt("blr x30", "{f}", .{(try as.nextInstruction()).?});
813 try std.testing.expectFmt("ret", "{f}", .{(try as.nextInstruction()).?});
814 try std.testing.expectFmt("br x29", "{f}", .{(try as.nextInstruction()).?});
815 try std.testing.expectFmt("blr x29", "{f}", .{(try as.nextInstruction()).?});
816 try std.testing.expectFmt("ret x29", "{f}", .{(try as.nextInstruction()).?});
817 try std.testing.expectFmt("br x2", "{f}", .{(try as.nextInstruction()).?});
818 try std.testing.expectFmt("blr x1", "{f}", .{(try as.nextInstruction()).?});
819 try std.testing.expectFmt("ret x0", "{f}", .{(try as.nextInstruction()).?});
820
821 try std.testing.expect(null == try as.nextInstruction());
822}
823test "exception generating" {
824 var as: Assemble = .{
825 .source =
826 \\SVC #0
827 \\HVC #0x1
828 \\SMC #0o15
829 \\BRK #42
830 \\HLT #0x42
831 \\TCANCEL #123
832 \\DCPS1 #1234
833 \\DCPS2 #12345
834 \\DCPS3 #65535
835 \\DCPS3 #0x0
836 \\DCPS2 #0
837 \\DCPS1
838 ,
839 .operands = .empty,
840 };
841
842 try std.testing.expectFmt("svc #0", "{f}", .{(try as.nextInstruction()).?});
843 try std.testing.expectFmt("hvc #0x1", "{f}", .{(try as.nextInstruction()).?});
844 try std.testing.expectFmt("smc #0xd", "{f}", .{(try as.nextInstruction()).?});
845 try std.testing.expectFmt("brk #0x2a", "{f}", .{(try as.nextInstruction()).?});
846 try std.testing.expectFmt("hlt #0x42", "{f}", .{(try as.nextInstruction()).?});
847 try std.testing.expectFmt("tcancel #0x7b", "{f}", .{(try as.nextInstruction()).?});
848 try std.testing.expectFmt("dcps1 #0x4d2", "{f}", .{(try as.nextInstruction()).?});
849 try std.testing.expectFmt("dcps2 #0x3039", "{f}", .{(try as.nextInstruction()).?});
850 try std.testing.expectFmt("dcps3 #0xffff", "{f}", .{(try as.nextInstruction()).?});
851 try std.testing.expectFmt("dcps3", "{f}", .{(try as.nextInstruction()).?});
852 try std.testing.expectFmt("dcps2", "{f}", .{(try as.nextInstruction()).?});
853 try std.testing.expectFmt("dcps1", "{f}", .{(try as.nextInstruction()).?});
854
855 try std.testing.expect(null == try as.nextInstruction());
856}
857test "extract" {
858 var as: Assemble = .{
859 .source =
860 \\extr W0, W1, W2, #0
861 \\extr W3, W3, W4, #1
862 \\extr W5, W5, W5, #31
863 \\
864 \\extr X0, X1, X2, #0
865 \\extr X3, X3, X4, #1
866 \\extr X5, X5, X5, #63
867 ,
868 .operands = .empty,
869 };
870
871 try std.testing.expectFmt("extr w0, w1, w2, #0", "{f}", .{(try as.nextInstruction()).?});
872 try std.testing.expectFmt("extr w3, w3, w4, #1", "{f}", .{(try as.nextInstruction()).?});
873 try std.testing.expectFmt("extr w5, w5, w5, #31", "{f}", .{(try as.nextInstruction()).?});
874
875 try std.testing.expectFmt("extr x0, x1, x2, #0", "{f}", .{(try as.nextInstruction()).?});
876 try std.testing.expectFmt("extr x3, x3, x4, #1", "{f}", .{(try as.nextInstruction()).?});
877 try std.testing.expectFmt("extr x5, x5, x5, #63", "{f}", .{(try as.nextInstruction()).?});
878
879 try std.testing.expect(null == try as.nextInstruction());
880}
881test "hints" {
882 var as: Assemble = .{
883 .source =
884 \\NOP
885 \\hint #0
886 \\YiElD
887 \\Hint #0x1
888 \\WfE
889 \\hInt #02
890 \\wFi
891 \\hiNt #0b11
892 \\sEv
893 \\hinT #4
894 \\sevl
895 \\HINT #0b101
896 \\hint #0x7F
897 ,
898 .operands = .empty,
899 };
900
901 try std.testing.expectFmt("nop", "{f}", .{(try as.nextInstruction()).?});
902 try std.testing.expectFmt("nop", "{f}", .{(try as.nextInstruction()).?});
903 try std.testing.expectFmt("yield", "{f}", .{(try as.nextInstruction()).?});
904 try std.testing.expectFmt("yield", "{f}", .{(try as.nextInstruction()).?});
905 try std.testing.expectFmt("wfe", "{f}", .{(try as.nextInstruction()).?});
906 try std.testing.expectFmt("wfe", "{f}", .{(try as.nextInstruction()).?});
907 try std.testing.expectFmt("wfi", "{f}", .{(try as.nextInstruction()).?});
908 try std.testing.expectFmt("wfi", "{f}", .{(try as.nextInstruction()).?});
909 try std.testing.expectFmt("sev", "{f}", .{(try as.nextInstruction()).?});
910 try std.testing.expectFmt("sev", "{f}", .{(try as.nextInstruction()).?});
911 try std.testing.expectFmt("sevl", "{f}", .{(try as.nextInstruction()).?});
912 try std.testing.expectFmt("sevl", "{f}", .{(try as.nextInstruction()).?});
913 try std.testing.expectFmt("hint #0x7f", "{f}", .{(try as.nextInstruction()).?});
914
915 try std.testing.expect(null == try as.nextInstruction());
916}
917test "load store" {
918 var as: Assemble = .{
919 .source =
920 \\ LDP w0, w1, [x2], #-256
921 \\ LDP w3, w4, [x5], #0
922 \\ LDP w6, w7, [sp], #252
923 \\ LDP w0, w1, [x2, #-0x100]!
924 \\ LDP w3, w4, [x5, #0]!
925 \\ LDP w6, w7, [sp, #0xfc]!
926 \\ LDP w0, w1, [x2, #-256]
927 \\ LDP w3, w4, [x5]
928 \\ LDP w6, w7, [x8, #0]
929 \\ LDP w9, w10, [sp, #252]
930 \\
931 \\ LDP x0, x1, [x2], #-512
932 \\ LDP x3, x4, [x5], #0
933 \\ LDP x6, x7, [sp], #504
934 \\ LDP x0, x1, [x2, #-0x200]!
935 \\ LDP x3, x4, [x5, #0]!
936 \\ LDP x6, x7, [sp, #0x1f8]!
937 \\ LDP x0, x1, [x2, #-512]
938 \\ LDP x3, x4, [x5]
939 \\ LDP x6, x7, [x8, #0]
940 \\ LDP x9, x10, [sp, #504]
941 \\
942 \\ LDR w0, [x1], #-256
943 \\ LDR w2, [x3], #0
944 \\ LDR w4, [sp], #255
945 \\ LDR w0, [x1, #-0x100]!
946 \\ LDR w2, [x3, #0]!
947 \\ LDR w4, [sp, #0xff]!
948 \\ LDR w0, [x1, #0]
949 \\ LDR w2, [x3]
950 \\ LDR w4, [sp, #16380]
951 \\
952 \\ LDR x0, [x1], #-256
953 \\ LDR x2, [x3], #0
954 \\ LDR x4, [sp], #255
955 \\ LDR x0, [x1, #-0x100]!
956 \\ LDR x2, [x3, #0]!
957 \\ LDR x4, [sp, #0xff]!
958 \\ LDR x0, [x1, #0]
959 \\ LDR x2, [x3]
960 \\ LDR x4, [sp, #32760]
961 \\
962 \\ STP w0, w1, [x2], #-256
963 \\ STP w3, w4, [x5], #0
964 \\ STP w6, w7, [sp], #252
965 \\ STP w0, w1, [x2, #-0x100]!
966 \\ STP w3, w4, [x5, #0]!
967 \\ STP w6, w7, [sp, #0xfc]!
968 \\ STP w0, w1, [x2, #-256]
969 \\ STP w3, w4, [x5]
970 \\ STP w6, w7, [x8, #0]
971 \\ STP w9, w10, [sp, #252]
972 \\
973 \\ STP x0, x1, [x2], #-512
974 \\ STP x3, x4, [x5], #0
975 \\ STP x6, x7, [sp], #504
976 \\ STP x0, x1, [x2, #-0x200]!
977 \\ STP x3, x4, [x5, #0]!
978 \\ STP x6, x7, [sp, #0x1f8]!
979 \\ STP x0, x1, [x2, #-512]
980 \\ STP x3, x4, [x5]
981 \\ STP x6, x7, [x8, #0]
982 \\ STP x9, x10, [sp, #504]
983 \\
984 \\ STR w0, [x1], #-256
985 \\ STR w2, [x3], #0
986 \\ STR w4, [sp], #255
987 \\ STR w0, [x1, #-0x100]!
988 \\ STR w2, [x3, #0]!
989 \\ STR w4, [sp, #0xff]!
990 \\ STR w0, [x1, #0]
991 \\ STR w2, [x3]
992 \\ STR w4, [sp, #16380]
993 \\
994 \\ STR x0, [x1], #-256
995 \\ STR x2, [x3], #0
996 \\ STR x4, [sp], #255
997 \\ STR x0, [x1, #-0x100]!
998 \\ STR x2, [x3, #0]!
999 \\ STR x4, [sp, #0xff]!
1000 \\ STR x0, [x1, #0]
1001 \\ STR x2, [x3]
1002 \\ STR x4, [sp, #32760]
1003 ,
1004 .operands = .empty,
1005 };
1006
1007 try std.testing.expectFmt("ldp w0, w1, [x2], #-0x100", "{f}", .{(try as.nextInstruction()).?});
1008 try std.testing.expectFmt("ldp w3, w4, [x5], #0x0", "{f}", .{(try as.nextInstruction()).?});
1009 try std.testing.expectFmt("ldp w6, w7, [sp], #0xfc", "{f}", .{(try as.nextInstruction()).?});
1010 try std.testing.expectFmt("ldp w0, w1, [x2, #-0x100]!", "{f}", .{(try as.nextInstruction()).?});
1011 try std.testing.expectFmt("ldp w3, w4, [x5, #0x0]!", "{f}", .{(try as.nextInstruction()).?});
1012 try std.testing.expectFmt("ldp w6, w7, [sp, #0xfc]!", "{f}", .{(try as.nextInstruction()).?});
1013 try std.testing.expectFmt("ldp w0, w1, [x2, #-0x100]", "{f}", .{(try as.nextInstruction()).?});
1014 try std.testing.expectFmt("ldp w3, w4, [x5]", "{f}", .{(try as.nextInstruction()).?});
1015 try std.testing.expectFmt("ldp w6, w7, [x8]", "{f}", .{(try as.nextInstruction()).?});
1016 try std.testing.expectFmt("ldp w9, w10, [sp, #0xfc]", "{f}", .{(try as.nextInstruction()).?});
1017
1018 try std.testing.expectFmt("ldp x0, x1, [x2], #-0x200", "{f}", .{(try as.nextInstruction()).?});
1019 try std.testing.expectFmt("ldp x3, x4, [x5], #0x0", "{f}", .{(try as.nextInstruction()).?});
1020 try std.testing.expectFmt("ldp x6, x7, [sp], #0x1f8", "{f}", .{(try as.nextInstruction()).?});
1021 try std.testing.expectFmt("ldp x0, x1, [x2, #-0x200]!", "{f}", .{(try as.nextInstruction()).?});
1022 try std.testing.expectFmt("ldp x3, x4, [x5, #0x0]!", "{f}", .{(try as.nextInstruction()).?});
1023 try std.testing.expectFmt("ldp x6, x7, [sp, #0x1f8]!", "{f}", .{(try as.nextInstruction()).?});
1024 try std.testing.expectFmt("ldp x0, x1, [x2, #-0x200]", "{f}", .{(try as.nextInstruction()).?});
1025 try std.testing.expectFmt("ldp x3, x4, [x5]", "{f}", .{(try as.nextInstruction()).?});
1026 try std.testing.expectFmt("ldp x6, x7, [x8]", "{f}", .{(try as.nextInstruction()).?});
1027 try std.testing.expectFmt("ldp x9, x10, [sp, #0x1f8]", "{f}", .{(try as.nextInstruction()).?});
1028
1029 try std.testing.expectFmt("ldr w0, [x1], #-0x100", "{f}", .{(try as.nextInstruction()).?});
1030 try std.testing.expectFmt("ldr w2, [x3], #0x0", "{f}", .{(try as.nextInstruction()).?});
1031 try std.testing.expectFmt("ldr w4, [sp], #0xff", "{f}", .{(try as.nextInstruction()).?});
1032 try std.testing.expectFmt("ldr w0, [x1, #-0x100]!", "{f}", .{(try as.nextInstruction()).?});
1033 try std.testing.expectFmt("ldr w2, [x3, #0x0]!", "{f}", .{(try as.nextInstruction()).?});
1034 try std.testing.expectFmt("ldr w4, [sp, #0xff]!", "{f}", .{(try as.nextInstruction()).?});
1035 try std.testing.expectFmt("ldr w0, [x1]", "{f}", .{(try as.nextInstruction()).?});
1036 try std.testing.expectFmt("ldr w2, [x3]", "{f}", .{(try as.nextInstruction()).?});
1037 try std.testing.expectFmt("ldr w4, [sp, #0x3ffc]", "{f}", .{(try as.nextInstruction()).?});
1038
1039 try std.testing.expectFmt("ldr x0, [x1], #-0x100", "{f}", .{(try as.nextInstruction()).?});
1040 try std.testing.expectFmt("ldr x2, [x3], #0x0", "{f}", .{(try as.nextInstruction()).?});
1041 try std.testing.expectFmt("ldr x4, [sp], #0xff", "{f}", .{(try as.nextInstruction()).?});
1042 try std.testing.expectFmt("ldr x0, [x1, #-0x100]!", "{f}", .{(try as.nextInstruction()).?});
1043 try std.testing.expectFmt("ldr x2, [x3, #0x0]!", "{f}", .{(try as.nextInstruction()).?});
1044 try std.testing.expectFmt("ldr x4, [sp, #0xff]!", "{f}", .{(try as.nextInstruction()).?});
1045 try std.testing.expectFmt("ldr x0, [x1]", "{f}", .{(try as.nextInstruction()).?});
1046 try std.testing.expectFmt("ldr x2, [x3]", "{f}", .{(try as.nextInstruction()).?});
1047 try std.testing.expectFmt("ldr x4, [sp, #0x7ff8]", "{f}", .{(try as.nextInstruction()).?});
1048
1049 try std.testing.expectFmt("stp w0, w1, [x2], #-0x100", "{f}", .{(try as.nextInstruction()).?});
1050 try std.testing.expectFmt("stp w3, w4, [x5], #0x0", "{f}", .{(try as.nextInstruction()).?});
1051 try std.testing.expectFmt("stp w6, w7, [sp], #0xfc", "{f}", .{(try as.nextInstruction()).?});
1052 try std.testing.expectFmt("stp w0, w1, [x2, #-0x100]!", "{f}", .{(try as.nextInstruction()).?});
1053 try std.testing.expectFmt("stp w3, w4, [x5, #0x0]!", "{f}", .{(try as.nextInstruction()).?});
1054 try std.testing.expectFmt("stp w6, w7, [sp, #0xfc]!", "{f}", .{(try as.nextInstruction()).?});
1055 try std.testing.expectFmt("stp w0, w1, [x2, #-0x100]", "{f}", .{(try as.nextInstruction()).?});
1056 try std.testing.expectFmt("stp w3, w4, [x5]", "{f}", .{(try as.nextInstruction()).?});
1057 try std.testing.expectFmt("stp w6, w7, [x8]", "{f}", .{(try as.nextInstruction()).?});
1058 try std.testing.expectFmt("stp w9, w10, [sp, #0xfc]", "{f}", .{(try as.nextInstruction()).?});
1059
1060 try std.testing.expectFmt("stp x0, x1, [x2], #-0x200", "{f}", .{(try as.nextInstruction()).?});
1061 try std.testing.expectFmt("stp x3, x4, [x5], #0x0", "{f}", .{(try as.nextInstruction()).?});
1062 try std.testing.expectFmt("stp x6, x7, [sp], #0x1f8", "{f}", .{(try as.nextInstruction()).?});
1063 try std.testing.expectFmt("stp x0, x1, [x2, #-0x200]!", "{f}", .{(try as.nextInstruction()).?});
1064 try std.testing.expectFmt("stp x3, x4, [x5, #0x0]!", "{f}", .{(try as.nextInstruction()).?});
1065 try std.testing.expectFmt("stp x6, x7, [sp, #0x1f8]!", "{f}", .{(try as.nextInstruction()).?});
1066 try std.testing.expectFmt("stp x0, x1, [x2, #-0x200]", "{f}", .{(try as.nextInstruction()).?});
1067 try std.testing.expectFmt("stp x3, x4, [x5]", "{f}", .{(try as.nextInstruction()).?});
1068 try std.testing.expectFmt("stp x6, x7, [x8]", "{f}", .{(try as.nextInstruction()).?});
1069 try std.testing.expectFmt("stp x9, x10, [sp, #0x1f8]", "{f}", .{(try as.nextInstruction()).?});
1070
1071 try std.testing.expectFmt("str w0, [x1], #-0x100", "{f}", .{(try as.nextInstruction()).?});
1072 try std.testing.expectFmt("str w2, [x3], #0x0", "{f}", .{(try as.nextInstruction()).?});
1073 try std.testing.expectFmt("str w4, [sp], #0xff", "{f}", .{(try as.nextInstruction()).?});
1074 try std.testing.expectFmt("str w0, [x1, #-0x100]!", "{f}", .{(try as.nextInstruction()).?});
1075 try std.testing.expectFmt("str w2, [x3, #0x0]!", "{f}", .{(try as.nextInstruction()).?});
1076 try std.testing.expectFmt("str w4, [sp, #0xff]!", "{f}", .{(try as.nextInstruction()).?});
1077 try std.testing.expectFmt("str w0, [x1]", "{f}", .{(try as.nextInstruction()).?});
1078 try std.testing.expectFmt("str w2, [x3]", "{f}", .{(try as.nextInstruction()).?});
1079 try std.testing.expectFmt("str w4, [sp, #0x3ffc]", "{f}", .{(try as.nextInstruction()).?});
1080
1081 try std.testing.expectFmt("str x0, [x1], #-0x100", "{f}", .{(try as.nextInstruction()).?});
1082 try std.testing.expectFmt("str x2, [x3], #0x0", "{f}", .{(try as.nextInstruction()).?});
1083 try std.testing.expectFmt("str x4, [sp], #0xff", "{f}", .{(try as.nextInstruction()).?});
1084 try std.testing.expectFmt("str x0, [x1, #-0x100]!", "{f}", .{(try as.nextInstruction()).?});
1085 try std.testing.expectFmt("str x2, [x3, #0x0]!", "{f}", .{(try as.nextInstruction()).?});
1086 try std.testing.expectFmt("str x4, [sp, #0xff]!", "{f}", .{(try as.nextInstruction()).?});
1087 try std.testing.expectFmt("str x0, [x1]", "{f}", .{(try as.nextInstruction()).?});
1088 try std.testing.expectFmt("str x2, [x3]", "{f}", .{(try as.nextInstruction()).?});
1089 try std.testing.expectFmt("str x4, [sp, #0x7ff8]", "{f}", .{(try as.nextInstruction()).?});
1090
1091 try std.testing.expect(null == try as.nextInstruction());
1092}
1093test "logical" {
1094 var as: Assemble = .{
1095 .source =
1096 \\ and w0, w0, w0
1097 \\ and w1, w1, w2, lsl #0
1098 \\ and w3, w4, w5, lsl #1
1099 \\ and w6, w6, wzr, lsl #31
1100 \\ and w7, wzr, w8, lsr #0
1101 \\ and w9, wzr, wzr, lsr #30
1102 \\ and wzr, w10, w11, lsr #31
1103 \\ and wzr, w12, wzr, asr #0x0
1104 \\ and wzr, wzr, w13, asr #0x10
1105 \\ and wzr, wzr, wzr, asr #0x1f
1106 \\ and w0, w0, wzr
1107 \\ and w1, w2, wzr, lsl #0
1108 \\ and w3, wzr, w3
1109 \\ and w4, wzr, w5, lsl #0
1110 \\ and w6, wzr, wzr
1111 \\ and w7, wzr, wzr, lsl #0
1112 \\ and wzr, w8, wzr
1113 \\ and wzr, w9, wzr, lsl #0
1114 \\ and wzr, wzr, w10
1115 \\ and wzr, wzr, w11, lsl #0
1116 \\ and wzr, wzr, wzr
1117 \\ and wzr, wzr, wzr, lsl #0
1118 \\
1119 \\ and x0, x0, x0
1120 \\ and x1, x1, x2, lsl #0
1121 \\ and x3, x4, x5, lsl #1
1122 \\ and x6, x6, xzr, lsl #63
1123 \\ and x7, xzr, x8, lsr #0
1124 \\ and x9, xzr, xzr, lsr #62
1125 \\ and xzr, x10, x11, lsr #63
1126 \\ and xzr, x12, xzr, asr #0x0
1127 \\ and xzr, xzr, x13, asr #0x1F
1128 \\ and xzr, xzr, xzr, asr #0x3f
1129 \\ and x0, x0, xzr
1130 \\ and x1, x2, xzr, lsl #0
1131 \\ and x3, xzr, x3
1132 \\ and x4, xzr, x5, lsl #0
1133 \\ and x6, xzr, xzr
1134 \\ and x7, xzr, xzr, lsl #0
1135 \\ and xzr, x8, xzr
1136 \\ and xzr, x9, xzr, lsl #0
1137 \\ and xzr, xzr, x10
1138 \\ and xzr, xzr, x11, lsl #0
1139 \\ and xzr, xzr, xzr
1140 \\ and xzr, xzr, xzr, lsl #0
1141 \\
1142 \\ orr w0, w0, w0
1143 \\ orr w1, w1, w2, lsl #0
1144 \\ orr w3, w4, w5, lsl #1
1145 \\ orr w6, w6, wzr, lsl #31
1146 \\ orr w7, wzr, w8, lsr #0
1147 \\ orr w9, wzr, wzr, lsr #30
1148 \\ orr wzr, w10, w11, lsr #31
1149 \\ orr wzr, w12, wzr, asr #0x0
1150 \\ orr wzr, wzr, w13, asr #0x10
1151 \\ orr wzr, wzr, wzr, asr #0x1f
1152 \\ orr w0, w0, wzr
1153 \\ orr w1, w2, wzr, lsl #0
1154 \\ orr w3, wzr, w3
1155 \\ orr w4, wzr, w5, lsl #0
1156 \\ orr w6, wzr, wzr
1157 \\ orr w7, wzr, wzr, lsl #0
1158 \\ orr wzr, w8, wzr
1159 \\ orr wzr, w9, wzr, lsl #0
1160 \\ orr wzr, wzr, w10
1161 \\ orr wzr, wzr, w11, lsl #0
1162 \\ orr wzr, wzr, wzr
1163 \\ orr wzr, wzr, wzr, lsl #0
1164 \\
1165 \\ orr x0, x0, x0
1166 \\ orr x1, x1, x2, lsl #0
1167 \\ orr x3, x4, x5, lsl #1
1168 \\ orr x6, x6, xzr, lsl #63
1169 \\ orr x7, xzr, x8, lsr #0
1170 \\ orr x9, xzr, xzr, lsr #62
1171 \\ orr xzr, x10, x11, lsr #63
1172 \\ orr xzr, x12, xzr, asr #0x0
1173 \\ orr xzr, xzr, x13, asr #0x1F
1174 \\ orr xzr, xzr, xzr, asr #0x3f
1175 \\ orr x0, x0, xzr
1176 \\ orr x1, x2, xzr, lsl #0
1177 \\ orr x3, xzr, x3
1178 \\ orr x4, xzr, x5, lsl #0
1179 \\ orr x6, xzr, xzr
1180 \\ orr x7, xzr, xzr, lsl #0
1181 \\ orr xzr, x8, xzr
1182 \\ orr xzr, x9, xzr, lsl #0
1183 \\ orr xzr, xzr, x10
1184 \\ orr xzr, xzr, x11, lsl #0
1185 \\ orr xzr, xzr, xzr
1186 \\ orr xzr, xzr, xzr, lsl #0
1187 \\
1188 \\ eor w0, w0, w0
1189 \\ eor w1, w1, w2, lsl #0
1190 \\ eor w3, w4, w5, lsl #1
1191 \\ eor w6, w6, wzr, lsl #31
1192 \\ eor w7, wzr, w8, lsr #0
1193 \\ eor w9, wzr, wzr, lsr #30
1194 \\ eor wzr, w10, w11, lsr #31
1195 \\ eor wzr, w12, wzr, asr #0x0
1196 \\ eor wzr, wzr, w13, asr #0x10
1197 \\ eor wzr, wzr, wzr, asr #0x1f
1198 \\ eor w0, w0, wzr
1199 \\ eor w1, w2, wzr, lsl #0
1200 \\ eor w3, wzr, w3
1201 \\ eor w4, wzr, w5, lsl #0
1202 \\ eor w6, wzr, wzr
1203 \\ eor w7, wzr, wzr, lsl #0
1204 \\ eor wzr, w8, wzr
1205 \\ eor wzr, w9, wzr, lsl #0
1206 \\ eor wzr, wzr, w10
1207 \\ eor wzr, wzr, w11, lsl #0
1208 \\ eor wzr, wzr, wzr
1209 \\ eor wzr, wzr, wzr, lsl #0
1210 \\
1211 \\ eor x0, x0, x0
1212 \\ eor x1, x1, x2, lsl #0
1213 \\ eor x3, x4, x5, lsl #1
1214 \\ eor x6, x6, xzr, lsl #63
1215 \\ eor x7, xzr, x8, lsr #0
1216 \\ eor x9, xzr, xzr, lsr #62
1217 \\ eor xzr, x10, x11, lsr #63
1218 \\ eor xzr, x12, xzr, asr #0x0
1219 \\ eor xzr, xzr, x13, asr #0x1F
1220 \\ eor xzr, xzr, xzr, asr #0x3f
1221 \\ eor x0, x0, xzr
1222 \\ eor x1, x2, xzr, lsl #0
1223 \\ eor x3, xzr, x3
1224 \\ eor x4, xzr, x5, lsl #0
1225 \\ eor x6, xzr, xzr
1226 \\ eor x7, xzr, xzr, lsl #0
1227 \\ eor xzr, x8, xzr
1228 \\ eor xzr, x9, xzr, lsl #0
1229 \\ eor xzr, xzr, x10
1230 \\ eor xzr, xzr, x11, lsl #0
1231 \\ eor xzr, xzr, xzr
1232 \\ eor xzr, xzr, xzr, lsl #0
1233 \\
1234 \\ ands w0, w0, w0
1235 \\ ands w1, w1, w2, lsl #0
1236 \\ ands w3, w4, w5, lsl #1
1237 \\ ands w6, w6, wzr, lsl #31
1238 \\ ands w7, wzr, w8, lsr #0
1239 \\ ands w9, wzr, wzr, lsr #30
1240 \\ ands wzr, w10, w11, lsr #31
1241 \\ ands wzr, w12, wzr, asr #0x0
1242 \\ ands wzr, wzr, w13, asr #0x10
1243 \\ ands wzr, wzr, wzr, asr #0x1f
1244 \\ ands w0, w0, wzr
1245 \\ ands w1, w2, wzr, lsl #0
1246 \\ ands w3, wzr, w3
1247 \\ ands w4, wzr, w5, lsl #0
1248 \\ ands w6, wzr, wzr
1249 \\ ands w7, wzr, wzr, lsl #0
1250 \\ ands wzr, w8, wzr
1251 \\ ands wzr, w9, wzr, lsl #0
1252 \\ ands wzr, wzr, w10
1253 \\ ands wzr, wzr, w11, lsl #0
1254 \\ ands wzr, wzr, wzr
1255 \\ ands wzr, wzr, wzr, lsl #0
1256 \\
1257 \\ ands x0, x0, x0
1258 \\ ands x1, x1, x2, lsl #0
1259 \\ ands x3, x4, x5, lsl #1
1260 \\ ands x6, x6, xzr, lsl #63
1261 \\ ands x7, xzr, x8, lsr #0
1262 \\ ands x9, xzr, xzr, lsr #62
1263 \\ ands xzr, x10, x11, lsr #63
1264 \\ ands xzr, x12, xzr, asr #0x0
1265 \\ ands xzr, xzr, x13, asr #0x1F
1266 \\ ands xzr, xzr, xzr, asr #0x3f
1267 \\ ands x0, x0, xzr
1268 \\ ands x1, x2, xzr, lsl #0
1269 \\ ands x3, xzr, x3
1270 \\ ands x4, xzr, x5, lsl #0
1271 \\ ands x6, xzr, xzr
1272 \\ ands x7, xzr, xzr, lsl #0
1273 \\ ands xzr, x8, xzr
1274 \\ ands xzr, x9, xzr, lsl #0
1275 \\ ands xzr, xzr, x10
1276 \\ ands xzr, xzr, x11, lsl #0
1277 \\ ands xzr, xzr, xzr
1278 \\ ands xzr, xzr, xzr, lsl #0
1279 ,
1280 .operands = .empty,
1281 };
1282
1283 try std.testing.expectFmt("and w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
1284 try std.testing.expectFmt("and w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
1285 try std.testing.expectFmt("and w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1286 try std.testing.expectFmt("and w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
1287 try std.testing.expectFmt("and w7, wzr, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1288 try std.testing.expectFmt("and w9, wzr, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
1289 try std.testing.expectFmt("and wzr, w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
1290 try std.testing.expectFmt("and wzr, w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1291 try std.testing.expectFmt("and wzr, wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
1292 try std.testing.expectFmt("and wzr, wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
1293 try std.testing.expectFmt("and w0, w0, wzr", "{f}", .{(try as.nextInstruction()).?});
1294 try std.testing.expectFmt("and w1, w2, wzr", "{f}", .{(try as.nextInstruction()).?});
1295 try std.testing.expectFmt("and w3, wzr, w3", "{f}", .{(try as.nextInstruction()).?});
1296 try std.testing.expectFmt("and w4, wzr, w5", "{f}", .{(try as.nextInstruction()).?});
1297 try std.testing.expectFmt("and w6, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1298 try std.testing.expectFmt("and w7, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1299 try std.testing.expectFmt("and wzr, w8, wzr", "{f}", .{(try as.nextInstruction()).?});
1300 try std.testing.expectFmt("and wzr, w9, wzr", "{f}", .{(try as.nextInstruction()).?});
1301 try std.testing.expectFmt("and wzr, wzr, w10", "{f}", .{(try as.nextInstruction()).?});
1302 try std.testing.expectFmt("and wzr, wzr, w11", "{f}", .{(try as.nextInstruction()).?});
1303 try std.testing.expectFmt("and wzr, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1304 try std.testing.expectFmt("and wzr, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1305
1306 try std.testing.expectFmt("and x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
1307 try std.testing.expectFmt("and x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
1308 try std.testing.expectFmt("and x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1309 try std.testing.expectFmt("and x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
1310 try std.testing.expectFmt("and x7, xzr, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1311 try std.testing.expectFmt("and x9, xzr, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
1312 try std.testing.expectFmt("and xzr, x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
1313 try std.testing.expectFmt("and xzr, x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1314 try std.testing.expectFmt("and xzr, xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
1315 try std.testing.expectFmt("and xzr, xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
1316 try std.testing.expectFmt("and x0, x0, xzr", "{f}", .{(try as.nextInstruction()).?});
1317 try std.testing.expectFmt("and x1, x2, xzr", "{f}", .{(try as.nextInstruction()).?});
1318 try std.testing.expectFmt("and x3, xzr, x3", "{f}", .{(try as.nextInstruction()).?});
1319 try std.testing.expectFmt("and x4, xzr, x5", "{f}", .{(try as.nextInstruction()).?});
1320 try std.testing.expectFmt("and x6, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1321 try std.testing.expectFmt("and x7, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1322 try std.testing.expectFmt("and xzr, x8, xzr", "{f}", .{(try as.nextInstruction()).?});
1323 try std.testing.expectFmt("and xzr, x9, xzr", "{f}", .{(try as.nextInstruction()).?});
1324 try std.testing.expectFmt("and xzr, xzr, x10", "{f}", .{(try as.nextInstruction()).?});
1325 try std.testing.expectFmt("and xzr, xzr, x11", "{f}", .{(try as.nextInstruction()).?});
1326 try std.testing.expectFmt("and xzr, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1327 try std.testing.expectFmt("and xzr, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1328
1329 try std.testing.expectFmt("orr w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
1330 try std.testing.expectFmt("orr w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
1331 try std.testing.expectFmt("orr w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1332 try std.testing.expectFmt("orr w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
1333 try std.testing.expectFmt("orr w7, wzr, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1334 try std.testing.expectFmt("orr w9, wzr, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
1335 try std.testing.expectFmt("orr wzr, w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
1336 try std.testing.expectFmt("orr wzr, w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1337 try std.testing.expectFmt("orr wzr, wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
1338 try std.testing.expectFmt("orr wzr, wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
1339 try std.testing.expectFmt("orr w0, w0, wzr", "{f}", .{(try as.nextInstruction()).?});
1340 try std.testing.expectFmt("orr w1, w2, wzr", "{f}", .{(try as.nextInstruction()).?});
1341 try std.testing.expectFmt("mov w3, w3", "{f}", .{(try as.nextInstruction()).?});
1342 try std.testing.expectFmt("mov w4, w5", "{f}", .{(try as.nextInstruction()).?});
1343 try std.testing.expectFmt("mov w6, wzr", "{f}", .{(try as.nextInstruction()).?});
1344 try std.testing.expectFmt("mov w7, wzr", "{f}", .{(try as.nextInstruction()).?});
1345 try std.testing.expectFmt("orr wzr, w8, wzr", "{f}", .{(try as.nextInstruction()).?});
1346 try std.testing.expectFmt("orr wzr, w9, wzr", "{f}", .{(try as.nextInstruction()).?});
1347 try std.testing.expectFmt("mov wzr, w10", "{f}", .{(try as.nextInstruction()).?});
1348 try std.testing.expectFmt("mov wzr, w11", "{f}", .{(try as.nextInstruction()).?});
1349 try std.testing.expectFmt("mov wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1350 try std.testing.expectFmt("mov wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1351
1352 try std.testing.expectFmt("orr x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
1353 try std.testing.expectFmt("orr x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
1354 try std.testing.expectFmt("orr x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1355 try std.testing.expectFmt("orr x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
1356 try std.testing.expectFmt("orr x7, xzr, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1357 try std.testing.expectFmt("orr x9, xzr, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
1358 try std.testing.expectFmt("orr xzr, x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
1359 try std.testing.expectFmt("orr xzr, x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1360 try std.testing.expectFmt("orr xzr, xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
1361 try std.testing.expectFmt("orr xzr, xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
1362 try std.testing.expectFmt("orr x0, x0, xzr", "{f}", .{(try as.nextInstruction()).?});
1363 try std.testing.expectFmt("orr x1, x2, xzr", "{f}", .{(try as.nextInstruction()).?});
1364 try std.testing.expectFmt("mov x3, x3", "{f}", .{(try as.nextInstruction()).?});
1365 try std.testing.expectFmt("mov x4, x5", "{f}", .{(try as.nextInstruction()).?});
1366 try std.testing.expectFmt("mov x6, xzr", "{f}", .{(try as.nextInstruction()).?});
1367 try std.testing.expectFmt("mov x7, xzr", "{f}", .{(try as.nextInstruction()).?});
1368 try std.testing.expectFmt("orr xzr, x8, xzr", "{f}", .{(try as.nextInstruction()).?});
1369 try std.testing.expectFmt("orr xzr, x9, xzr", "{f}", .{(try as.nextInstruction()).?});
1370 try std.testing.expectFmt("mov xzr, x10", "{f}", .{(try as.nextInstruction()).?});
1371 try std.testing.expectFmt("mov xzr, x11", "{f}", .{(try as.nextInstruction()).?});
1372 try std.testing.expectFmt("mov xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1373 try std.testing.expectFmt("mov xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1374
1375 try std.testing.expectFmt("eor w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
1376 try std.testing.expectFmt("eor w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
1377 try std.testing.expectFmt("eor w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1378 try std.testing.expectFmt("eor w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
1379 try std.testing.expectFmt("eor w7, wzr, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1380 try std.testing.expectFmt("eor w9, wzr, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
1381 try std.testing.expectFmt("eor wzr, w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
1382 try std.testing.expectFmt("eor wzr, w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1383 try std.testing.expectFmt("eor wzr, wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
1384 try std.testing.expectFmt("eor wzr, wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
1385 try std.testing.expectFmt("eor w0, w0, wzr", "{f}", .{(try as.nextInstruction()).?});
1386 try std.testing.expectFmt("eor w1, w2, wzr", "{f}", .{(try as.nextInstruction()).?});
1387 try std.testing.expectFmt("eor w3, wzr, w3", "{f}", .{(try as.nextInstruction()).?});
1388 try std.testing.expectFmt("eor w4, wzr, w5", "{f}", .{(try as.nextInstruction()).?});
1389 try std.testing.expectFmt("eor w6, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1390 try std.testing.expectFmt("eor w7, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1391 try std.testing.expectFmt("eor wzr, w8, wzr", "{f}", .{(try as.nextInstruction()).?});
1392 try std.testing.expectFmt("eor wzr, w9, wzr", "{f}", .{(try as.nextInstruction()).?});
1393 try std.testing.expectFmt("eor wzr, wzr, w10", "{f}", .{(try as.nextInstruction()).?});
1394 try std.testing.expectFmt("eor wzr, wzr, w11", "{f}", .{(try as.nextInstruction()).?});
1395 try std.testing.expectFmt("eor wzr, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1396 try std.testing.expectFmt("eor wzr, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1397
1398 try std.testing.expectFmt("eor x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
1399 try std.testing.expectFmt("eor x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
1400 try std.testing.expectFmt("eor x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1401 try std.testing.expectFmt("eor x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
1402 try std.testing.expectFmt("eor x7, xzr, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1403 try std.testing.expectFmt("eor x9, xzr, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
1404 try std.testing.expectFmt("eor xzr, x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
1405 try std.testing.expectFmt("eor xzr, x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1406 try std.testing.expectFmt("eor xzr, xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
1407 try std.testing.expectFmt("eor xzr, xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
1408 try std.testing.expectFmt("eor x0, x0, xzr", "{f}", .{(try as.nextInstruction()).?});
1409 try std.testing.expectFmt("eor x1, x2, xzr", "{f}", .{(try as.nextInstruction()).?});
1410 try std.testing.expectFmt("eor x3, xzr, x3", "{f}", .{(try as.nextInstruction()).?});
1411 try std.testing.expectFmt("eor x4, xzr, x5", "{f}", .{(try as.nextInstruction()).?});
1412 try std.testing.expectFmt("eor x6, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1413 try std.testing.expectFmt("eor x7, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1414 try std.testing.expectFmt("eor xzr, x8, xzr", "{f}", .{(try as.nextInstruction()).?});
1415 try std.testing.expectFmt("eor xzr, x9, xzr", "{f}", .{(try as.nextInstruction()).?});
1416 try std.testing.expectFmt("eor xzr, xzr, x10", "{f}", .{(try as.nextInstruction()).?});
1417 try std.testing.expectFmt("eor xzr, xzr, x11", "{f}", .{(try as.nextInstruction()).?});
1418 try std.testing.expectFmt("eor xzr, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1419 try std.testing.expectFmt("eor xzr, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1420
1421 try std.testing.expectFmt("ands w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
1422 try std.testing.expectFmt("ands w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
1423 try std.testing.expectFmt("ands w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1424 try std.testing.expectFmt("ands w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
1425 try std.testing.expectFmt("ands w7, wzr, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1426 try std.testing.expectFmt("ands w9, wzr, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
1427 try std.testing.expectFmt("tst w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
1428 try std.testing.expectFmt("tst w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1429 try std.testing.expectFmt("tst wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
1430 try std.testing.expectFmt("tst wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
1431 try std.testing.expectFmt("ands w0, w0, wzr", "{f}", .{(try as.nextInstruction()).?});
1432 try std.testing.expectFmt("ands w1, w2, wzr", "{f}", .{(try as.nextInstruction()).?});
1433 try std.testing.expectFmt("ands w3, wzr, w3", "{f}", .{(try as.nextInstruction()).?});
1434 try std.testing.expectFmt("ands w4, wzr, w5", "{f}", .{(try as.nextInstruction()).?});
1435 try std.testing.expectFmt("ands w6, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1436 try std.testing.expectFmt("ands w7, wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1437 try std.testing.expectFmt("tst w8, wzr", "{f}", .{(try as.nextInstruction()).?});
1438 try std.testing.expectFmt("tst w9, wzr", "{f}", .{(try as.nextInstruction()).?});
1439 try std.testing.expectFmt("tst wzr, w10", "{f}", .{(try as.nextInstruction()).?});
1440 try std.testing.expectFmt("tst wzr, w11", "{f}", .{(try as.nextInstruction()).?});
1441 try std.testing.expectFmt("tst wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1442 try std.testing.expectFmt("tst wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1443
1444 try std.testing.expectFmt("ands x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
1445 try std.testing.expectFmt("ands x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
1446 try std.testing.expectFmt("ands x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
1447 try std.testing.expectFmt("ands x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
1448 try std.testing.expectFmt("ands x7, xzr, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
1449 try std.testing.expectFmt("ands x9, xzr, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
1450 try std.testing.expectFmt("tst x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
1451 try std.testing.expectFmt("tst x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
1452 try std.testing.expectFmt("tst xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
1453 try std.testing.expectFmt("tst xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
1454 try std.testing.expectFmt("ands x0, x0, xzr", "{f}", .{(try as.nextInstruction()).?});
1455 try std.testing.expectFmt("ands x1, x2, xzr", "{f}", .{(try as.nextInstruction()).?});
1456 try std.testing.expectFmt("ands x3, xzr, x3", "{f}", .{(try as.nextInstruction()).?});
1457 try std.testing.expectFmt("ands x4, xzr, x5", "{f}", .{(try as.nextInstruction()).?});
1458 try std.testing.expectFmt("ands x6, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1459 try std.testing.expectFmt("ands x7, xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1460 try std.testing.expectFmt("tst x8, xzr", "{f}", .{(try as.nextInstruction()).?});
1461 try std.testing.expectFmt("tst x9, xzr", "{f}", .{(try as.nextInstruction()).?});
1462 try std.testing.expectFmt("tst xzr, x10", "{f}", .{(try as.nextInstruction()).?});
1463 try std.testing.expectFmt("tst xzr, x11", "{f}", .{(try as.nextInstruction()).?});
1464 try std.testing.expectFmt("tst xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1465 try std.testing.expectFmt("tst xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1466
1467 try std.testing.expect(null == try as.nextInstruction());
1468}
1469test "mov" {
1470 var as: Assemble = .{
1471 .source =
1472 \\MOV W0, #0
1473 \\MOV WZR, #0xffff
1474 \\
1475 \\MOV X0, #0
1476 \\MOV XZR, #0xffff
1477 \\
1478 \\MOV W0, WSP
1479 \\MOV WSP, W1
1480 \\MOV WSP, WSP
1481 \\MOV X0, SP
1482 \\MOV SP, X1
1483 \\MOV SP, SP
1484 \\
1485 \\MOV W0, W0
1486 \\MOV W1, W2
1487 \\MOV W3, WZR
1488 \\MOV WZR, W4
1489 \\MOV WZR, WZR
1490 \\MOV X0, X0
1491 \\MOV X1, X2
1492 \\MOV X3, XZR
1493 \\MOV XZR, X4
1494 \\MOV XZR, XZR
1495 \\
1496 \\MOVK W0, #0
1497 \\MOVK W1, #1, lsl #0
1498 \\MOVK W2, #2, lsl #16
1499 \\MOVK X3, #3
1500 \\MOVK X4, #4, lsl #0x00
1501 \\MOVK X5, #5, lsl #0x10
1502 \\MOVK X6, #6, lsl #0x20
1503 \\MOVK X7, #7, lsl #0x30
1504 \\
1505 \\MOVN W0, #8
1506 \\MOVN W1, #9, lsl #0
1507 \\MOVN W2, #10, lsl #16
1508 \\MOVN X3, #11
1509 \\MOVN X4, #12, lsl #0x00
1510 \\MOVN X5, #13, lsl #0x10
1511 \\MOVN X6, #14, lsl #0x20
1512 \\MOVN X7, #15, lsl #0x30
1513 \\
1514 \\MOVN WZR, #0, lsl #0
1515 \\MOVN WZR, #0, lsl #16
1516 \\MOVN XZR, #0, lsl #0
1517 \\MOVN XZR, #0, lsl #16
1518 \\MOVN XZR, #0, lsl #32
1519 \\MOVN XZR, #0, lsl #48
1520 \\
1521 \\MOVN WZR, #0xffff, lsl #0
1522 \\MOVN WZR, #0xffff, lsl #16
1523 \\MOVN XZR, #0xffff, lsl #0
1524 \\MOVN XZR, #0xffff, lsl #16
1525 \\MOVN XZR, #0xffff, lsl #32
1526 \\MOVN XZR, #0xffff, lsl #48
1527 \\
1528 \\MOVZ W0, #16
1529 \\MOVZ W1, #17, lsl #0
1530 \\MOVZ W2, #18, lsl #16
1531 \\MOVZ X3, #19
1532 \\MOVZ X4, #20, lsl #0x00
1533 \\MOVZ X5, #21, lsl #0x10
1534 \\MOVZ X6, #22, lsl #0x20
1535 \\MOVZ X7, #23, lsl #0x30
1536 \\
1537 \\MOVZ WZR, #0, lsl #0
1538 \\MOVZ WZR, #0, lsl #16
1539 \\MOVZ XZR, #0, lsl #0
1540 \\MOVZ XZR, #0, lsl #16
1541 \\MOVZ XZR, #0, lsl #32
1542 \\MOVZ XZR, #0, lsl #48
1543 \\
1544 \\MOVZ WZR, #0xffff, lsl #0
1545 \\MOVZ WZR, #0xffff, lsl #16
1546 \\MOVZ XZR, #0xffff, lsl #0
1547 \\MOVZ XZR, #0xffff, lsl #16
1548 \\MOVZ XZR, #0xffff, lsl #32
1549 \\MOVZ XZR, #0xffff, lsl #48
1550 ,
1551 .operands = .empty,
1552 };
1553
1554 try std.testing.expectFmt("mov w0, #0x0", "{f}", .{(try as.nextInstruction()).?});
1555 try std.testing.expectFmt("mov wzr, #0xffff", "{f}", .{(try as.nextInstruction()).?});
1556 try std.testing.expectFmt("mov x0, #0x0", "{f}", .{(try as.nextInstruction()).?});
1557 try std.testing.expectFmt("mov xzr, #0xffff", "{f}", .{(try as.nextInstruction()).?});
1558
1559 try std.testing.expectFmt("mov w0, wsp", "{f}", .{(try as.nextInstruction()).?});
1560 try std.testing.expectFmt("mov wsp, w1", "{f}", .{(try as.nextInstruction()).?});
1561 try std.testing.expectFmt("mov wsp, wsp", "{f}", .{(try as.nextInstruction()).?});
1562 try std.testing.expectFmt("mov x0, sp", "{f}", .{(try as.nextInstruction()).?});
1563 try std.testing.expectFmt("mov sp, x1", "{f}", .{(try as.nextInstruction()).?});
1564 try std.testing.expectFmt("mov sp, sp", "{f}", .{(try as.nextInstruction()).?});
1565
1566 try std.testing.expectFmt("mov w0, w0", "{f}", .{(try as.nextInstruction()).?});
1567 try std.testing.expectFmt("mov w1, w2", "{f}", .{(try as.nextInstruction()).?});
1568 try std.testing.expectFmt("mov w3, wzr", "{f}", .{(try as.nextInstruction()).?});
1569 try std.testing.expectFmt("mov wzr, w4", "{f}", .{(try as.nextInstruction()).?});
1570 try std.testing.expectFmt("mov wzr, wzr", "{f}", .{(try as.nextInstruction()).?});
1571 try std.testing.expectFmt("mov x0, x0", "{f}", .{(try as.nextInstruction()).?});
1572 try std.testing.expectFmt("mov x1, x2", "{f}", .{(try as.nextInstruction()).?});
1573 try std.testing.expectFmt("mov x3, xzr", "{f}", .{(try as.nextInstruction()).?});
1574 try std.testing.expectFmt("mov xzr, x4", "{f}", .{(try as.nextInstruction()).?});
1575 try std.testing.expectFmt("mov xzr, xzr", "{f}", .{(try as.nextInstruction()).?});
1576
1577 try std.testing.expectFmt("movk w0, #0x0", "{f}", .{(try as.nextInstruction()).?});
1578 try std.testing.expectFmt("movk w1, #0x1", "{f}", .{(try as.nextInstruction()).?});
1579 try std.testing.expectFmt("movk w2, #0x2, lsl #16", "{f}", .{(try as.nextInstruction()).?});
1580 try std.testing.expectFmt("movk x3, #0x3", "{f}", .{(try as.nextInstruction()).?});
1581 try std.testing.expectFmt("movk x4, #0x4", "{f}", .{(try as.nextInstruction()).?});
1582 try std.testing.expectFmt("movk x5, #0x5, lsl #16", "{f}", .{(try as.nextInstruction()).?});
1583 try std.testing.expectFmt("movk x6, #0x6, lsl #32", "{f}", .{(try as.nextInstruction()).?});
1584 try std.testing.expectFmt("movk x7, #0x7, lsl #48", "{f}", .{(try as.nextInstruction()).?});
1585
1586 try std.testing.expectFmt("mov w0, #-0x9", "{f}", .{(try as.nextInstruction()).?});
1587 try std.testing.expectFmt("mov w1, #-0xa", "{f}", .{(try as.nextInstruction()).?});
1588 try std.testing.expectFmt("mov w2, #-0xa0001", "{f}", .{(try as.nextInstruction()).?});
1589 try std.testing.expectFmt("mov x3, #-0xc", "{f}", .{(try as.nextInstruction()).?});
1590 try std.testing.expectFmt("mov x4, #-0xd", "{f}", .{(try as.nextInstruction()).?});
1591 try std.testing.expectFmt("mov x5, #-0xd0001", "{f}", .{(try as.nextInstruction()).?});
1592 try std.testing.expectFmt("mov x6, #-0xe00000001", "{f}", .{(try as.nextInstruction()).?});
1593 try std.testing.expectFmt("mov x7, #-0xf000000000001", "{f}", .{(try as.nextInstruction()).?});
1594
1595 try std.testing.expectFmt("mov wzr, #-0x1", "{f}", .{(try as.nextInstruction()).?});
1596 try std.testing.expectFmt("movn wzr, #0x0, lsl #16", "{f}", .{(try as.nextInstruction()).?});
1597 try std.testing.expectFmt("mov xzr, #-0x1", "{f}", .{(try as.nextInstruction()).?});
1598 try std.testing.expectFmt("movn xzr, #0x0, lsl #16", "{f}", .{(try as.nextInstruction()).?});
1599 try std.testing.expectFmt("movn xzr, #0x0, lsl #32", "{f}", .{(try as.nextInstruction()).?});
1600 try std.testing.expectFmt("movn xzr, #0x0, lsl #48", "{f}", .{(try as.nextInstruction()).?});
1601
1602 try std.testing.expectFmt("movn wzr, #0xffff", "{f}", .{(try as.nextInstruction()).?});
1603 try std.testing.expectFmt("movn wzr, #0xffff, lsl #16", "{f}", .{(try as.nextInstruction()).?});
1604 try std.testing.expectFmt("mov xzr, #-0x10000", "{f}", .{(try as.nextInstruction()).?});
1605 try std.testing.expectFmt("mov xzr, #-0xffff0001", "{f}", .{(try as.nextInstruction()).?});
1606 try std.testing.expectFmt("mov xzr, #-0xffff00000001", "{f}", .{(try as.nextInstruction()).?});
1607 try std.testing.expectFmt("mov xzr, #0xffffffffffff", "{f}", .{(try as.nextInstruction()).?});
1608
1609 try std.testing.expectFmt("mov w0, #0x10", "{f}", .{(try as.nextInstruction()).?});
1610 try std.testing.expectFmt("mov w1, #0x11", "{f}", .{(try as.nextInstruction()).?});
1611 try std.testing.expectFmt("mov w2, #0x120000", "{f}", .{(try as.nextInstruction()).?});
1612 try std.testing.expectFmt("mov x3, #0x13", "{f}", .{(try as.nextInstruction()).?});
1613 try std.testing.expectFmt("mov x4, #0x14", "{f}", .{(try as.nextInstruction()).?});
1614 try std.testing.expectFmt("mov x5, #0x150000", "{f}", .{(try as.nextInstruction()).?});
1615 try std.testing.expectFmt("mov x6, #0x1600000000", "{f}", .{(try as.nextInstruction()).?});
1616 try std.testing.expectFmt("mov x7, #0x17000000000000", "{f}", .{(try as.nextInstruction()).?});
1617
1618 try std.testing.expectFmt("mov wzr, #0x0", "{f}", .{(try as.nextInstruction()).?});
1619 try std.testing.expectFmt("movz wzr, #0x0, lsl #16", "{f}", .{(try as.nextInstruction()).?});
1620 try std.testing.expectFmt("mov xzr, #0x0", "{f}", .{(try as.nextInstruction()).?});
1621 try std.testing.expectFmt("movz xzr, #0x0, lsl #16", "{f}", .{(try as.nextInstruction()).?});
1622 try std.testing.expectFmt("movz xzr, #0x0, lsl #32", "{f}", .{(try as.nextInstruction()).?});
1623 try std.testing.expectFmt("movz xzr, #0x0, lsl #48", "{f}", .{(try as.nextInstruction()).?});
1624
1625 try std.testing.expectFmt("mov wzr, #0xffff", "{f}", .{(try as.nextInstruction()).?});
1626 try std.testing.expectFmt("mov wzr, #-0x10000", "{f}", .{(try as.nextInstruction()).?});
1627 try std.testing.expectFmt("mov xzr, #0xffff", "{f}", .{(try as.nextInstruction()).?});
1628 try std.testing.expectFmt("mov xzr, #0xffff0000", "{f}", .{(try as.nextInstruction()).?});
1629 try std.testing.expectFmt("mov xzr, #0xffff00000000", "{f}", .{(try as.nextInstruction()).?});
1630 try std.testing.expectFmt("mov xzr, #-0x1000000000000", "{f}", .{(try as.nextInstruction()).?});
1631
1632 try std.testing.expect(null == try as.nextInstruction());
1633}
1634test "reserved" {
1635 var as: Assemble = .{
1636 .source = "\n\nudf #0x0\n\t\n\tudf\t#01234\n \nudf#65535",
1637 .operands = .empty,
1638 };
1639
1640 try std.testing.expectFmt("udf #0x0", "{f}", .{(try as.nextInstruction()).?});
1641 try std.testing.expectFmt("udf #0x4d2", "{f}", .{(try as.nextInstruction()).?});
1642 try std.testing.expectFmt("udf #0xffff", "{f}", .{(try as.nextInstruction()).?});
1643
1644 try std.testing.expect(null == try as.nextInstruction());
1645}
1646
1647const aarch64 = @import("../aarch64.zig");
1648const Assemble = @This();
1649const assert = std.debug.assert;
1650const Instruction = aarch64.encoding.Instruction;
1651const instructions = @import("instructions.zon");
1652const std = @import("std");
1653const log = std.log.scoped(.@"asm");
src/codegen/aarch64/Disassemble.zig created+905
...@@ -0,0 +1,905 @@
1case: Case = .lower,
2mnemonic_operands_separator: []const u8 = " ",
3operands_separator: []const u8 = ", ",
4enable_aliases: bool = true,
5
6pub const Case = enum { lower, upper };
7
8pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Writer) std.Io.Writer.Error!void {
9 unallocated: switch (inst.decode()) {
10 .unallocated => break :unallocated,
11 .reserved => |reserved| switch (reserved.decode()) {
12 .unallocated => break :unallocated,
13 .udf => |udf| return writer.print("{f}{s}#0x{x}", .{
14 fmtCase(.udf, dis.case),
15 dis.mnemonic_operands_separator,
16 udf.imm16,
17 }),
18 },
19 .sme => {},
20 .sve => {},
21 .data_processing_immediate => |data_processing_immediate| switch (data_processing_immediate.decode()) {
22 .unallocated => break :unallocated,
23 .pc_relative_addressing => |pc_relative_addressing| {
24 const group = pc_relative_addressing.group;
25 const imm = (@as(i33, group.immhi) << 2 | @as(i33, group.immlo) << 0) + @as(i33, switch (group.op) {
26 .adr => Instruction.size,
27 .adrp => 0,
28 });
29 return writer.print("{f}{s}{f}{s}.{c}0x{x}", .{
30 fmtCase(group.op, dis.case),
31 dis.mnemonic_operands_separator,
32 group.Rd.decodeInteger(.doubleword, .{}).fmtCase(dis.case),
33 dis.operands_separator,
34 @as(u8, if (imm < 0) '-' else '+'),
35 switch (group.op) {
36 .adr => @abs(imm),
37 .adrp => @abs(imm) << 12,
38 },
39 });
40 },
41 .add_subtract_immediate => |add_subtract_immediate| {
42 const group = add_subtract_immediate.group;
43 const op = group.op;
44 const S = group.S;
45 const sf = group.sf;
46 const sh = group.sh;
47 const imm12 = group.imm12;
48 const Rn = group.Rn.decodeInteger(sf, .{ .sp = true });
49 const Rd = group.Rd.decodeInteger(sf, .{ .sp = !S });
50 const elide_shift = sh == .@"0";
51 if (dis.enable_aliases and op == .add and S == false and elide_shift and imm12 == 0 and
52 (Rn.alias == .sp or Rd.alias == .sp)) try writer.print("{f}{s}{f}{s}{f}", .{
53 fmtCase(.mov, dis.case),
54 dis.mnemonic_operands_separator,
55 Rd.fmtCase(dis.case),
56 dis.operands_separator,
57 Rn.fmtCase(dis.case),
58 }) else try writer.print("{f}{s}{s}{f}{s}{f}{s}#0x{x}", .{
59 fmtCase(op, dis.case),
60 if (S) "s" else "",
61 dis.mnemonic_operands_separator,
62 Rd.fmtCase(dis.case),
63 dis.operands_separator,
64 Rn.fmtCase(dis.case),
65 dis.operands_separator,
66 imm12,
67 });
68 return if (!elide_shift) writer.print("{s}{f} #{s}", .{
69 dis.operands_separator,
70 fmtCase(.lsl, dis.case),
71 @tagName(sh),
72 });
73 },
74 .add_subtract_immediate_with_tags => {},
75 .logical_immediate => |logical_immediate| {
76 const decoded = logical_immediate.decode();
77 if (decoded == .unallocated) break :unallocated;
78 const group = logical_immediate.group;
79 const sf = group.sf;
80 const decoded_imm = group.imm.decodeImmediate(sf);
81 const imm = switch (sf) {
82 .word => @as(i32, @bitCast(@as(u32, @intCast(decoded_imm)))),
83 .doubleword => @as(i64, @bitCast(decoded_imm)),
84 };
85 const Rn = group.Rn.decodeInteger(sf, .{});
86 const Rd = group.Rd.decodeInteger(sf, .{ .sp = decoded != .ands });
87 return if (dis.enable_aliases and decoded == .orr and Rn.alias == .zr and !group.imm.moveWidePreferred(sf)) writer.print("{f}{s}{f}{s}#{s}0x{x}", .{
88 fmtCase(.mov, dis.case),
89 dis.mnemonic_operands_separator,
90 Rd.fmtCase(dis.case),
91 dis.operands_separator,
92 if (imm < 0) "-" else "",
93 @abs(imm),
94 }) else if (dis.enable_aliases and decoded == .ands and Rd.alias == .zr) writer.print("{f}{s}{f}{s}#{s}0x{x}", .{
95 fmtCase(.tst, dis.case),
96 dis.mnemonic_operands_separator,
97 Rn.fmtCase(dis.case),
98 dis.operands_separator,
99 if (imm < 0) "-" else "",
100 @abs(imm),
101 }) else writer.print("{f}{s}{f}{s}{f}{s}#0x{x}", .{
102 fmtCase(decoded, dis.case),
103 dis.mnemonic_operands_separator,
104 Rd.fmtCase(dis.case),
105 dis.operands_separator,
106 Rn.fmtCase(dis.case),
107 dis.operands_separator,
108 decoded_imm,
109 });
110 },
111 .move_wide_immediate => |move_wide_immediate| {
112 const decoded = move_wide_immediate.decode();
113 if (decoded == .unallocated) break :unallocated;
114 const group = move_wide_immediate.group;
115 const sf = group.sf;
116 const hw = group.hw;
117 const imm16 = group.imm16;
118 const Rd = group.Rd.decodeInteger(sf, .{});
119 const elide_shift = hw == .@"0";
120 if (dis.enable_aliases and switch (decoded) {
121 .unallocated => unreachable,
122 .movz => elide_shift or group.imm16 != 0,
123 .movn => (elide_shift or group.imm16 != 0) and switch (sf) {
124 .word => group.imm16 != std.math.maxInt(u16),
125 .doubleword => true,
126 },
127 .movk => false,
128 }) {
129 const decoded_imm = switch (sf) {
130 .word => @as(i32, @bitCast(@as(u32, group.imm16) << @intCast(hw.int()))),
131 .doubleword => @as(i64, @bitCast(@as(u64, group.imm16) << hw.int())),
132 };
133 const imm = switch (decoded) {
134 .unallocated => unreachable,
135 .movz => decoded_imm,
136 .movn => ~decoded_imm,
137 .movk => unreachable,
138 };
139 return writer.print("{f}{s}{f}{s}#{s}0x{x}", .{
140 fmtCase(.mov, dis.case),
141 dis.mnemonic_operands_separator,
142 Rd.fmtCase(dis.case),
143 dis.operands_separator,
144 if (imm < 0) "-" else "",
145 @abs(imm),
146 });
147 }
148 try writer.print("{f}{s}{f}{s}#0x{x}", .{
149 fmtCase(decoded, dis.case),
150 dis.mnemonic_operands_separator,
151 Rd.fmtCase(dis.case),
152 dis.operands_separator,
153 imm16,
154 });
155 return if (!elide_shift) writer.print("{s}{f} #{s}", .{
156 dis.operands_separator,
157 fmtCase(.lsl, dis.case),
158 @tagName(hw),
159 });
160 },
161 .bitfield => |bitfield| {
162 const decoded = bitfield.decode();
163 if (decoded == .unallocated) break :unallocated;
164 const group = bitfield.group;
165 const sf = group.sf;
166 return writer.print("{f}{s}{f}{s}{f}{s}#{d}{s}#{d}", .{
167 fmtCase(decoded, dis.case),
168 dis.mnemonic_operands_separator,
169 group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
170 dis.operands_separator,
171 group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
172 dis.operands_separator,
173 group.imm.immr,
174 dis.operands_separator,
175 group.imm.imms,
176 });
177 },
178 .extract => |extract| {
179 const decoded = extract.decode();
180 if (decoded == .unallocated) break :unallocated;
181 const group = extract.group;
182 const sf = group.sf;
183 return writer.print("{f}{s}{f}{s}{f}{s}{f}{s}#{d}", .{
184 fmtCase(decoded, dis.case),
185 dis.mnemonic_operands_separator,
186 group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
187 dis.operands_separator,
188 group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
189 dis.operands_separator,
190 group.Rm.decodeInteger(sf, .{}).fmtCase(dis.case),
191 dis.operands_separator,
192 group.imms,
193 });
194 },
195 },
196 .branch_exception_generating_system => |branch_exception_generating_system| switch (branch_exception_generating_system.decode()) {
197 .unallocated => break :unallocated,
198 .conditional_branch_immediate => |conditional_branch_immediate| {
199 const decoded = conditional_branch_immediate.decode();
200 if (decoded == .unallocated) break :unallocated;
201 const group = conditional_branch_immediate.group;
202 const imm = @as(i21, group.imm19);
203 return writer.print("{f}.{f}{s}.{c}0x{x}", .{
204 fmtCase(decoded, dis.case),
205 fmtCase(group.cond, dis.case),
206 dis.mnemonic_operands_separator,
207 @as(u8, if (imm < 0) '-' else '+'),
208 @abs(imm) << 2,
209 });
210 },
211 .exception_generating => |exception_generating| {
212 const decoded = exception_generating.decode();
213 switch (decoded) {
214 .unallocated => break :unallocated,
215 .svc, .hvc, .smc, .brk, .hlt, .tcancel => {},
216 .dcps1, .dcps2, .dcps3 => switch (exception_generating.group.imm16) {
217 0 => return writer.print("{f}", .{fmtCase(decoded, dis.case)}),
218 else => {},
219 },
220 }
221 return switch (exception_generating.group.imm16) {
222 0 => writer.print("{f}{s}#0", .{
223 fmtCase(decoded, dis.case),
224 dis.mnemonic_operands_separator,
225 }),
226 else => writer.print("{f}{s}#0x{x}", .{
227 fmtCase(decoded, dis.case),
228 dis.mnemonic_operands_separator,
229 exception_generating.group.imm16,
230 }),
231 };
232 },
233 .system_register_argument => {},
234 .hints => |hints| switch (hints.decode()) {
235 .hint => |hint| return writer.print("{f}{s}#0x{x}", .{
236 fmtCase(.hint, dis.case),
237 dis.mnemonic_operands_separator,
238 @as(u7, hint.CRm) << 3 | @as(u7, hint.op2) << 0,
239 }),
240 else => |decoded| return writer.print("{f}", .{fmtCase(decoded, dis.case)}),
241 },
242 .barriers => {},
243 .pstate => {},
244 .system_result => {},
245 .system => {},
246 .system_register_move => {},
247 .unconditional_branch_register => |unconditional_branch_register| {
248 const decoded = unconditional_branch_register.decode();
249 if (decoded == .unallocated) break :unallocated;
250 const group = unconditional_branch_register.group;
251 const Rn = group.Rn.decodeInteger(.doubleword, .{});
252 try writer.print("{f}", .{fmtCase(decoded, dis.case)});
253 return if (decoded != .ret or Rn.alias != .r30) try writer.print("{s}{f}", .{
254 dis.mnemonic_operands_separator,
255 Rn.fmtCase(dis.case),
256 });
257 },
258 .unconditional_branch_immediate => |unconditional_branch_immediate| {
259 const group = unconditional_branch_immediate.group;
260 const imm = @as(i28, group.imm26);
261 return writer.print("{f}{s}.{c}0x{x}", .{
262 fmtCase(group.op, dis.case),
263 dis.mnemonic_operands_separator,
264 @as(u8, if (imm < 0) '-' else '+'),
265 @abs(imm) << 2,
266 });
267 },
268 .compare_branch_immediate => |compare_branch_immediate| {
269 const group = compare_branch_immediate.group;
270 const imm = @as(i21, group.imm19);
271 return writer.print("{f}{s}{f}{s}.{c}0x{x}", .{
272 fmtCase(group.op, dis.case),
273 dis.mnemonic_operands_separator,
274 group.Rt.decodeInteger(group.sf, .{}).fmtCase(dis.case),
275 dis.operands_separator,
276 @as(u8, if (imm < 0) '-' else '+'),
277 @abs(imm) << 2,
278 });
279 },
280 .test_branch_immediate => |test_branch_immediate| {
281 const group = test_branch_immediate.group;
282 const imm = @as(i16, group.imm14);
283 return writer.print("{f}{s}{f}{s}#0x{d}{s}.{c}0x{x}", .{
284 fmtCase(group.op, dis.case),
285 dis.mnemonic_operands_separator,
286 group.Rt.decodeInteger(@enumFromInt(group.b5), .{}).fmtCase(dis.case),
287 dis.operands_separator,
288 @as(u6, group.b5) << 5 |
289 @as(u6, group.b40) << 0,
290 dis.operands_separator,
291 @as(u8, if (imm < 0) '-' else '+'),
292 @abs(imm) << 2,
293 });
294 },
295 },
296 .load_store => |load_store| switch (load_store.decode()) {
297 .unallocated => break :unallocated,
298 .register_literal => {},
299 .memory => {},
300 .no_allocate_pair_offset => {},
301 .register_pair_post_indexed => |register_pair_post_indexed| switch (register_pair_post_indexed.decode()) {
302 .integer => |integer| {
303 const decoded = integer.decode();
304 if (decoded == .unallocated) break :unallocated;
305 const group = integer.group;
306 const sf: aarch64.encoding.Register.IntegerSize = @enumFromInt(group.opc >> 1);
307 return writer.print("{f}{s}{f}{s}{f}{s}[{f}]{s}#{s}0x{x}", .{
308 fmtCase(decoded, dis.case),
309 dis.mnemonic_operands_separator,
310 group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
311 dis.operands_separator,
312 group.Rt2.decodeInteger(sf, .{}).fmtCase(dis.case),
313 dis.operands_separator,
314 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
315 dis.operands_separator,
316 if (group.imm7 < 0) "-" else "",
317 @as(u10, @abs(group.imm7)) << (@as(u2, 2) + @intFromEnum(sf)),
318 });
319 },
320 .vector => |vector| {
321 const decoded = vector.decode();
322 if (decoded == .unallocated) break :unallocated;
323 const group = vector.group;
324 const vs = group.opc.decode();
325 return writer.print("{f}{s}{f}{s}{f}{s}[{f}]{s}#{s}0x{x}", .{
326 fmtCase(decoded, dis.case),
327 dis.mnemonic_operands_separator,
328 group.Rt.decodeVector(vs).fmtCase(dis.case),
329 dis.operands_separator,
330 group.Rt2.decodeVector(vs).fmtCase(dis.case),
331 dis.operands_separator,
332 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
333 dis.operands_separator,
334 if (group.imm7 < 0) "-" else "",
335 @as(u11, @abs(group.imm7)) << (@as(u3, 2) + @intFromEnum(vs)),
336 });
337 },
338 },
339 .register_pair_offset => |register_pair_offset| switch (register_pair_offset.decode()) {
340 .integer => |integer| {
341 const decoded = integer.decode();
342 if (decoded == .unallocated) break :unallocated;
343 const group = integer.group;
344 const sf: aarch64.encoding.Register.IntegerSize = @enumFromInt(group.opc >> 1);
345 try writer.print("{f}{s}{f}{s}{f}{s}[{f}", .{
346 fmtCase(decoded, dis.case),
347 dis.mnemonic_operands_separator,
348 group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
349 dis.operands_separator,
350 group.Rt2.decodeInteger(sf, .{}).fmtCase(dis.case),
351 dis.operands_separator,
352 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
353 });
354 if (group.imm7 != 0) try writer.print("{s}#{s}0x{x}", .{
355 dis.operands_separator,
356 if (group.imm7 < 0) "-" else "",
357 @as(u10, @abs(group.imm7)) << (@as(u2, 2) + @intFromEnum(sf)),
358 });
359 return writer.writeByte(']');
360 },
361 .vector => |vector| {
362 const decoded = vector.decode();
363 if (decoded == .unallocated) break :unallocated;
364 const group = vector.group;
365 const vs = group.opc.decode();
366 try writer.print("{f}{s}{f}{s}{f}{s}[{f}", .{
367 fmtCase(decoded, dis.case),
368 dis.mnemonic_operands_separator,
369 group.Rt.decodeVector(vs).fmtCase(dis.case),
370 dis.operands_separator,
371 group.Rt2.decodeVector(vs).fmtCase(dis.case),
372 dis.operands_separator,
373 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
374 });
375 if (group.imm7 != 0) try writer.print("{s}#{s}0x{x}", .{
376 dis.operands_separator,
377 if (group.imm7 < 0) "-" else "",
378 @as(u11, @abs(group.imm7)) << (@as(u3, 2) + @intFromEnum(vs)),
379 });
380 return writer.writeByte(']');
381 },
382 },
383 .register_pair_pre_indexed => |register_pair_pre_indexed| switch (register_pair_pre_indexed.decode()) {
384 .integer => |integer| {
385 const decoded = integer.decode();
386 if (decoded == .unallocated) break :unallocated;
387 const group = integer.group;
388 const sf: aarch64.encoding.Register.IntegerSize = @enumFromInt(group.opc >> 1);
389 return writer.print("{f}{s}{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
390 fmtCase(decoded, dis.case),
391 dis.mnemonic_operands_separator,
392 group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
393 dis.operands_separator,
394 group.Rt2.decodeInteger(sf, .{}).fmtCase(dis.case),
395 dis.operands_separator,
396 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
397 dis.operands_separator,
398 if (group.imm7 < 0) "-" else "",
399 @as(u10, @abs(group.imm7)) << (@as(u2, 2) + @intFromEnum(sf)),
400 });
401 },
402 .vector => |vector| {
403 const decoded = vector.decode();
404 if (decoded == .unallocated) break :unallocated;
405 const group = vector.group;
406 const vs = group.opc.decode();
407 return writer.print("{f}{s}{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
408 fmtCase(decoded, dis.case),
409 dis.mnemonic_operands_separator,
410 group.Rt.decodeVector(vs).fmtCase(dis.case),
411 dis.operands_separator,
412 group.Rt2.decodeVector(vs).fmtCase(dis.case),
413 dis.operands_separator,
414 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
415 dis.operands_separator,
416 if (group.imm7 < 0) "-" else "",
417 @as(u11, @abs(group.imm7)) << (@as(u3, 2) + @intFromEnum(vs)),
418 });
419 },
420 },
421 .register_unscaled_immediate => {},
422 .register_immediate_post_indexed => |register_immediate_post_indexed| switch (register_immediate_post_indexed.decode()) {
423 .integer => |integer| {
424 const decoded = integer.decode();
425 const sf: aarch64.encoding.Register.IntegerSize = switch (decoded) {
426 .unallocated => break :unallocated,
427 .strb, .ldrb, .strh, .ldrh => .word,
428 inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
429 0b0 => .doubleword,
430 0b1 => .word,
431 },
432 .ldrsw => .doubleword,
433 inline .str, .ldr => |encoded| encoded.sf,
434 };
435 const group = integer.group;
436 return writer.print("{f}{s}{f}{s}[{f}]{s}#{s}0x{x}", .{
437 fmtCase(decoded, dis.case),
438 dis.mnemonic_operands_separator,
439 group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
440 dis.operands_separator,
441 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
442 dis.operands_separator,
443 if (group.imm9 < 0) "-" else "",
444 @abs(group.imm9),
445 });
446 },
447 .vector => {},
448 },
449 .register_unprivileged => {},
450 .register_immediate_pre_indexed => |register_immediate_pre_indexed| switch (register_immediate_pre_indexed.decode()) {
451 .integer => |integer| {
452 const decoded = integer.decode();
453 const sf: aarch64.encoding.Register.IntegerSize = switch (decoded) {
454 .unallocated => break :unallocated,
455 inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
456 0b0 => .doubleword,
457 0b1 => .word,
458 },
459 .strb, .ldrb, .strh, .ldrh => .word,
460 .ldrsw => .doubleword,
461 inline .str, .ldr => |encoded| encoded.sf,
462 };
463 const group = integer.group;
464 return writer.print("{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
465 fmtCase(decoded, dis.case),
466 dis.mnemonic_operands_separator,
467 group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
468 dis.operands_separator,
469 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
470 dis.operands_separator,
471 if (group.imm9 < 0) "-" else "",
472 @abs(group.imm9),
473 });
474 },
475 .vector => |vector| {
476 const decoded = vector.decode();
477 if (decoded == .unallocated) break :unallocated;
478 const group = vector.group;
479 return writer.print("{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
480 fmtCase(decoded, dis.case),
481 dis.mnemonic_operands_separator,
482 group.Rt.decodeVector(group.opc1.decode(group.size)).fmtCase(dis.case),
483 dis.operands_separator,
484 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
485 dis.operands_separator,
486 if (group.imm9 < 0) "-" else "",
487 @abs(group.imm9),
488 });
489 },
490 },
491 .register_register_offset => |register_register_offset| switch (register_register_offset.decode()) {
492 .integer => |integer| {
493 const decoded = integer.decode();
494 const sf: aarch64.encoding.Register.IntegerSize = switch (decoded) {
495 .unallocated, .prfm => break :unallocated,
496 .strb, .ldrb, .strh, .ldrh => .word,
497 inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
498 0b0 => .doubleword,
499 0b1 => .word,
500 },
501 .ldrsw => .doubleword,
502 inline .str, .ldr => |encoded| encoded.sf,
503 };
504 const group = integer.group;
505 try writer.print("{f}{s}{f}{s}[{f}{s}{f}", .{
506 fmtCase(decoded, dis.case),
507 dis.mnemonic_operands_separator,
508 group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
509 dis.operands_separator,
510 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
511 dis.operands_separator,
512 group.Rm.decodeInteger(group.option.sf(), .{}).fmtCase(dis.case),
513 });
514 if (group.option != .lsl or group.S) {
515 try writer.print("{s}{f}", .{
516 dis.operands_separator,
517 fmtCase(group.option, dis.case),
518 });
519 if (group.S) try writer.print(" #{d}", .{
520 @intFromEnum(group.size),
521 });
522 }
523 return writer.writeByte(']');
524 },
525 .vector => {},
526 },
527 .register_unsigned_immediate => |register_unsigned_immediate| switch (register_unsigned_immediate.decode()) {
528 .integer => |integer| {
529 const decoded = integer.decode();
530 const sf: aarch64.encoding.Register.IntegerSize = switch (decoded) {
531 .unallocated, .prfm => break :unallocated,
532 .strb, .ldrb, .strh, .ldrh => .word,
533 inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
534 0b0 => .doubleword,
535 0b1 => .word,
536 },
537 .ldrsw => .doubleword,
538 inline .str, .ldr => |encoded| encoded.sf,
539 };
540 const group = integer.group;
541 try writer.print("{f}{s}{f}{s}[{f}", .{
542 fmtCase(decoded, dis.case),
543 dis.mnemonic_operands_separator,
544 group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
545 dis.operands_separator,
546 group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
547 });
548 if (group.imm12 > 0) try writer.print("{s}#0x{x}", .{
549 dis.operands_separator,
550 @as(u15, group.imm12) << @intFromEnum(group.size),
551 });
552 return writer.writeByte(']');
553 },
554 .vector => {},
555 },
556 },
557 .data_processing_register => |data_processing_register| switch (data_processing_register.decode()) {
558 .unallocated => break :unallocated,
559 .data_processing_two_source => |data_processing_two_source| {
560 const decoded = data_processing_two_source.decode();
561 if (decoded == .unallocated) break :unallocated;
562 const group = data_processing_two_source.group;
563 const sf = group.sf;
564 return writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
565 fmtCase(decoded, dis.case),
566 dis.mnemonic_operands_separator,
567 group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
568 dis.operands_separator,
569 group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
570 dis.operands_separator,
571 group.Rm.decodeInteger(sf, .{}).fmtCase(dis.case),
572 });
573 },
574 .data_processing_one_source => |data_processing_one_source| {
575 const decoded = data_processing_one_source.decode();
576 if (decoded == .unallocated) break :unallocated;
577 const group = data_processing_one_source.group;
578 const sf = group.sf;
579 return writer.print("{f}{s}{f}{s}{f}", .{
580 fmtCase(decoded, dis.case),
581 dis.mnemonic_operands_separator,
582 group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
583 dis.operands_separator,
584 group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
585 });
586 },
587 .logical_shifted_register => |logical_shifted_register| {
588 const decoded = logical_shifted_register.decode();
589 if (decoded == .unallocated) break :unallocated;
590 const group = logical_shifted_register.group;
591 const sf = group.sf;
592 const shift = group.shift;
593 const Rm = group.Rm.decodeInteger(sf, .{});
594 const amount = group.imm6;
595 const Rn = group.Rn.decodeInteger(sf, .{});
596 const Rd = group.Rd.decodeInteger(sf, .{});
597 const elide_shift = shift == .lsl and amount == 0;
598 if (dis.enable_aliases and switch (decoded) {
599 else => false,
600 .orr => elide_shift,
601 .orn => true,
602 } and Rn.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
603 fmtCase(@as(enum { mov, mvn }, switch (decoded) {
604 else => unreachable,
605 .orr => .mov,
606 .orn => .mvn,
607 }), dis.case),
608 dis.mnemonic_operands_separator,
609 Rd.fmtCase(dis.case),
610 dis.operands_separator,
611 Rm.fmtCase(dis.case),
612 }) else if (dis.enable_aliases and decoded == .ands and Rd.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
613 fmtCase(.tst, dis.case),
614 dis.mnemonic_operands_separator,
615 Rn.fmtCase(dis.case),
616 dis.operands_separator,
617 Rm.fmtCase(dis.case),
618 }) else try writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
619 fmtCase(decoded, dis.case),
620 dis.mnemonic_operands_separator,
621 Rd.fmtCase(dis.case),
622 dis.operands_separator,
623 Rn.fmtCase(dis.case),
624 dis.operands_separator,
625 Rm.fmtCase(dis.case),
626 });
627 return if (!elide_shift) writer.print("{s}{f} #{d}", .{
628 dis.operands_separator,
629 fmtCase(shift, dis.case),
630 amount,
631 });
632 },
633 .add_subtract_shifted_register => |add_subtract_shifted_register| {
634 const decoded = add_subtract_shifted_register.decode();
635 if (decoded == .unallocated) break :unallocated;
636 const group = add_subtract_shifted_register.group;
637 const sf = group.sf;
638 const shift = group.shift;
639 const Rm = group.Rm.decodeInteger(sf, .{});
640 const imm6 = group.imm6;
641 const Rn = group.Rn.decodeInteger(sf, .{});
642 const Rd = group.Rd.decodeInteger(sf, .{});
643 if (dis.enable_aliases and group.S and Rd.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
644 fmtCase(@as(enum { cmn, cmp }, switch (group.op) {
645 .add => .cmn,
646 .sub => .cmp,
647 }), dis.case),
648 dis.mnemonic_operands_separator,
649 Rn.fmtCase(dis.case),
650 dis.operands_separator,
651 Rm.fmtCase(dis.case),
652 }) else if (dis.enable_aliases and group.op == .sub and Rn.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
653 fmtCase(@as(enum { neg, negs }, switch (group.S) {
654 false => .neg,
655 true => .negs,
656 }), dis.case),
657 dis.mnemonic_operands_separator,
658 Rd.fmtCase(dis.case),
659 dis.operands_separator,
660 Rm.fmtCase(dis.case),
661 }) else try writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
662 fmtCase(decoded, dis.case),
663 dis.mnemonic_operands_separator,
664 Rd.fmtCase(dis.case),
665 dis.operands_separator,
666 Rn.fmtCase(dis.case),
667 dis.operands_separator,
668 Rm.fmtCase(dis.case),
669 });
670 return if (shift != .lsl or imm6 != 0) return writer.print("{s}{f} #{d}", .{
671 dis.operands_separator,
672 fmtCase(shift, dis.case),
673 imm6,
674 });
675 },
676 .add_subtract_extended_register => |add_subtract_extended_register| {
677 const decoded = add_subtract_extended_register.decode();
678 if (decoded == .unallocated) break :unallocated;
679 const group = add_subtract_extended_register.group;
680 const sf = group.sf;
681 const Rm = group.Rm.decodeInteger(group.option.sf(), .{});
682 const Rn = group.Rn.decodeInteger(sf, .{ .sp = true });
683 const Rd = group.Rd.decodeInteger(sf, .{ .sp = true });
684 if (dis.enable_aliases and group.S and Rd.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
685 fmtCase(@as(enum { cmn, cmp }, switch (group.op) {
686 .add => .cmn,
687 .sub => .cmp,
688 }), dis.case),
689 dis.mnemonic_operands_separator,
690 Rn.fmtCase(dis.case),
691 dis.operands_separator,
692 Rm.fmtCase(dis.case),
693 }) else try writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
694 fmtCase(decoded, dis.case),
695 dis.mnemonic_operands_separator,
696 Rd.fmtCase(dis.case),
697 dis.operands_separator,
698 Rn.fmtCase(dis.case),
699 dis.operands_separator,
700 Rm.fmtCase(dis.case),
701 });
702 return if (group.option != @as(Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option, switch (sf) {
703 .word => .uxtw,
704 .doubleword => .uxtx,
705 }) or group.imm3 != 0) writer.print("{s}{f} #{d}", .{
706 dis.operands_separator,
707 fmtCase(group.option, dis.case),
708 group.imm3,
709 });
710 },
711 .add_subtract_with_carry => |add_subtract_with_carry| {
712 const decoded = add_subtract_with_carry.decode();
713 const group = add_subtract_with_carry.group;
714 const sf = group.sf;
715 const Rm = group.Rm.decodeInteger(sf, .{});
716 const Rn = group.Rn.decodeInteger(sf, .{});
717 const Rd = group.Rd.decodeInteger(sf, .{});
718 return if (dis.enable_aliases and group.op == .sbc and Rn.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
719 fmtCase(@as(enum { ngc, ngcs }, switch (group.S) {
720 false => .ngc,
721 true => .ngcs,
722 }), dis.case),
723 dis.mnemonic_operands_separator,
724 Rd.fmtCase(dis.case),
725 dis.operands_separator,
726 Rm.fmtCase(dis.case),
727 }) else try writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
728 fmtCase(decoded, dis.case),
729 dis.mnemonic_operands_separator,
730 Rd.fmtCase(dis.case),
731 dis.operands_separator,
732 Rn.fmtCase(dis.case),
733 dis.operands_separator,
734 Rm.fmtCase(dis.case),
735 });
736 },
737 .rotate_right_into_flags => {},
738 .evaluate_into_flags => {},
739 .conditional_compare_register => {},
740 .conditional_compare_immediate => {},
741 .conditional_select => |conditional_select| {
742 const decoded = conditional_select.decode();
743 if (decoded == .unallocated) break :unallocated;
744 const group = conditional_select.group;
745 const sf = group.sf;
746 const Rm = group.Rm.decodeInteger(sf, .{});
747 const cond = group.cond;
748 const Rn = group.Rn.decodeInteger(sf, .{});
749 const Rd = group.Rd.decodeInteger(sf, .{});
750 return if (dis.enable_aliases and group.op != group.op2 and Rm.alias == .zr and cond != .al and cond != .nv and Rn.alias == Rm.alias) writer.print("{f}{s}{f}{s}{f}", .{
751 fmtCase(@as(enum { cset, csetm }, switch (decoded) {
752 else => unreachable,
753 .csinc => .cset,
754 .csinv => .csetm,
755 }), dis.case),
756 dis.mnemonic_operands_separator,
757 Rd.fmtCase(dis.case),
758 dis.operands_separator,
759 fmtCase(cond.invert(), dis.case),
760 }) else if (dis.enable_aliases and decoded != .csel and cond != .al and cond != .nv and Rn.alias == Rm.alias) writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
761 fmtCase(@as(enum { cinc, cinv, cneg }, switch (decoded) {
762 else => unreachable,
763 .csinc => .cinc,
764 .csinv => .cinv,
765 .csneg => .cneg,
766 }), dis.case),
767 dis.mnemonic_operands_separator,
768 Rd.fmtCase(dis.case),
769 dis.operands_separator,
770 Rn.fmtCase(dis.case),
771 dis.operands_separator,
772 fmtCase(cond.invert(), dis.case),
773 }) else writer.print("{f}{s}{f}{s}{f}{s}{f}{s}{f}", .{
774 fmtCase(decoded, dis.case),
775 dis.mnemonic_operands_separator,
776 Rd.fmtCase(dis.case),
777 dis.operands_separator,
778 Rn.fmtCase(dis.case),
779 dis.operands_separator,
780 Rm.fmtCase(dis.case),
781 dis.operands_separator,
782 fmtCase(cond, dis.case),
783 });
784 },
785 .data_processing_three_source => |data_processing_three_source| {
786 const decoded = data_processing_three_source.decode();
787 if (decoded == .unallocated) break :unallocated;
788 const group = data_processing_three_source.group;
789 const sf = group.sf;
790 try writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
791 fmtCase(decoded, dis.case),
792 dis.mnemonic_operands_separator,
793 group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
794 dis.operands_separator,
795 group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
796 dis.operands_separator,
797 group.Rm.decodeInteger(sf, .{}).fmtCase(dis.case),
798 });
799 return switch (decoded) {
800 .unallocated => unreachable,
801 .madd, .msub, .smaddl, .smsubl, .umaddl, .umsubl => writer.print("{s}{f}", .{
802 dis.operands_separator,
803 group.Ra.decodeInteger(sf, .{}).fmtCase(dis.case),
804 }),
805 .smulh, .umulh => {},
806 };
807 },
808 },
809 .data_processing_vector => {},
810 }
811 return writer.print(".{f}{s}0x{x:0>8}", .{
812 fmtCase(.word, dis.case),
813 dis.mnemonic_operands_separator,
814 @as(Instruction.Backing, @bitCast(inst)),
815 });
816}
817
818fn fmtCase(tag: anytype, case: Case) struct {
819 tag: []const u8,
820 case: Case,
821 pub fn format(data: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
822 for (data.tag) |c| try writer.writeByte(switch (data.case) {
823 .lower => std.ascii.toLower(c),
824 .upper => std.ascii.toUpper(c),
825 });
826 }
827} {
828 return .{ .tag = @tagName(tag), .case = case };
829}
830
831pub const RegisterFormatter = struct {
832 reg: aarch64.encoding.Register,
833 case: Case,
834 pub fn format(data: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
835 switch (data.reg.format) {
836 .alias => try writer.print("{f}", .{fmtCase(data.reg.alias, data.case)}),
837 .integer => |size| switch (data.reg.alias) {
838 .r0,
839 .r1,
840 .r2,
841 .r3,
842 .r4,
843 .r5,
844 .r6,
845 .r7,
846 .r8,
847 .r9,
848 .r10,
849 .r11,
850 .r12,
851 .r13,
852 .r14,
853 .r15,
854 .r16,
855 .r17,
856 .r18,
857 .r19,
858 .r20,
859 .r21,
860 .r22,
861 .r23,
862 .r24,
863 .r25,
864 .r26,
865 .r27,
866 .r28,
867 .r29,
868 .r30,
869 => |alias| try writer.print("{c}{d}", .{
870 size.prefix(),
871 @intFromEnum(alias.encode(.{})),
872 }),
873 .zr => try writer.print("{c}{f}", .{
874 size.prefix(),
875 fmtCase(data.reg.alias, data.case),
876 }),
877 else => try writer.print("{s}{f}", .{
878 switch (size) {
879 .word => "w",
880 .doubleword => "",
881 },
882 fmtCase(data.reg.alias, data.case),
883 }),
884 },
885 .scalar => |size| try writer.print("{c}{d}", .{
886 size.prefix(),
887 @intFromEnum(data.reg.alias.encode(.{ .V = true })),
888 }),
889 .vector => |arrangement| try writer.print("{f}.{f}", .{
890 fmtCase(data.reg.alias, data.case),
891 fmtCase(arrangement, data.case),
892 }),
893 .element => |element| try writer.print("{f}.{c}[{d}]", .{
894 fmtCase(data.reg.alias, data.case),
895 element.size.prefix(),
896 element.index,
897 }),
898 }
899 }
900};
901
902const aarch64 = @import("../aarch64.zig");
903const Disassemble = @This();
904const Instruction = aarch64.encoding.Instruction;
905const std = @import("std");
src/codegen/aarch64/Mir.zig created+275
...@@ -0,0 +1,275 @@
1prologue: []const Instruction,
2body: []const Instruction,
3epilogue: []const Instruction,
4literals: []const u32,
5nav_relocs: []const Reloc.Nav,
6uav_relocs: []const Reloc.Uav,
7global_relocs: []const Reloc.Global,
8literal_relocs: []const Reloc.Literal,
9
10pub const Reloc = struct {
11 label: u32,
12 addend: u64 align(@alignOf(u32)) = 0,
13
14 pub const Nav = struct {
15 nav: InternPool.Nav.Index,
16 reloc: Reloc,
17 };
18
19 pub const Uav = struct {
20 uav: InternPool.Key.Ptr.BaseAddr.Uav,
21 reloc: Reloc,
22 };
23
24 pub const Global = struct {
25 global: [*:0]const u8,
26 reloc: Reloc,
27 };
28
29 pub const Literal = struct {
30 label: u32,
31 };
32};
33
34pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
35 assert(mir.body.ptr + mir.body.len == mir.prologue.ptr);
36 assert(mir.prologue.ptr + mir.prologue.len == mir.epilogue.ptr);
37 gpa.free(mir.body.ptr[0 .. mir.body.len + mir.prologue.len + mir.epilogue.len]);
38 gpa.free(mir.literals);
39 gpa.free(mir.nav_relocs);
40 gpa.free(mir.uav_relocs);
41 gpa.free(mir.global_relocs);
42 gpa.free(mir.literal_relocs);
43 mir.* = undefined;
44}
45
46pub fn emit(
47 mir: Mir,
48 lf: *link.File,
49 pt: Zcu.PerThread,
50 src_loc: Zcu.LazySrcLoc,
51 func_index: InternPool.Index,
52 code: *std.ArrayListUnmanaged(u8),
53 debug_output: link.File.DebugInfoOutput,
54) !void {
55 _ = debug_output;
56 const zcu = pt.zcu;
57 const ip = &zcu.intern_pool;
58 const gpa = zcu.gpa;
59 const func = zcu.funcInfo(func_index);
60 const nav = ip.getNav(func.owner_nav);
61 const mod = zcu.navFileScope(func.owner_nav).mod.?;
62 const target = &mod.resolved_target.result;
63 mir_log.debug("{f}:", .{nav.fqn.fmt(ip)});
64
65 const func_align = switch (nav.status.fully_resolved.alignment) {
66 .none => switch (mod.optimize_mode) {
67 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
68 .ReleaseSmall => target_util.minFunctionAlignment(target),
69 },
70 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
71 };
72 const code_len = mir.prologue.len + mir.body.len + mir.epilogue.len;
73 const literals_align_gap = -%code_len & (@divExact(
74 @as(u5, @intCast(func_align.minStrict(.@"16").toByteUnits().?)),
75 Instruction.size,
76 ) - 1);
77 try code.ensureUnusedCapacity(gpa, Instruction.size *
78 (code_len + literals_align_gap + mir.literals.len));
79 emitInstructionsForward(code, mir.prologue);
80 emitInstructionsBackward(code, mir.body);
81 const body_end: u32 = @intCast(code.items.len);
82 emitInstructionsBackward(code, mir.epilogue);
83 code.appendNTimesAssumeCapacity(0, Instruction.size * literals_align_gap);
84 code.appendSliceAssumeCapacity(@ptrCast(mir.literals));
85 mir_log.debug("", .{});
86
87 for (mir.nav_relocs) |nav_reloc| try emitReloc(
88 lf,
89 zcu,
90 func.owner_nav,
91 switch (try @import("../../codegen.zig").genNavRef(
92 lf,
93 pt,
94 src_loc,
95 nav_reloc.nav,
96 &mod.resolved_target.result,
97 )) {
98 .sym_index => |sym_index| sym_index,
99 .fail => |em| return zcu.codegenFailMsg(func.owner_nav, em),
100 },
101 mir.body[nav_reloc.reloc.label],
102 body_end - Instruction.size * (1 + nav_reloc.reloc.label),
103 nav_reloc.reloc.addend,
104 );
105 for (mir.uav_relocs) |uav_reloc| try emitReloc(
106 lf,
107 zcu,
108 func.owner_nav,
109 switch (try lf.lowerUav(
110 pt,
111 uav_reloc.uav.val,
112 ZigType.fromInterned(uav_reloc.uav.orig_ty).ptrAlignment(zcu),
113 src_loc,
114 )) {
115 .sym_index => |sym_index| sym_index,
116 .fail => |em| return zcu.codegenFailMsg(func.owner_nav, em),
117 },
118 mir.body[uav_reloc.reloc.label],
119 body_end - Instruction.size * (1 + uav_reloc.reloc.label),
120 uav_reloc.reloc.addend,
121 );
122 for (mir.global_relocs) |global_reloc| try emitReloc(
123 lf,
124 zcu,
125 func.owner_nav,
126 if (lf.cast(.elf)) |ef|
127 try ef.getGlobalSymbol(std.mem.span(global_reloc.global), null)
128 else if (lf.cast(.macho)) |mf|
129 try mf.getGlobalSymbol(std.mem.span(global_reloc.global), null)
130 else if (lf.cast(.coff)) |cf|
131 try cf.getGlobalSymbol(std.mem.span(global_reloc.global), "compiler_rt")
132 else
133 return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
134 mir.body[global_reloc.reloc.label],
135 body_end - Instruction.size * (1 + global_reloc.reloc.label),
136 global_reloc.reloc.addend,
137 );
138 const literal_reloc_offset: i19 = @intCast(mir.epilogue.len + literals_align_gap);
139 for (mir.literal_relocs) |literal_reloc| {
140 var instruction = mir.body[literal_reloc.label];
141 instruction.load_store.register_literal.group.imm19 += literal_reloc_offset;
142 instruction.write(
143 code.items[body_end - Instruction.size * (1 + literal_reloc.label) ..][0..Instruction.size],
144 );
145 }
146}
147
148fn emitInstructionsForward(code: *std.ArrayListUnmanaged(u8), instructions: []const Instruction) void {
149 for (instructions) |instruction| emitInstruction(code, instruction);
150}
151fn emitInstructionsBackward(code: *std.ArrayListUnmanaged(u8), instructions: []const Instruction) void {
152 var instruction_index = instructions.len;
153 while (instruction_index > 0) {
154 instruction_index -= 1;
155 emitInstruction(code, instructions[instruction_index]);
156 }
157}
158fn emitInstruction(code: *std.ArrayListUnmanaged(u8), instruction: Instruction) void {
159 mir_log.debug(" {f}", .{instruction});
160 instruction.write(code.addManyAsArrayAssumeCapacity(Instruction.size));
161}
162
163fn emitReloc(
164 lf: *link.File,
165 zcu: *Zcu,
166 owner_nav: InternPool.Nav.Index,
167 sym_index: u32,
168 instruction: Instruction,
169 offset: u32,
170 addend: u64,
171) !void {
172 const gpa = zcu.gpa;
173 switch (instruction.decode()) {
174 else => unreachable,
175 .branch_exception_generating_system => |decoded| if (lf.cast(.elf)) |ef| {
176 const zo = ef.zigObjectPtr().?;
177 const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?;
178 const r_type: std.elf.R_AARCH64 = switch (decoded.decode().unconditional_branch_immediate.group.op) {
179 .b => .JUMP26,
180 .bl => .CALL26,
181 };
182 try atom.addReloc(gpa, .{
183 .r_offset = offset,
184 .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type),
185 .r_addend = @bitCast(addend),
186 }, zo);
187 } else if (lf.cast(.macho)) |mf| {
188 const zo = mf.getZigObject().?;
189 const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?;
190 try atom.addReloc(mf, .{
191 .tag = .@"extern",
192 .offset = offset,
193 .target = sym_index,
194 .addend = @bitCast(addend),
195 .type = .branch,
196 .meta = .{
197 .pcrel = true,
198 .has_subtractor = false,
199 .length = 2,
200 .symbolnum = @intCast(sym_index),
201 },
202 });
203 },
204 .data_processing_immediate => |decoded| if (lf.cast(.elf)) |ef| {
205 const zo = ef.zigObjectPtr().?;
206 const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?;
207 const r_type: std.elf.R_AARCH64 = switch (decoded.decode()) {
208 else => unreachable,
209 .pc_relative_addressing => |pc_relative_addressing| switch (pc_relative_addressing.group.op) {
210 .adr => .ADR_PREL_LO21,
211 .adrp => .ADR_PREL_PG_HI21,
212 },
213 .add_subtract_immediate => |add_subtract_immediate| switch (add_subtract_immediate.group.op) {
214 .add => .ADD_ABS_LO12_NC,
215 .sub => unreachable,
216 },
217 };
218 try atom.addReloc(gpa, .{
219 .r_offset = offset,
220 .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type),
221 .r_addend = @bitCast(addend),
222 }, zo);
223 } else if (lf.cast(.macho)) |mf| {
224 const zo = mf.getZigObject().?;
225 const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?;
226 switch (decoded.decode()) {
227 else => unreachable,
228 .pc_relative_addressing => |pc_relative_addressing| switch (pc_relative_addressing.group.op) {
229 .adr => unreachable,
230 .adrp => try atom.addReloc(mf, .{
231 .tag = .@"extern",
232 .offset = offset,
233 .target = sym_index,
234 .addend = @bitCast(addend),
235 .type = .page,
236 .meta = .{
237 .pcrel = true,
238 .has_subtractor = false,
239 .length = 2,
240 .symbolnum = @intCast(sym_index),
241 },
242 }),
243 },
244 .add_subtract_immediate => |add_subtract_immediate| switch (add_subtract_immediate.group.op) {
245 .add => try atom.addReloc(mf, .{
246 .tag = .@"extern",
247 .offset = offset,
248 .target = sym_index,
249 .addend = @bitCast(addend),
250 .type = .pageoff,
251 .meta = .{
252 .pcrel = false,
253 .has_subtractor = false,
254 .length = 2,
255 .symbolnum = @intCast(sym_index),
256 },
257 }),
258 .sub => unreachable,
259 },
260 }
261 },
262 }
263}
264
265const Air = @import("../../Air.zig");
266const assert = std.debug.assert;
267const mir_log = std.log.scoped(.mir);
268const Instruction = @import("encoding.zig").Instruction;
269const InternPool = @import("../../InternPool.zig");
270const link = @import("../../link.zig");
271const Mir = @This();
272const std = @import("std");
273const target_util = @import("../../target.zig");
274const Zcu = @import("../../Zcu.zig");
275const ZigType = @import("../../Type.zig");
src/codegen/aarch64/Select.zig created+10981
...@@ -0,0 +1,10981 @@
1pt: Zcu.PerThread,
2target: *const std.Target,
3air: Air,
4nav_index: InternPool.Nav.Index,
5
6// Blocks
7def_order: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, void),
8blocks: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, Block),
9loops: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, Loop),
10active_loops: std.ArrayListUnmanaged(Loop.Index),
11loop_live: struct {
12 set: std.AutoArrayHashMapUnmanaged(struct { Loop.Index, Air.Inst.Index }, void),
13 list: std.ArrayListUnmanaged(Air.Inst.Index),
14},
15dom_start: u32,
16dom_len: u32,
17dom: std.ArrayListUnmanaged(DomInt),
18
19// Wip Mir
20saved_registers: std.enums.EnumSet(Register.Alias),
21instructions: std.ArrayListUnmanaged(codegen.aarch64.encoding.Instruction),
22literals: std.ArrayListUnmanaged(u32),
23nav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Nav),
24uav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Uav),
25global_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Global),
26literal_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Literal),
27
28// Stack Frame
29returns: bool,
30va_list: struct {
31 __stack: Value.Indirect,
32 __gr_top: Value.Indirect,
33 __vr_top: Value.Indirect,
34},
35stack_size: u24,
36stack_align: InternPool.Alignment,
37
38// Value Tracking
39live_registers: LiveRegisters,
40live_values: std.AutoHashMapUnmanaged(Air.Inst.Index, Value.Index),
41values: std.ArrayListUnmanaged(Value),
42
43pub const LiveRegisters = std.enums.EnumArray(Register.Alias, Value.Index);
44
45pub const Block = struct {
46 live_registers: LiveRegisters,
47 target_label: u32,
48
49 pub const main: Air.Inst.Index = @enumFromInt(
50 std.math.maxInt(@typeInfo(Air.Inst.Index).@"enum".tag_type),
51 );
52
53 fn branch(block: *const Block, isel: *Select) !void {
54 if (isel.instructions.items.len > block.target_label) {
55 try isel.emit(.b(@intCast((isel.instructions.items.len + 1 - block.target_label) << 2)));
56 }
57 try isel.merge(&block.live_registers, .{});
58 }
59};
60
61pub const Loop = struct {
62 def_order: u32,
63 dom: u32,
64 depth: u32,
65 live: u32,
66 live_registers: LiveRegisters,
67 repeat_list: u32,
68
69 pub const invalid: Air.Inst.Index = @enumFromInt(
70 std.math.maxInt(@typeInfo(Air.Inst.Index).@"enum".tag_type),
71 );
72
73 pub const Index = enum(u32) {
74 _,
75
76 fn inst(li: Loop.Index, isel: *Select) Air.Inst.Index {
77 return isel.loops.keys()[@intFromEnum(li)];
78 }
79
80 fn get(li: Loop.Index, isel: *Select) *Loop {
81 return &isel.loops.values()[@intFromEnum(li)];
82 }
83 };
84
85 pub const empty_list: u32 = std.math.maxInt(u32);
86
87 fn branch(loop: *Loop, isel: *Select) !void {
88 try isel.instructions.ensureUnusedCapacity(isel.pt.zcu.gpa, 1);
89 const repeat_list_tail = loop.repeat_list;
90 loop.repeat_list = @intCast(isel.instructions.items.len);
91 isel.instructions.appendAssumeCapacity(@bitCast(repeat_list_tail));
92 try isel.merge(&loop.live_registers, .{});
93 }
94};
95
96pub fn deinit(isel: *Select) void {
97 const gpa = isel.pt.zcu.gpa;
98
99 isel.def_order.deinit(gpa);
100 isel.blocks.deinit(gpa);
101 isel.loops.deinit(gpa);
102 isel.active_loops.deinit(gpa);
103 isel.loop_live.set.deinit(gpa);
104 isel.loop_live.list.deinit(gpa);
105 isel.dom.deinit(gpa);
106
107 isel.instructions.deinit(gpa);
108 isel.literals.deinit(gpa);
109 isel.nav_relocs.deinit(gpa);
110 isel.uav_relocs.deinit(gpa);
111 isel.global_relocs.deinit(gpa);
112 isel.literal_relocs.deinit(gpa);
113
114 isel.live_values.deinit(gpa);
115 isel.values.deinit(gpa);
116
117 isel.* = undefined;
118}
119
120pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
121 const zcu = isel.pt.zcu;
122 const ip = &zcu.intern_pool;
123 const gpa = zcu.gpa;
124 const air_tags = isel.air.instructions.items(.tag);
125 const air_data = isel.air.instructions.items(.data);
126 var air_body_index: usize = 0;
127 var air_inst_index = air_body[air_body_index];
128 const initial_def_order_len = isel.def_order.count();
129 air_tag: switch (air_tags[@intFromEnum(air_inst_index)]) {
130 .arg,
131 .ret_addr,
132 .frame_addr,
133 .err_return_trace,
134 .save_err_return_trace_index,
135 .runtime_nav_ptr,
136 .c_va_start,
137 => {
138 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
139
140 air_body_index += 1;
141 air_inst_index = air_body[air_body_index];
142 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
143 },
144 .add,
145 .add_safe,
146 .add_optimized,
147 .add_wrap,
148 .add_sat,
149 .sub,
150 .sub_safe,
151 .sub_optimized,
152 .sub_wrap,
153 .sub_sat,
154 .mul,
155 .mul_safe,
156 .mul_optimized,
157 .mul_wrap,
158 .mul_sat,
159 .div_float,
160 .div_float_optimized,
161 .div_trunc,
162 .div_trunc_optimized,
163 .div_floor,
164 .div_floor_optimized,
165 .div_exact,
166 .div_exact_optimized,
167 .rem,
168 .rem_optimized,
169 .mod,
170 .mod_optimized,
171 .max,
172 .min,
173 .bit_and,
174 .bit_or,
175 .shr,
176 .shr_exact,
177 .shl,
178 .shl_exact,
179 .shl_sat,
180 .xor,
181 .cmp_lt,
182 .cmp_lt_optimized,
183 .cmp_lte,
184 .cmp_lte_optimized,
185 .cmp_eq,
186 .cmp_eq_optimized,
187 .cmp_gte,
188 .cmp_gte_optimized,
189 .cmp_gt,
190 .cmp_gt_optimized,
191 .cmp_neq,
192 .cmp_neq_optimized,
193 .bool_and,
194 .bool_or,
195 .array_elem_val,
196 .slice_elem_val,
197 .ptr_elem_val,
198 => {
199 const bin_op = air_data[@intFromEnum(air_inst_index)].bin_op;
200
201 try isel.analyzeUse(bin_op.lhs);
202 try isel.analyzeUse(bin_op.rhs);
203 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
204
205 air_body_index += 1;
206 air_inst_index = air_body[air_body_index];
207 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
208 },
209 .ptr_add,
210 .ptr_sub,
211 .add_with_overflow,
212 .sub_with_overflow,
213 .mul_with_overflow,
214 .shl_with_overflow,
215 .slice,
216 .slice_elem_ptr,
217 .ptr_elem_ptr,
218 => {
219 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
220 const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data;
221
222 try isel.analyzeUse(bin_op.lhs);
223 try isel.analyzeUse(bin_op.rhs);
224 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
225
226 air_body_index += 1;
227 air_inst_index = air_body[air_body_index];
228 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
229 },
230 .alloc => {
231 const ty = air_data[@intFromEnum(air_inst_index)].ty;
232
233 isel.stack_align = isel.stack_align.maxStrict(ty.ptrAlignment(zcu));
234 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
235
236 air_body_index += 1;
237 air_inst_index = air_body[air_body_index];
238 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
239 },
240 .inferred_alloc,
241 .inferred_alloc_comptime,
242 .wasm_memory_size,
243 .wasm_memory_grow,
244 .work_item_id,
245 .work_group_size,
246 .work_group_id,
247 => unreachable,
248 .ret_ptr => {
249 const ty = air_data[@intFromEnum(air_inst_index)].ty;
250
251 if (isel.live_values.get(Block.main)) |ret_vi| switch (ret_vi.parent(isel)) {
252 .unallocated, .stack_slot => isel.stack_align = isel.stack_align.maxStrict(ty.ptrAlignment(zcu)),
253 .value, .constant => unreachable,
254 .address => |address_vi| try isel.live_values.putNoClobber(gpa, air_inst_index, address_vi.ref(isel)),
255 };
256 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
257
258 air_body_index += 1;
259 air_inst_index = air_body[air_body_index];
260 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
261 },
262 .assembly => {
263 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
264 const extra = isel.air.extraData(Air.Asm, ty_pl.payload);
265 const operands: []const Air.Inst.Ref = @ptrCast(isel.air.extra.items[extra.end..][0 .. extra.data.flags.outputs_len + extra.data.inputs_len]);
266
267 for (operands) |operand| if (operand != .none) try isel.analyzeUse(operand);
268 if (ty_pl.ty != .void_type) try isel.def_order.putNoClobber(gpa, air_inst_index, {});
269
270 air_body_index += 1;
271 air_inst_index = air_body[air_body_index];
272 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
273 },
274 .not,
275 .clz,
276 .ctz,
277 .popcount,
278 .byte_swap,
279 .bit_reverse,
280 .abs,
281 .load,
282 .fptrunc,
283 .fpext,
284 .intcast,
285 .intcast_safe,
286 .trunc,
287 .optional_payload,
288 .optional_payload_ptr,
289 .optional_payload_ptr_set,
290 .wrap_optional,
291 .unwrap_errunion_payload,
292 .unwrap_errunion_err,
293 .unwrap_errunion_payload_ptr,
294 .unwrap_errunion_err_ptr,
295 .errunion_payload_ptr_set,
296 .wrap_errunion_payload,
297 .wrap_errunion_err,
298 .struct_field_ptr_index_0,
299 .struct_field_ptr_index_1,
300 .struct_field_ptr_index_2,
301 .struct_field_ptr_index_3,
302 .get_union_tag,
303 .ptr_slice_len_ptr,
304 .ptr_slice_ptr_ptr,
305 .array_to_slice,
306 .int_from_float,
307 .int_from_float_optimized,
308 .int_from_float_safe,
309 .int_from_float_optimized_safe,
310 .float_from_int,
311 .splat,
312 .error_set_has_value,
313 .addrspace_cast,
314 .c_va_arg,
315 .c_va_copy,
316 => {
317 const ty_op = air_data[@intFromEnum(air_inst_index)].ty_op;
318
319 try isel.analyzeUse(ty_op.operand);
320 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
321
322 air_body_index += 1;
323 air_inst_index = air_body[air_body_index];
324 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
325 },
326 .bitcast => {
327 const ty_op = air_data[@intFromEnum(air_inst_index)].ty_op;
328 maybe_noop: {
329 if (ty_op.ty.toInterned().? != isel.air.typeOf(ty_op.operand, ip).toIntern()) break :maybe_noop;
330 if (true) break :maybe_noop;
331 if (ty_op.operand.toIndex()) |src_air_inst_index| {
332 if (isel.hints.get(src_air_inst_index)) |hint_vpsi| {
333 try isel.hints.putNoClobber(gpa, air_inst_index, hint_vpsi);
334 }
335 }
336 }
337 try isel.analyzeUse(ty_op.operand);
338 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
339
340 air_body_index += 1;
341 air_inst_index = air_body[air_body_index];
342 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
343 },
344 inline .block, .dbg_inline_block => |air_tag| {
345 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
346 const extra = isel.air.extraData(switch (air_tag) {
347 else => comptime unreachable,
348 .block => Air.Block,
349 .dbg_inline_block => Air.DbgInlineBlock,
350 }, ty_pl.payload);
351 const result_ty = ty_pl.ty.toInterned().?;
352
353 if (result_ty == .noreturn_type) {
354 try isel.analyze(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
355
356 air_body_index += 1;
357 break :air_tag;
358 }
359
360 assert(!(try isel.blocks.getOrPut(gpa, air_inst_index)).found_existing);
361 try isel.analyze(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
362 const block_entry = isel.blocks.pop().?;
363 assert(block_entry.key == air_inst_index);
364
365 if (result_ty != .void_type) try isel.def_order.putNoClobber(gpa, air_inst_index, {});
366
367 air_body_index += 1;
368 air_inst_index = air_body[air_body_index];
369 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
370 },
371 .loop => {
372 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
373 const extra = isel.air.extraData(Air.Block, ty_pl.payload);
374
375 const initial_dom_start = isel.dom_start;
376 const initial_dom_len = isel.dom_len;
377 isel.dom_start = @intCast(isel.dom.items.len);
378 isel.dom_len = @intCast(isel.blocks.count());
379 try isel.active_loops.append(gpa, @enumFromInt(isel.loops.count()));
380 try isel.loops.putNoClobber(gpa, air_inst_index, .{
381 .def_order = @intCast(isel.def_order.count()),
382 .dom = isel.dom_start,
383 .depth = isel.dom_len,
384 .live = 0,
385 .live_registers = undefined,
386 .repeat_list = undefined,
387 });
388 try isel.dom.appendNTimes(gpa, 0, std.math.divCeil(usize, isel.dom_len, @bitSizeOf(DomInt)) catch unreachable);
389 try isel.analyze(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
390 for (
391 isel.dom.items[initial_dom_start..].ptr,
392 isel.dom.items[isel.dom_start..][0 .. std.math.divCeil(usize, initial_dom_len, @bitSizeOf(DomInt)) catch unreachable],
393 ) |*initial_dom, loop_dom| initial_dom.* |= loop_dom;
394 isel.dom_start = initial_dom_start;
395 isel.dom_len = initial_dom_len;
396 assert(isel.active_loops.pop().?.inst(isel) == air_inst_index);
397
398 air_body_index += 1;
399 },
400 .repeat, .trap, .unreach => air_body_index += 1,
401 .br => {
402 const br = air_data[@intFromEnum(air_inst_index)].br;
403 const block_index = isel.blocks.getIndex(br.block_inst).?;
404 if (block_index < isel.dom_len) isel.dom.items[isel.dom_start + block_index / @bitSizeOf(DomInt)] |= @as(DomInt, 1) << @truncate(block_index);
405 try isel.analyzeUse(br.operand);
406
407 air_body_index += 1;
408 },
409 .breakpoint,
410 .dbg_stmt,
411 .dbg_empty_stmt,
412 .dbg_var_ptr,
413 .dbg_var_val,
414 .dbg_arg_inline,
415 => {
416 air_body_index += 1;
417 air_inst_index = air_body[air_body_index];
418 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
419 },
420 .call,
421 .call_always_tail,
422 .call_never_tail,
423 .call_never_inline,
424 => {
425 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
426 const extra = isel.air.extraData(Air.Call, pl_op.payload);
427 const args: []const Air.Inst.Ref = @ptrCast(isel.air.extra.items[extra.end..][0..extra.data.args_len]);
428 isel.saved_registers.insert(.lr);
429
430 try isel.analyzeUse(pl_op.operand);
431 var param_it: CallAbiIterator = .init;
432 for (args) |arg| {
433 const restore_values_len = isel.values.items.len;
434 defer isel.values.shrinkRetainingCapacity(restore_values_len);
435 const param_vi = try param_it.param(isel, isel.air.typeOf(arg, ip)) orelse continue;
436 const param_parent = param_vi.parent(isel);
437 switch (switch (param_parent) {
438 .unallocated, .stack_slot => param_parent,
439 .value, .constant => unreachable,
440 .address => |address_vi| address_vi.parent(isel),
441 }) {
442 .unallocated => {},
443 .stack_slot => |stack_slot| {
444 assert(stack_slot.base == .sp);
445 isel.stack_size = @max(isel.stack_size, stack_slot.offset);
446 },
447 .value, .constant, .address => unreachable,
448 }
449
450 try isel.analyzeUse(arg);
451 }
452
453 var ret_it: CallAbiIterator = .init;
454 if (try ret_it.ret(isel, isel.air.typeOfIndex(air_inst_index, ip))) |ret_vi| {
455 tracking_log.debug("${d} <- %{d}", .{ @intFromEnum(ret_vi), @intFromEnum(air_inst_index) });
456 switch (ret_vi.parent(isel)) {
457 .unallocated, .stack_slot => {},
458 .value, .constant => unreachable,
459 .address => |address_vi| {
460 defer address_vi.deref(isel);
461 const ret_value = ret_vi.get(isel);
462 ret_value.flags.parent_tag = .unallocated;
463 ret_value.parent_payload = .{ .unallocated = {} };
464 },
465 }
466 try isel.live_values.putNoClobber(gpa, air_inst_index, ret_vi);
467
468 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
469 }
470
471 air_body_index += 1;
472 air_inst_index = air_body[air_body_index];
473 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
474 },
475 .sqrt,
476 .sin,
477 .cos,
478 .tan,
479 .exp,
480 .exp2,
481 .log,
482 .log2,
483 .log10,
484 .floor,
485 .ceil,
486 .round,
487 .trunc_float,
488 .neg,
489 .neg_optimized,
490 .is_null,
491 .is_non_null,
492 .is_null_ptr,
493 .is_non_null_ptr,
494 .is_err,
495 .is_non_err,
496 .is_err_ptr,
497 .is_non_err_ptr,
498 .is_named_enum_value,
499 .tag_name,
500 .error_name,
501 .cmp_lt_errors_len,
502 => {
503 const un_op = air_data[@intFromEnum(air_inst_index)].un_op;
504
505 try isel.analyzeUse(un_op);
506 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
507
508 air_body_index += 1;
509 air_inst_index = air_body[air_body_index];
510 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
511 },
512 .cmp_vector, .cmp_vector_optimized => {
513 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
514 const extra = isel.air.extraData(Air.VectorCmp, ty_pl.payload).data;
515
516 try isel.analyzeUse(extra.lhs);
517 try isel.analyzeUse(extra.rhs);
518 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
519
520 air_body_index += 1;
521 air_inst_index = air_body[air_body_index];
522 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
523 },
524 .cond_br => {
525 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
526 const extra = isel.air.extraData(Air.CondBr, pl_op.payload);
527
528 try isel.analyzeUse(pl_op.operand);
529
530 try isel.analyze(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.then_body_len]));
531 try isel.analyze(@ptrCast(isel.air.extra.items[extra.end + extra.data.then_body_len ..][0..extra.data.else_body_len]));
532
533 air_body_index += 1;
534 },
535 .switch_br => {
536 const switch_br = isel.air.unwrapSwitch(air_inst_index);
537
538 try isel.analyzeUse(switch_br.operand);
539
540 var cases_it = switch_br.iterateCases();
541 while (cases_it.next()) |case| try isel.analyze(case.body);
542 if (switch_br.else_body_len > 0) try isel.analyze(cases_it.elseBody());
543
544 air_body_index += 1;
545 },
546 .loop_switch_br => {
547 const switch_br = isel.air.unwrapSwitch(air_inst_index);
548
549 const initial_dom_start = isel.dom_start;
550 const initial_dom_len = isel.dom_len;
551 isel.dom_start = @intCast(isel.dom.items.len);
552 isel.dom_len = @intCast(isel.blocks.count());
553 try isel.active_loops.append(gpa, @enumFromInt(isel.loops.count()));
554 try isel.loops.putNoClobber(gpa, air_inst_index, .{
555 .def_order = @intCast(isel.def_order.count()),
556 .dom = isel.dom_start,
557 .depth = isel.dom_len,
558 .live = 0,
559 .live_registers = undefined,
560 .repeat_list = undefined,
561 });
562 try isel.dom.appendNTimes(gpa, 0, std.math.divCeil(usize, isel.dom_len, @bitSizeOf(DomInt)) catch unreachable);
563
564 var cases_it = switch_br.iterateCases();
565 while (cases_it.next()) |case| try isel.analyze(case.body);
566 if (switch_br.else_body_len > 0) try isel.analyze(cases_it.elseBody());
567
568 for (
569 isel.dom.items[initial_dom_start..].ptr,
570 isel.dom.items[isel.dom_start..][0 .. std.math.divCeil(usize, initial_dom_len, @bitSizeOf(DomInt)) catch unreachable],
571 ) |*initial_dom, loop_dom| initial_dom.* |= loop_dom;
572 isel.dom_start = initial_dom_start;
573 isel.dom_len = initial_dom_len;
574 assert(isel.active_loops.pop().?.inst(isel) == air_inst_index);
575
576 air_body_index += 1;
577 },
578 .switch_dispatch => {
579 const br = air_data[@intFromEnum(air_inst_index)].br;
580
581 try isel.analyzeUse(br.operand);
582
583 air_body_index += 1;
584 },
585 .@"try", .try_cold, .try_ptr, .try_ptr_cold => {
586 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
587 const extra = isel.air.extraData(Air.Try, pl_op.payload);
588
589 try isel.analyzeUse(pl_op.operand);
590 try isel.analyze(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
591 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
592
593 air_body_index += 1;
594 air_inst_index = air_body[air_body_index];
595 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
596 },
597 .ret, .ret_safe, .ret_load => {
598 const un_op = air_data[@intFromEnum(air_inst_index)].un_op;
599 isel.returns = true;
600
601 const block_index = 0;
602 assert(isel.blocks.keys()[block_index] == Block.main);
603 if (isel.dom_len > 0) isel.dom.items[isel.dom_start] |= 1 << block_index;
604
605 try isel.analyzeUse(un_op);
606
607 air_body_index += 1;
608 },
609 .store,
610 .store_safe,
611 .set_union_tag,
612 .memset,
613 .memset_safe,
614 .memcpy,
615 .memmove,
616 .atomic_store_unordered,
617 .atomic_store_monotonic,
618 .atomic_store_release,
619 .atomic_store_seq_cst,
620 => {
621 const bin_op = air_data[@intFromEnum(air_inst_index)].bin_op;
622
623 try isel.analyzeUse(bin_op.lhs);
624 try isel.analyzeUse(bin_op.rhs);
625
626 air_body_index += 1;
627 air_inst_index = air_body[air_body_index];
628 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
629 },
630 .struct_field_ptr, .struct_field_val => {
631 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
632 const extra = isel.air.extraData(Air.StructField, ty_pl.payload).data;
633
634 try isel.analyzeUse(extra.struct_operand);
635 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
636
637 air_body_index += 1;
638 air_inst_index = air_body[air_body_index];
639 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
640 },
641 .slice_len => {
642 const ty_op = air_data[@intFromEnum(air_inst_index)].ty_op;
643
644 try isel.analyzeUse(ty_op.operand);
645 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
646
647 const slice_vi = try isel.use(ty_op.operand);
648 var len_part_it = slice_vi.field(isel.air.typeOf(ty_op.operand, ip), 8, 8);
649 if (try len_part_it.only(isel)) |len_part_vi|
650 try isel.live_values.putNoClobber(gpa, air_inst_index, len_part_vi.ref(isel));
651
652 air_body_index += 1;
653 air_inst_index = air_body[air_body_index];
654 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
655 },
656 .slice_ptr => {
657 const ty_op = air_data[@intFromEnum(air_inst_index)].ty_op;
658
659 try isel.analyzeUse(ty_op.operand);
660 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
661
662 const slice_vi = try isel.use(ty_op.operand);
663 var ptr_part_it = slice_vi.field(isel.air.typeOf(ty_op.operand, ip), 0, 8);
664 if (try ptr_part_it.only(isel)) |ptr_part_vi|
665 try isel.live_values.putNoClobber(gpa, air_inst_index, ptr_part_vi.ref(isel));
666
667 air_body_index += 1;
668 air_inst_index = air_body[air_body_index];
669 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
670 },
671 .reduce, .reduce_optimized => {
672 const reduce = air_data[@intFromEnum(air_inst_index)].reduce;
673
674 try isel.analyzeUse(reduce.operand);
675 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
676
677 air_body_index += 1;
678 air_inst_index = air_body[air_body_index];
679 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
680 },
681 .shuffle_one => {
682 const extra = isel.air.unwrapShuffleOne(zcu, air_inst_index);
683
684 try isel.analyzeUse(extra.operand);
685 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
686
687 air_body_index += 1;
688 air_inst_index = air_body[air_body_index];
689 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
690 },
691 .shuffle_two => {
692 const extra = isel.air.unwrapShuffleTwo(zcu, air_inst_index);
693
694 try isel.analyzeUse(extra.operand_a);
695 try isel.analyzeUse(extra.operand_b);
696 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
697
698 air_body_index += 1;
699 air_inst_index = air_body[air_body_index];
700 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
701 },
702 .select, .mul_add => {
703 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
704 const bin_op = isel.air.extraData(Air.Bin, pl_op.payload).data;
705
706 try isel.analyzeUse(pl_op.operand);
707 try isel.analyzeUse(bin_op.lhs);
708 try isel.analyzeUse(bin_op.rhs);
709 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
710
711 air_body_index += 1;
712 air_inst_index = air_body[air_body_index];
713 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
714 },
715 .cmpxchg_weak, .cmpxchg_strong => {
716 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
717 const extra = isel.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
718
719 try isel.analyzeUse(extra.ptr);
720 try isel.analyzeUse(extra.expected_value);
721 try isel.analyzeUse(extra.new_value);
722 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
723
724 air_body_index += 1;
725 air_inst_index = air_body[air_body_index];
726 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
727 },
728 .atomic_load => {
729 const atomic_load = air_data[@intFromEnum(air_inst_index)].atomic_load;
730
731 try isel.analyzeUse(atomic_load.ptr);
732 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
733
734 air_body_index += 1;
735 air_inst_index = air_body[air_body_index];
736 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
737 },
738 .atomic_rmw => {
739 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
740 const extra = isel.air.extraData(Air.AtomicRmw, pl_op.payload).data;
741
742 try isel.analyzeUse(extra.operand);
743 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
744
745 air_body_index += 1;
746 air_inst_index = air_body[air_body_index];
747 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
748 },
749 .aggregate_init => {
750 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
751 const elements: []const Air.Inst.Ref = @ptrCast(isel.air.extra.items[ty_pl.payload..][0..@intCast(ty_pl.ty.toType().arrayLen(zcu))]);
752
753 for (elements) |element| try isel.analyzeUse(element);
754 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
755
756 air_body_index += 1;
757 air_inst_index = air_body[air_body_index];
758 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
759 },
760 .union_init => {
761 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
762 const extra = isel.air.extraData(Air.UnionInit, ty_pl.payload).data;
763
764 try isel.analyzeUse(extra.init);
765 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
766
767 air_body_index += 1;
768 air_inst_index = air_body[air_body_index];
769 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
770 },
771 .prefetch => {
772 const prefetch = air_data[@intFromEnum(air_inst_index)].prefetch;
773
774 try isel.analyzeUse(prefetch.ptr);
775
776 air_body_index += 1;
777 air_inst_index = air_body[air_body_index];
778 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
779 },
780 .field_parent_ptr => {
781 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
782 const extra = isel.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
783
784 try isel.analyzeUse(extra.field_ptr);
785 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
786
787 air_body_index += 1;
788 air_inst_index = air_body[air_body_index];
789 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
790 },
791 .set_err_return_trace, .c_va_end => {
792 const un_op = air_data[@intFromEnum(air_inst_index)].un_op;
793
794 try isel.analyzeUse(un_op);
795
796 air_body_index += 1;
797 air_inst_index = air_body[air_body_index];
798 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
799 },
800 .vector_store_elem => {
801 const vector_store_elem = air_data[@intFromEnum(air_inst_index)].vector_store_elem;
802 const bin_op = isel.air.extraData(Air.Bin, vector_store_elem.payload).data;
803
804 try isel.analyzeUse(vector_store_elem.vector_ptr);
805 try isel.analyzeUse(bin_op.lhs);
806 try isel.analyzeUse(bin_op.rhs);
807
808 air_body_index += 1;
809 air_inst_index = air_body[air_body_index];
810 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
811 },
812 }
813 assert(air_body_index == air_body.len);
814 isel.def_order.shrinkRetainingCapacity(initial_def_order_len);
815}
816
817fn analyzeUse(isel: *Select, air_ref: Air.Inst.Ref) !void {
818 const air_inst_index = air_ref.toIndex() orelse return;
819 const def_order_index = isel.def_order.getIndex(air_inst_index).?;
820
821 // Loop liveness
822 var active_loop_index = isel.active_loops.items.len;
823 while (active_loop_index > 0) {
824 const prev_active_loop_index = active_loop_index - 1;
825 const active_loop = isel.active_loops.items[prev_active_loop_index];
826 if (def_order_index >= active_loop.get(isel).def_order) break;
827 active_loop_index = prev_active_loop_index;
828 }
829 if (active_loop_index < isel.active_loops.items.len) {
830 const active_loop = isel.active_loops.items[active_loop_index];
831 const loop_live_gop =
832 try isel.loop_live.set.getOrPut(isel.pt.zcu.gpa, .{ active_loop, air_inst_index });
833 if (!loop_live_gop.found_existing) active_loop.get(isel).live += 1;
834 }
835}
836
837pub fn finishAnalysis(isel: *Select) !void {
838 const gpa = isel.pt.zcu.gpa;
839
840 // Loop Liveness
841 if (isel.loops.count() > 0) {
842 try isel.loops.ensureUnusedCapacity(gpa, 1);
843
844 const loop_live_len: u32 = @intCast(isel.loop_live.set.count());
845 if (loop_live_len > 0) {
846 try isel.loop_live.list.resize(gpa, loop_live_len);
847
848 const loops = isel.loops.values();
849 for (loops[1..], loops[0 .. loops.len - 1]) |*loop, prev_loop| loop.live += prev_loop.live;
850 assert(loops[loops.len - 1].live == loop_live_len);
851
852 for (isel.loop_live.set.keys()) |entry| {
853 const loop, const inst = entry;
854 const loop_live = &loop.get(isel).live;
855 loop_live.* -= 1;
856 isel.loop_live.list.items[loop_live.*] = inst;
857 }
858 assert(loops[0].live == 0);
859 }
860
861 const invalid_gop = isel.loops.getOrPutAssumeCapacity(Loop.invalid);
862 assert(!invalid_gop.found_existing);
863 invalid_gop.value_ptr.live = loop_live_len;
864 }
865}
866
867pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
868 const zcu = isel.pt.zcu;
869 const ip = &zcu.intern_pool;
870 const gpa = zcu.gpa;
871
872 {
873 var live_reg_it = isel.live_registers.iterator();
874 while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) {
875 _ => {
876 const ra = &live_reg_entry.value.get(isel).location_payload.small.register;
877 assert(ra.* == live_reg_entry.key);
878 ra.* = .zr;
879 live_reg_entry.value.* = .free;
880 },
881 .allocating => live_reg_entry.value.* = .free,
882 .free => {},
883 };
884 }
885
886 var air: struct {
887 isel: *Select,
888 tag_items: []const Air.Inst.Tag,
889 data_items: []const Air.Inst.Data,
890 body: []const Air.Inst.Index,
891 body_index: u32,
892 inst_index: Air.Inst.Index,
893
894 fn tag(it: *@This(), inst_index: Air.Inst.Index) Air.Inst.Tag {
895 return it.tag_items[@intFromEnum(inst_index)];
896 }
897
898 fn data(it: *@This(), inst_index: Air.Inst.Index) Air.Inst.Data {
899 return it.data_items[@intFromEnum(inst_index)];
900 }
901
902 fn next(it: *@This()) ?Air.Inst.Tag {
903 if (it.body_index == 0) {
904 @branchHint(.unlikely);
905 return null;
906 }
907 it.body_index -= 1;
908 it.inst_index = it.body[it.body_index];
909 wip_mir_log.debug("{f}", .{it.fmtAir(it.inst_index)});
910 return it.tag(it.inst_index);
911 }
912
913 fn fmtAir(it: @This(), inst: Air.Inst.Index) struct {
914 isel: *Select,
915 inst: Air.Inst.Index,
916 pub fn format(fmt_air: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
917 fmt_air.isel.air.writeInst(writer, fmt_air.inst, fmt_air.isel.pt, null);
918 }
919 } {
920 return .{ .isel = it.isel, .inst = inst };
921 }
922 } = .{
923 .isel = isel,
924 .tag_items = isel.air.instructions.items(.tag),
925 .data_items = isel.air.instructions.items(.data),
926 .body = air_body,
927 .body_index = @intCast(air_body.len),
928 .inst_index = undefined,
929 };
930 air_tag: switch (air.next().?) {
931 else => |air_tag| return isel.fail("unimplemented {s}", .{@tagName(air_tag)}),
932 .arg => {
933 const arg_vi = isel.live_values.fetchRemove(air.inst_index).?.value;
934 defer arg_vi.deref(isel);
935 switch (arg_vi.parent(isel)) {
936 .unallocated, .stack_slot => if (arg_vi.hint(isel)) |arg_ra| {
937 try arg_vi.defLiveIn(isel, arg_ra, comptime &.initFill(.free));
938 } else {
939 var arg_part_it = arg_vi.parts(isel);
940 while (arg_part_it.next()) |arg_part| {
941 try arg_part.defLiveIn(isel, arg_part.hint(isel).?, comptime &.initFill(.free));
942 }
943 },
944 .value, .constant => unreachable,
945 .address => |address_vi| try address_vi.defLiveIn(isel, address_vi.hint(isel).?, comptime &.initFill(.free)),
946 }
947 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
948 },
949 .add, .add_optimized, .add_wrap, .sub, .sub_optimized, .sub_wrap => |air_tag| {
950 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
951 defer res_vi.value.deref(isel);
952
953 const bin_op = air.data(air.inst_index).bin_op;
954 const ty = isel.air.typeOf(bin_op.lhs, ip);
955 if (!ty.isRuntimeFloat()) try res_vi.value.addOrSubtract(isel, ty, try isel.use(bin_op.lhs), switch (air_tag) {
956 else => unreachable,
957 .add, .add_wrap => .add,
958 .sub, .sub_wrap => .sub,
959 }, try isel.use(bin_op.rhs), .{ .wrap = switch (air_tag) {
960 else => unreachable,
961 .add, .sub => false,
962 .add_wrap, .sub_wrap => true,
963 } }) else switch (ty.floatBits(isel.target)) {
964 else => unreachable,
965 16, 32, 64 => |bits| {
966 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
967 const need_fcvt = switch (bits) {
968 else => unreachable,
969 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
970 32, 64 => false,
971 };
972 if (need_fcvt) try isel.emit(.fcvt(res_ra.h(), res_ra.s()));
973 const lhs_vi = try isel.use(bin_op.lhs);
974 const rhs_vi = try isel.use(bin_op.rhs);
975 const lhs_mat = try lhs_vi.matReg(isel);
976 const rhs_mat = try rhs_vi.matReg(isel);
977 const lhs_ra = if (need_fcvt) try isel.allocVecReg() else lhs_mat.ra;
978 defer if (need_fcvt) isel.freeReg(lhs_ra);
979 const rhs_ra = if (need_fcvt) try isel.allocVecReg() else rhs_mat.ra;
980 defer if (need_fcvt) isel.freeReg(rhs_ra);
981 try isel.emit(bits: switch (bits) {
982 else => unreachable,
983 16 => if (need_fcvt) continue :bits 32 else switch (air_tag) {
984 else => unreachable,
985 .add, .add_optimized => .fadd(res_ra.h(), lhs_ra.h(), rhs_ra.h()),
986 .sub, .sub_optimized => .fsub(res_ra.h(), lhs_ra.h(), rhs_ra.h()),
987 },
988 32 => switch (air_tag) {
989 else => unreachable,
990 .add, .add_optimized => .fadd(res_ra.s(), lhs_ra.s(), rhs_ra.s()),
991 .sub, .sub_optimized => .fsub(res_ra.s(), lhs_ra.s(), rhs_ra.s()),
992 },
993 64 => switch (air_tag) {
994 else => unreachable,
995 .add, .add_optimized => .fadd(res_ra.d(), lhs_ra.d(), rhs_ra.d()),
996 .sub, .sub_optimized => .fsub(res_ra.d(), lhs_ra.d(), rhs_ra.d()),
997 },
998 });
999 if (need_fcvt) {
1000 try isel.emit(.fcvt(rhs_ra.s(), rhs_mat.ra.h()));
1001 try isel.emit(.fcvt(lhs_ra.s(), lhs_mat.ra.h()));
1002 }
1003 try rhs_mat.finish(isel);
1004 try lhs_mat.finish(isel);
1005 },
1006 80, 128 => |bits| {
1007 try call.prepareReturn(isel);
1008 switch (bits) {
1009 else => unreachable,
1010 16, 32, 64, 128 => try call.returnLiveIn(isel, res_vi.value, .v0),
1011 80 => {
1012 var res_hi16_it = res_vi.value.field(ty, 8, 8);
1013 const res_hi16_vi = try res_hi16_it.only(isel);
1014 try call.returnLiveIn(isel, res_hi16_vi.?, .r1);
1015 var res_lo64_it = res_vi.value.field(ty, 0, 8);
1016 const res_lo64_vi = try res_lo64_it.only(isel);
1017 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
1018 },
1019 }
1020 try call.finishReturn(isel);
1021
1022 try call.prepareCallee(isel);
1023 try isel.global_relocs.append(gpa, .{
1024 .global = switch (air_tag) {
1025 else => unreachable,
1026 .add, .add_optimized => switch (bits) {
1027 else => unreachable,
1028 16 => "__addhf3",
1029 32 => "__addsf3",
1030 64 => "__adddf3",
1031 80 => "__addxf3",
1032 128 => "__addtf3",
1033 },
1034 .sub, .sub_optimized => switch (bits) {
1035 else => unreachable,
1036 16 => "__subhf3",
1037 32 => "__subsf3",
1038 64 => "__subdf3",
1039 80 => "__subxf3",
1040 128 => "__subtf3",
1041 },
1042 },
1043 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
1044 });
1045 try isel.emit(.bl(0));
1046 try call.finishCallee(isel);
1047
1048 try call.prepareParams(isel);
1049 const lhs_vi = try isel.use(bin_op.lhs);
1050 const rhs_vi = try isel.use(bin_op.rhs);
1051 switch (bits) {
1052 else => unreachable,
1053 16, 32, 64, 128 => {
1054 try call.paramLiveOut(isel, rhs_vi, .v1);
1055 try call.paramLiveOut(isel, lhs_vi, .v0);
1056 },
1057 80 => {
1058 var rhs_hi16_it = rhs_vi.field(ty, 8, 8);
1059 const rhs_hi16_vi = try rhs_hi16_it.only(isel);
1060 try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3);
1061 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
1062 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
1063 try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2);
1064 var lhs_hi16_it = lhs_vi.field(ty, 8, 8);
1065 const lhs_hi16_vi = try lhs_hi16_it.only(isel);
1066 try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1);
1067 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
1068 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
1069 try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0);
1070 },
1071 }
1072 try call.finishParams(isel);
1073 },
1074 }
1075 }
1076 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
1077 },
1078 .add_sat, .sub_sat => |air_tag| {
1079 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
1080 defer res_vi.value.deref(isel);
1081
1082 const bin_op = air.data(air.inst_index).bin_op;
1083 const ty = isel.air.typeOf(bin_op.lhs, ip);
1084 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
1085 const int_info = ty.intInfo(zcu);
1086 switch (int_info.bits) {
1087 0 => unreachable,
1088 32, 64 => |bits| switch (int_info.signedness) {
1089 .signed => return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
1090 .unsigned => {
1091 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1092 const lhs_vi = try isel.use(bin_op.lhs);
1093 const rhs_vi = try isel.use(bin_op.rhs);
1094 const lhs_mat = try lhs_vi.matReg(isel);
1095 const rhs_mat = try rhs_vi.matReg(isel);
1096 const unsat_res_ra = try isel.allocIntReg();
1097 defer isel.freeReg(unsat_res_ra);
1098 switch (air_tag) {
1099 else => unreachable,
1100 .add_sat => switch (bits) {
1101 else => unreachable,
1102 32 => {
1103 try isel.emit(.csinv(res_ra.w(), unsat_res_ra.w(), .wzr, .invert(.cs)));
1104 try isel.emit(.adds(unsat_res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
1105 },
1106 64 => {
1107 try isel.emit(.csinv(res_ra.x(), unsat_res_ra.x(), .xzr, .invert(.cs)));
1108 try isel.emit(.adds(unsat_res_ra.x(), lhs_mat.ra.x(), .{ .register = rhs_mat.ra.x() }));
1109 },
1110 },
1111 .sub_sat => switch (bits) {
1112 else => unreachable,
1113 32 => {
1114 try isel.emit(.csel(res_ra.w(), unsat_res_ra.w(), .wzr, .invert(.cc)));
1115 try isel.emit(.subs(unsat_res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
1116 },
1117 64 => {
1118 try isel.emit(.csel(res_ra.x(), unsat_res_ra.x(), .xzr, .invert(.cc)));
1119 try isel.emit(.subs(unsat_res_ra.x(), lhs_mat.ra.x(), .{ .register = rhs_mat.ra.x() }));
1120 },
1121 },
1122 }
1123 try rhs_mat.finish(isel);
1124 try lhs_mat.finish(isel);
1125 },
1126 },
1127 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
1128 }
1129 }
1130 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
1131 },
1132 .mul, .mul_optimized, .mul_wrap => |air_tag| {
1133 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
1134 defer res_vi.value.deref(isel);
1135
1136 const bin_op = air.data(air.inst_index).bin_op;
1137 const ty = isel.air.typeOf(bin_op.lhs, ip);
1138 if (!ty.isRuntimeFloat()) {
1139 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
1140 const int_info = ty.intInfo(zcu);
1141 switch (int_info.bits) {
1142 0 => unreachable,
1143 1 => {
1144 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1145 switch (int_info.signedness) {
1146 .signed => switch (air_tag) {
1147 else => unreachable,
1148 .mul => break :unused try isel.emit(.orr(res_ra.w(), .wzr, .{ .register = .wzr })),
1149 .mul_wrap => {},
1150 },
1151 .unsigned => {},
1152 }
1153 const lhs_vi = try isel.use(bin_op.lhs);
1154 const rhs_vi = try isel.use(bin_op.rhs);
1155 const lhs_mat = try lhs_vi.matReg(isel);
1156 const rhs_mat = try rhs_vi.matReg(isel);
1157 try isel.emit(.@"and"(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
1158 try rhs_mat.finish(isel);
1159 try lhs_mat.finish(isel);
1160 },
1161 2...32 => |bits| {
1162 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1163 switch (air_tag) {
1164 else => unreachable,
1165 .mul => {},
1166 .mul_wrap => switch (bits) {
1167 else => unreachable,
1168 1...31 => try isel.emit(switch (int_info.signedness) {
1169 .signed => .sbfm(res_ra.w(), res_ra.w(), .{
1170 .N = .word,
1171 .immr = 0,
1172 .imms = @intCast(bits - 1),
1173 }),
1174 .unsigned => .ubfm(res_ra.w(), res_ra.w(), .{
1175 .N = .word,
1176 .immr = 0,
1177 .imms = @intCast(bits - 1),
1178 }),
1179 }),
1180 32 => {},
1181 },
1182 }
1183 const lhs_vi = try isel.use(bin_op.lhs);
1184 const rhs_vi = try isel.use(bin_op.rhs);
1185 const lhs_mat = try lhs_vi.matReg(isel);
1186 const rhs_mat = try rhs_vi.matReg(isel);
1187 try isel.emit(.madd(res_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w(), .wzr));
1188 try rhs_mat.finish(isel);
1189 try lhs_mat.finish(isel);
1190 },
1191 33...64 => |bits| {
1192 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1193 switch (air_tag) {
1194 else => unreachable,
1195 .mul => {},
1196 .mul_wrap => switch (bits) {
1197 else => unreachable,
1198 33...63 => try isel.emit(switch (int_info.signedness) {
1199 .signed => .sbfm(res_ra.x(), res_ra.x(), .{
1200 .N = .doubleword,
1201 .immr = 0,
1202 .imms = @intCast(bits - 1),
1203 }),
1204 .unsigned => .ubfm(res_ra.x(), res_ra.x(), .{
1205 .N = .doubleword,
1206 .immr = 0,
1207 .imms = @intCast(bits - 1),
1208 }),
1209 }),
1210 64 => {},
1211 },
1212 }
1213 const lhs_vi = try isel.use(bin_op.lhs);
1214 const rhs_vi = try isel.use(bin_op.rhs);
1215 const lhs_mat = try lhs_vi.matReg(isel);
1216 const rhs_mat = try rhs_vi.matReg(isel);
1217 try isel.emit(.madd(res_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr));
1218 try rhs_mat.finish(isel);
1219 try lhs_mat.finish(isel);
1220 },
1221 65...128 => |bits| {
1222 var res_hi64_it = res_vi.value.field(ty, 8, 8);
1223 const res_hi64_vi = try res_hi64_it.only(isel);
1224 const res_hi64_ra = try res_hi64_vi.?.defReg(isel);
1225 var res_lo64_it = res_vi.value.field(ty, 0, 8);
1226 const res_lo64_vi = try res_lo64_it.only(isel);
1227 const res_lo64_ra = try res_lo64_vi.?.defReg(isel);
1228 if (res_hi64_ra == null and res_lo64_ra == null) break :unused;
1229 if (res_hi64_ra) |res_ra| switch (air_tag) {
1230 else => unreachable,
1231 .mul => {},
1232 .mul_wrap => switch (bits) {
1233 else => unreachable,
1234 65...127 => try isel.emit(switch (int_info.signedness) {
1235 .signed => .sbfm(res_ra.x(), res_ra.x(), .{
1236 .N = .doubleword,
1237 .immr = 0,
1238 .imms = @intCast(bits - 1),
1239 }),
1240 .unsigned => .ubfm(res_ra.x(), res_ra.x(), .{
1241 .N = .doubleword,
1242 .immr = 0,
1243 .imms = @intCast(bits - 1),
1244 }),
1245 }),
1246 128 => {},
1247 },
1248 };
1249 const lhs_vi = try isel.use(bin_op.lhs);
1250 const rhs_vi = try isel.use(bin_op.rhs);
1251 const lhs_lo64_mat, const rhs_lo64_mat = lo64_mat: {
1252 const res_hi64_lock: RegLock = if (res_hi64_ra != null and res_lo64_ra != null)
1253 isel.lockReg(res_hi64_ra.?)
1254 else
1255 .empty;
1256 defer res_hi64_lock.unlock(isel);
1257
1258 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
1259 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
1260 const rhs_lo64_mat = try rhs_lo64_vi.?.matReg(isel);
1261 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
1262 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
1263 const lhs_lo64_mat = try lhs_lo64_vi.?.matReg(isel);
1264 break :lo64_mat .{ lhs_lo64_mat, rhs_lo64_mat };
1265 };
1266 if (res_lo64_ra) |res_ra| try isel.emit(.madd(res_ra.x(), lhs_lo64_mat.ra.x(), rhs_lo64_mat.ra.x(), .xzr));
1267 if (res_hi64_ra) |res_ra| {
1268 var rhs_hi64_it = rhs_vi.field(ty, 8, 8);
1269 const rhs_hi64_vi = try rhs_hi64_it.only(isel);
1270 const rhs_hi64_mat = try rhs_hi64_vi.?.matReg(isel);
1271 var lhs_hi64_it = lhs_vi.field(ty, 8, 8);
1272 const lhs_hi64_vi = try lhs_hi64_it.only(isel);
1273 const lhs_hi64_mat = try lhs_hi64_vi.?.matReg(isel);
1274 const acc_ra = try isel.allocIntReg();
1275 defer isel.freeReg(acc_ra);
1276 try isel.emit(.madd(res_ra.x(), lhs_hi64_mat.ra.x(), rhs_lo64_mat.ra.x(), acc_ra.x()));
1277 try isel.emit(.madd(acc_ra.x(), lhs_lo64_mat.ra.x(), rhs_hi64_mat.ra.x(), acc_ra.x()));
1278 try isel.emit(.umulh(acc_ra.x(), lhs_lo64_mat.ra.x(), rhs_lo64_mat.ra.x()));
1279 try rhs_hi64_mat.finish(isel);
1280 try lhs_hi64_mat.finish(isel);
1281 }
1282 try rhs_lo64_mat.finish(isel);
1283 try lhs_lo64_mat.finish(isel);
1284 },
1285 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
1286 }
1287 } else switch (ty.floatBits(isel.target)) {
1288 else => unreachable,
1289 16, 32, 64 => |bits| {
1290 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1291 const need_fcvt = switch (bits) {
1292 else => unreachable,
1293 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
1294 32, 64 => false,
1295 };
1296 if (need_fcvt) try isel.emit(.fcvt(res_ra.h(), res_ra.s()));
1297 const lhs_vi = try isel.use(bin_op.lhs);
1298 const rhs_vi = try isel.use(bin_op.rhs);
1299 const lhs_mat = try lhs_vi.matReg(isel);
1300 const rhs_mat = try rhs_vi.matReg(isel);
1301 const lhs_ra = if (need_fcvt) try isel.allocVecReg() else lhs_mat.ra;
1302 defer if (need_fcvt) isel.freeReg(lhs_ra);
1303 const rhs_ra = if (need_fcvt) try isel.allocVecReg() else rhs_mat.ra;
1304 defer if (need_fcvt) isel.freeReg(rhs_ra);
1305 try isel.emit(bits: switch (bits) {
1306 else => unreachable,
1307 16 => if (need_fcvt)
1308 continue :bits 32
1309 else
1310 .fmul(res_ra.h(), lhs_ra.h(), rhs_ra.h()),
1311 32 => .fmul(res_ra.s(), lhs_ra.s(), rhs_ra.s()),
1312 64 => .fmul(res_ra.d(), lhs_ra.d(), rhs_ra.d()),
1313 });
1314 if (need_fcvt) {
1315 try isel.emit(.fcvt(rhs_ra.s(), rhs_mat.ra.h()));
1316 try isel.emit(.fcvt(lhs_ra.s(), lhs_mat.ra.h()));
1317 }
1318 try rhs_mat.finish(isel);
1319 try lhs_mat.finish(isel);
1320 },
1321 80, 128 => |bits| {
1322 try call.prepareReturn(isel);
1323 switch (bits) {
1324 else => unreachable,
1325 16, 32, 64, 128 => try call.returnLiveIn(isel, res_vi.value, .v0),
1326 80 => {
1327 var res_hi16_it = res_vi.value.field(ty, 8, 8);
1328 const res_hi16_vi = try res_hi16_it.only(isel);
1329 try call.returnLiveIn(isel, res_hi16_vi.?, .r1);
1330 var res_lo64_it = res_vi.value.field(ty, 0, 8);
1331 const res_lo64_vi = try res_lo64_it.only(isel);
1332 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
1333 },
1334 }
1335 try call.finishReturn(isel);
1336
1337 try call.prepareCallee(isel);
1338 try isel.global_relocs.append(gpa, .{
1339 .global = switch (bits) {
1340 else => unreachable,
1341 16 => "__mulhf3",
1342 32 => "__mulsf3",
1343 64 => "__muldf3",
1344 80 => "__mulxf3",
1345 128 => "__multf3",
1346 },
1347 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
1348 });
1349 try isel.emit(.bl(0));
1350 try call.finishCallee(isel);
1351
1352 try call.prepareParams(isel);
1353 const lhs_vi = try isel.use(bin_op.lhs);
1354 const rhs_vi = try isel.use(bin_op.rhs);
1355 switch (bits) {
1356 else => unreachable,
1357 16, 32, 64, 128 => {
1358 try call.paramLiveOut(isel, rhs_vi, .v1);
1359 try call.paramLiveOut(isel, lhs_vi, .v0);
1360 },
1361 80 => {
1362 var rhs_hi16_it = rhs_vi.field(ty, 8, 8);
1363 const rhs_hi16_vi = try rhs_hi16_it.only(isel);
1364 try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3);
1365 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
1366 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
1367 try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2);
1368 var lhs_hi16_it = lhs_vi.field(ty, 8, 8);
1369 const lhs_hi16_vi = try lhs_hi16_it.only(isel);
1370 try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1);
1371 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
1372 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
1373 try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0);
1374 },
1375 }
1376 try call.finishParams(isel);
1377 },
1378 }
1379 }
1380 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
1381 },
1382 .mul_sat => |air_tag| {
1383 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
1384 defer res_vi.value.deref(isel);
1385
1386 const bin_op = air.data(air.inst_index).bin_op;
1387 const ty = isel.air.typeOf(bin_op.lhs, ip);
1388 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
1389 const int_info = ty.intInfo(zcu);
1390 switch (int_info.bits) {
1391 0 => unreachable,
1392 1 => {
1393 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1394 switch (int_info.signedness) {
1395 .signed => try isel.emit(.orr(res_ra.w(), .wzr, .{ .register = .wzr })),
1396 .unsigned => {
1397 const lhs_vi = try isel.use(bin_op.lhs);
1398 const rhs_vi = try isel.use(bin_op.rhs);
1399 const lhs_mat = try lhs_vi.matReg(isel);
1400 const rhs_mat = try rhs_vi.matReg(isel);
1401 try isel.emit(.@"and"(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
1402 try rhs_mat.finish(isel);
1403 try lhs_mat.finish(isel);
1404 },
1405 }
1406 },
1407 2...32 => |bits| {
1408 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1409 const saturated_ra = switch (int_info.signedness) {
1410 .signed => try isel.allocIntReg(),
1411 .unsigned => switch (bits) {
1412 else => unreachable,
1413 2...31 => try isel.allocIntReg(),
1414 32 => .zr,
1415 },
1416 };
1417 defer if (saturated_ra != .zr) isel.freeReg(saturated_ra);
1418 const unwrapped_ra = try isel.allocIntReg();
1419 defer isel.freeReg(unwrapped_ra);
1420 try isel.emit(switch (saturated_ra) {
1421 else => .csel(res_ra.w(), unwrapped_ra.w(), saturated_ra.w(), .eq),
1422 .zr => .csinv(res_ra.w(), unwrapped_ra.w(), saturated_ra.w(), .eq),
1423 });
1424 switch (bits) {
1425 else => unreachable,
1426 2...7, 9...15, 17...31 => switch (int_info.signedness) {
1427 .signed => {
1428 const wrapped_ra = try isel.allocIntReg();
1429 defer isel.freeReg(wrapped_ra);
1430 switch (bits) {
1431 else => unreachable,
1432 1...7, 9...15 => {
1433 try isel.emit(.subs(.wzr, unwrapped_ra.w(), .{ .register = wrapped_ra.w() }));
1434 try isel.emit(.sbfm(wrapped_ra.w(), unwrapped_ra.w(), .{
1435 .N = .word,
1436 .immr = 0,
1437 .imms = @intCast(bits - 1),
1438 }));
1439 },
1440 17...31 => {
1441 try isel.emit(.subs(.xzr, unwrapped_ra.x(), .{ .register = wrapped_ra.x() }));
1442 try isel.emit(.sbfm(wrapped_ra.x(), unwrapped_ra.x(), .{
1443 .N = .doubleword,
1444 .immr = 0,
1445 .imms = @intCast(bits - 1),
1446 }));
1447 },
1448 }
1449 },
1450 .unsigned => switch (bits) {
1451 else => unreachable,
1452 1...7, 9...15 => try isel.emit(.ands(.wzr, unwrapped_ra.w(), .{ .immediate = .{
1453 .N = .word,
1454 .immr = @intCast(32 - bits),
1455 .imms = @intCast(32 - bits - 1),
1456 } })),
1457 17...31 => try isel.emit(.ands(.xzr, unwrapped_ra.x(), .{ .immediate = .{
1458 .N = .doubleword,
1459 .immr = @intCast(64 - bits),
1460 .imms = @intCast(64 - bits - 1),
1461 } })),
1462 },
1463 },
1464 8 => try isel.emit(.subs(.wzr, unwrapped_ra.w(), .{ .extended_register = .{
1465 .register = unwrapped_ra.w(),
1466 .extend = switch (int_info.signedness) {
1467 .signed => .{ .sxtb = 0 },
1468 .unsigned => .{ .uxtb = 0 },
1469 },
1470 } })),
1471 16 => try isel.emit(.subs(.wzr, unwrapped_ra.w(), .{ .extended_register = .{
1472 .register = unwrapped_ra.w(),
1473 .extend = switch (int_info.signedness) {
1474 .signed => .{ .sxth = 0 },
1475 .unsigned => .{ .uxth = 0 },
1476 },
1477 } })),
1478 32 => try isel.emit(.subs(.xzr, unwrapped_ra.x(), .{ .extended_register = .{
1479 .register = unwrapped_ra.w(),
1480 .extend = switch (int_info.signedness) {
1481 .signed => .{ .sxtw = 0 },
1482 .unsigned => .{ .uxtw = 0 },
1483 },
1484 } })),
1485 }
1486 const lhs_vi = try isel.use(bin_op.lhs);
1487 const rhs_vi = try isel.use(bin_op.rhs);
1488 const lhs_mat = try lhs_vi.matReg(isel);
1489 const rhs_mat = try rhs_vi.matReg(isel);
1490 switch (int_info.signedness) {
1491 .signed => {
1492 try isel.emit(.eor(saturated_ra.w(), saturated_ra.w(), .{ .immediate = .{
1493 .N = .word,
1494 .immr = 0,
1495 .imms = @intCast(bits - 1 - 1),
1496 } }));
1497 try isel.emit(.sbfm(saturated_ra.w(), saturated_ra.w(), .{
1498 .N = .word,
1499 .immr = @intCast(bits - 1),
1500 .imms = @intCast(bits - 1 + 1 - 1),
1501 }));
1502 try isel.emit(.eor(saturated_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
1503 },
1504 .unsigned => switch (bits) {
1505 else => unreachable,
1506 2...31 => try isel.movImmediate(saturated_ra.w(), @as(u32, std.math.maxInt(u32)) >> @intCast(32 - bits)),
1507 32 => {},
1508 },
1509 }
1510 switch (bits) {
1511 else => unreachable,
1512 2...16 => try isel.emit(.madd(unwrapped_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w(), .wzr)),
1513 17...32 => switch (int_info.signedness) {
1514 .signed => try isel.emit(.smaddl(unwrapped_ra.x(), lhs_mat.ra.w(), rhs_mat.ra.w(), .xzr)),
1515 .unsigned => try isel.emit(.umaddl(unwrapped_ra.x(), lhs_mat.ra.w(), rhs_mat.ra.w(), .xzr)),
1516 },
1517 }
1518 try rhs_mat.finish(isel);
1519 try lhs_mat.finish(isel);
1520 },
1521 33...64 => |bits| {
1522 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1523 const saturated_ra = switch (int_info.signedness) {
1524 .signed => try isel.allocIntReg(),
1525 .unsigned => switch (bits) {
1526 else => unreachable,
1527 33...63 => try isel.allocIntReg(),
1528 64 => .zr,
1529 },
1530 };
1531 defer if (saturated_ra != .zr) isel.freeReg(saturated_ra);
1532 const unwrapped_lo64_ra = try isel.allocIntReg();
1533 defer isel.freeReg(unwrapped_lo64_ra);
1534 const unwrapped_hi64_ra = try isel.allocIntReg();
1535 defer isel.freeReg(unwrapped_hi64_ra);
1536 try isel.emit(switch (saturated_ra) {
1537 else => .csel(res_ra.x(), unwrapped_lo64_ra.x(), saturated_ra.x(), .eq),
1538 .zr => .csinv(res_ra.x(), unwrapped_lo64_ra.x(), saturated_ra.x(), .eq),
1539 });
1540 switch (int_info.signedness) {
1541 .signed => switch (bits) {
1542 else => unreachable,
1543 32...63 => {
1544 const wrapped_lo64_ra = try isel.allocIntReg();
1545 defer isel.freeReg(wrapped_lo64_ra);
1546 try isel.emit(.ccmp(
1547 unwrapped_lo64_ra.x(),
1548 .{ .register = wrapped_lo64_ra.x() },
1549 .{ .n = false, .z = false, .c = false, .v = false },
1550 .eq,
1551 ));
1552 try isel.emit(.subs(.xzr, unwrapped_hi64_ra.x(), .{ .shifted_register = .{
1553 .register = unwrapped_lo64_ra.x(),
1554 .shift = .{ .asr = 63 },
1555 } }));
1556 try isel.emit(.sbfm(wrapped_lo64_ra.x(), unwrapped_lo64_ra.x(), .{
1557 .N = .doubleword,
1558 .immr = 0,
1559 .imms = @intCast(bits - 1),
1560 }));
1561 },
1562 64 => try isel.emit(.subs(.xzr, unwrapped_hi64_ra.x(), .{ .shifted_register = .{
1563 .register = unwrapped_lo64_ra.x(),
1564 .shift = .{ .asr = @intCast(bits - 1) },
1565 } })),
1566 },
1567 .unsigned => switch (bits) {
1568 else => unreachable,
1569 32...63 => {
1570 const overflow_ra = try isel.allocIntReg();
1571 defer isel.freeReg(overflow_ra);
1572 try isel.emit(.subs(.xzr, overflow_ra.x(), .{ .immediate = 0 }));
1573 try isel.emit(.orr(overflow_ra.x(), unwrapped_hi64_ra.x(), .{ .shifted_register = .{
1574 .register = unwrapped_lo64_ra.x(),
1575 .shift = .{ .lsr = @intCast(bits) },
1576 } }));
1577 },
1578 64 => try isel.emit(.subs(.xzr, unwrapped_hi64_ra.x(), .{ .immediate = 0 })),
1579 },
1580 }
1581 const lhs_vi = try isel.use(bin_op.lhs);
1582 const rhs_vi = try isel.use(bin_op.rhs);
1583 const lhs_mat = try lhs_vi.matReg(isel);
1584 const rhs_mat = try rhs_vi.matReg(isel);
1585 switch (int_info.signedness) {
1586 .signed => {
1587 try isel.emit(.eor(saturated_ra.x(), saturated_ra.x(), .{ .immediate = .{
1588 .N = .doubleword,
1589 .immr = 0,
1590 .imms = @intCast(bits - 1 - 1),
1591 } }));
1592 try isel.emit(.sbfm(saturated_ra.x(), saturated_ra.x(), .{
1593 .N = .doubleword,
1594 .immr = @intCast(bits - 1),
1595 .imms = @intCast(bits - 1 + 1 - 1),
1596 }));
1597 try isel.emit(.eor(saturated_ra.x(), lhs_mat.ra.x(), .{ .register = rhs_mat.ra.x() }));
1598 try isel.emit(.madd(unwrapped_lo64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr));
1599 try isel.emit(.smulh(unwrapped_hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()));
1600 },
1601 .unsigned => {
1602 switch (bits) {
1603 else => unreachable,
1604 32...63 => try isel.movImmediate(saturated_ra.x(), @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits)),
1605 64 => {},
1606 }
1607 try isel.emit(.madd(unwrapped_lo64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr));
1608 try isel.emit(.umulh(unwrapped_hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()));
1609 },
1610 }
1611 try rhs_mat.finish(isel);
1612 try lhs_mat.finish(isel);
1613 },
1614 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
1615 }
1616 }
1617 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
1618 },
1619 .div_float, .div_float_optimized => {
1620 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
1621 defer res_vi.value.deref(isel);
1622
1623 const bin_op = air.data(air.inst_index).bin_op;
1624 const ty = isel.air.typeOf(bin_op.lhs, ip);
1625 switch (ty.floatBits(isel.target)) {
1626 else => unreachable,
1627 16, 32, 64 => |bits| {
1628 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1629 const need_fcvt = switch (bits) {
1630 else => unreachable,
1631 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
1632 32, 64 => false,
1633 };
1634 if (need_fcvt) try isel.emit(.fcvt(res_ra.h(), res_ra.s()));
1635 const lhs_vi = try isel.use(bin_op.lhs);
1636 const rhs_vi = try isel.use(bin_op.rhs);
1637 const lhs_mat = try lhs_vi.matReg(isel);
1638 const rhs_mat = try rhs_vi.matReg(isel);
1639 const lhs_ra = if (need_fcvt) try isel.allocVecReg() else lhs_mat.ra;
1640 defer if (need_fcvt) isel.freeReg(lhs_ra);
1641 const rhs_ra = if (need_fcvt) try isel.allocVecReg() else rhs_mat.ra;
1642 defer if (need_fcvt) isel.freeReg(rhs_ra);
1643 try isel.emit(bits: switch (bits) {
1644 else => unreachable,
1645 16 => if (need_fcvt)
1646 continue :bits 32
1647 else
1648 .fdiv(res_ra.h(), lhs_ra.h(), rhs_ra.h()),
1649 32 => .fdiv(res_ra.s(), lhs_ra.s(), rhs_ra.s()),
1650 64 => .fdiv(res_ra.d(), lhs_ra.d(), rhs_ra.d()),
1651 });
1652 if (need_fcvt) {
1653 try isel.emit(.fcvt(rhs_ra.s(), rhs_mat.ra.h()));
1654 try isel.emit(.fcvt(lhs_ra.s(), lhs_mat.ra.h()));
1655 }
1656 try rhs_mat.finish(isel);
1657 try lhs_mat.finish(isel);
1658 },
1659 80, 128 => |bits| {
1660 try call.prepareReturn(isel);
1661 switch (bits) {
1662 else => unreachable,
1663 16, 32, 64, 128 => try call.returnLiveIn(isel, res_vi.value, .v0),
1664 80 => {
1665 var res_hi16_it = res_vi.value.field(ty, 8, 8);
1666 const res_hi16_vi = try res_hi16_it.only(isel);
1667 try call.returnLiveIn(isel, res_hi16_vi.?, .r1);
1668 var res_lo64_it = res_vi.value.field(ty, 0, 8);
1669 const res_lo64_vi = try res_lo64_it.only(isel);
1670 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
1671 },
1672 }
1673 try call.finishReturn(isel);
1674
1675 try call.prepareCallee(isel);
1676 try isel.global_relocs.append(gpa, .{
1677 .global = switch (bits) {
1678 else => unreachable,
1679 16 => "__divhf3",
1680 32 => "__divsf3",
1681 64 => "__divdf3",
1682 80 => "__divxf3",
1683 128 => "__divtf3",
1684 },
1685 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
1686 });
1687 try isel.emit(.bl(0));
1688 try call.finishCallee(isel);
1689
1690 try call.prepareParams(isel);
1691 const lhs_vi = try isel.use(bin_op.lhs);
1692 const rhs_vi = try isel.use(bin_op.rhs);
1693 switch (bits) {
1694 else => unreachable,
1695 16, 32, 64, 128 => {
1696 try call.paramLiveOut(isel, rhs_vi, .v1);
1697 try call.paramLiveOut(isel, lhs_vi, .v0);
1698 },
1699 80 => {
1700 var rhs_hi16_it = rhs_vi.field(ty, 8, 8);
1701 const rhs_hi16_vi = try rhs_hi16_it.only(isel);
1702 try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3);
1703 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
1704 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
1705 try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2);
1706 var lhs_hi16_it = lhs_vi.field(ty, 8, 8);
1707 const lhs_hi16_vi = try lhs_hi16_it.only(isel);
1708 try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1);
1709 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
1710 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
1711 try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0);
1712 },
1713 }
1714 try call.finishParams(isel);
1715 },
1716 }
1717 }
1718 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
1719 },
1720 .div_trunc, .div_trunc_optimized, .div_floor, .div_floor_optimized, .div_exact, .div_exact_optimized => |air_tag| {
1721 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
1722 defer res_vi.value.deref(isel);
1723
1724 const bin_op = air.data(air.inst_index).bin_op;
1725 const ty = isel.air.typeOf(bin_op.lhs, ip);
1726 if (!ty.isRuntimeFloat()) {
1727 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
1728 const int_info = ty.intInfo(zcu);
1729 switch (int_info.bits) {
1730 0 => unreachable,
1731 1...64 => |bits| {
1732 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1733 const lhs_vi = try isel.use(bin_op.lhs);
1734 const rhs_vi = try isel.use(bin_op.rhs);
1735 const lhs_mat = try lhs_vi.matReg(isel);
1736 const rhs_mat = try rhs_vi.matReg(isel);
1737 const div_ra = div_ra: switch (air_tag) {
1738 else => unreachable,
1739 .div_trunc, .div_exact => res_ra,
1740 .div_floor => switch (int_info.signedness) {
1741 .signed => {
1742 const div_ra = try isel.allocIntReg();
1743 errdefer isel.freeReg(div_ra);
1744 const rem_ra = try isel.allocIntReg();
1745 defer isel.freeReg(rem_ra);
1746 switch (bits) {
1747 else => unreachable,
1748 1...32 => {
1749 try isel.emit(.sub(res_ra.w(), div_ra.w(), .{ .register = rem_ra.w() }));
1750 try isel.emit(.csinc(rem_ra.w(), .wzr, .wzr, .ge));
1751 try isel.emit(.ccmp(
1752 rem_ra.w(),
1753 .{ .immediate = 0 },
1754 .{ .n = false, .z = false, .c = false, .v = false },
1755 .ne,
1756 ));
1757 try isel.emit(.eor(rem_ra.w(), rem_ra.w(), .{ .register = rhs_mat.ra.w() }));
1758 try isel.emit(.subs(.wzr, rem_ra.w(), .{ .immediate = 0 }));
1759 try isel.emit(.msub(rem_ra.w(), div_ra.w(), rhs_mat.ra.w(), lhs_mat.ra.w()));
1760 },
1761 33...64 => {
1762 try isel.emit(.sub(res_ra.x(), div_ra.x(), .{ .register = rem_ra.x() }));
1763 try isel.emit(.csinc(rem_ra.x(), .xzr, .xzr, .ge));
1764 try isel.emit(.ccmp(
1765 rem_ra.x(),
1766 .{ .immediate = 0 },
1767 .{ .n = false, .z = false, .c = false, .v = false },
1768 .ne,
1769 ));
1770 try isel.emit(.eor(rem_ra.x(), rem_ra.x(), .{ .register = rhs_mat.ra.x() }));
1771 try isel.emit(.subs(.xzr, rem_ra.x(), .{ .immediate = 0 }));
1772 try isel.emit(.msub(rem_ra.x(), div_ra.x(), rhs_mat.ra.x(), lhs_mat.ra.x()));
1773 },
1774 }
1775 break :div_ra div_ra;
1776 },
1777 .unsigned => res_ra,
1778 },
1779 };
1780 defer if (div_ra != res_ra) isel.freeReg(div_ra);
1781 try isel.emit(switch (bits) {
1782 else => unreachable,
1783 1...32 => switch (int_info.signedness) {
1784 .signed => .sdiv(div_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w()),
1785 .unsigned => .udiv(div_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w()),
1786 },
1787 33...64 => switch (int_info.signedness) {
1788 .signed => .sdiv(div_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()),
1789 .unsigned => .udiv(div_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()),
1790 },
1791 });
1792 try rhs_mat.finish(isel);
1793 try lhs_mat.finish(isel);
1794 },
1795 65...128 => {
1796 switch (air_tag) {
1797 else => unreachable,
1798 .div_trunc, .div_exact => {},
1799 .div_floor => switch (int_info.signedness) {
1800 .signed => return isel.fail("unimplemented {s}", .{@tagName(air_tag)}),
1801 .unsigned => {},
1802 },
1803 }
1804
1805 try call.prepareReturn(isel);
1806 var res_hi64_it = res_vi.value.field(ty, 8, 8);
1807 const res_hi64_vi = try res_hi64_it.only(isel);
1808 try call.returnLiveIn(isel, res_hi64_vi.?, .r1);
1809 var res_lo64_it = res_vi.value.field(ty, 0, 8);
1810 const res_lo64_vi = try res_lo64_it.only(isel);
1811 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
1812 try call.finishReturn(isel);
1813
1814 try call.prepareCallee(isel);
1815 try isel.global_relocs.append(gpa, .{
1816 .global = switch (int_info.signedness) {
1817 .signed => "__divti3",
1818 .unsigned => "__udivti3",
1819 },
1820 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
1821 });
1822 try isel.emit(.bl(0));
1823 try call.finishCallee(isel);
1824
1825 try call.prepareParams(isel);
1826 const lhs_vi = try isel.use(bin_op.lhs);
1827 const rhs_vi = try isel.use(bin_op.rhs);
1828 var rhs_hi64_it = rhs_vi.field(ty, 8, 8);
1829 const rhs_hi64_vi = try rhs_hi64_it.only(isel);
1830 try call.paramLiveOut(isel, rhs_hi64_vi.?, .r3);
1831 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
1832 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
1833 try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2);
1834 var lhs_hi64_it = lhs_vi.field(ty, 8, 8);
1835 const lhs_hi64_vi = try lhs_hi64_it.only(isel);
1836 try call.paramLiveOut(isel, lhs_hi64_vi.?, .r1);
1837 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
1838 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
1839 try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0);
1840 try call.finishParams(isel);
1841 },
1842 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
1843 }
1844 } else switch (ty.floatBits(isel.target)) {
1845 else => unreachable,
1846 16, 32, 64 => |bits| {
1847 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1848 const need_fcvt = switch (bits) {
1849 else => unreachable,
1850 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
1851 32, 64 => false,
1852 };
1853 if (need_fcvt) try isel.emit(.fcvt(res_ra.h(), res_ra.s()));
1854 const lhs_vi = try isel.use(bin_op.lhs);
1855 const rhs_vi = try isel.use(bin_op.rhs);
1856 const lhs_mat = try lhs_vi.matReg(isel);
1857 const rhs_mat = try rhs_vi.matReg(isel);
1858 const lhs_ra = if (need_fcvt) try isel.allocVecReg() else lhs_mat.ra;
1859 defer if (need_fcvt) isel.freeReg(lhs_ra);
1860 const rhs_ra = if (need_fcvt) try isel.allocVecReg() else rhs_mat.ra;
1861 defer if (need_fcvt) isel.freeReg(rhs_ra);
1862 bits: switch (bits) {
1863 else => unreachable,
1864 16 => if (need_fcvt) continue :bits 32 else {
1865 switch (air_tag) {
1866 else => unreachable,
1867 .div_trunc, .div_trunc_optimized => try isel.emit(.frintz(res_ra.h(), res_ra.h())),
1868 .div_floor, .div_floor_optimized => try isel.emit(.frintm(res_ra.h(), res_ra.h())),
1869 .div_exact, .div_exact_optimized => {},
1870 }
1871 try isel.emit(.fdiv(res_ra.h(), lhs_ra.h(), rhs_ra.h()));
1872 },
1873 32 => {
1874 switch (air_tag) {
1875 else => unreachable,
1876 .div_trunc, .div_trunc_optimized => try isel.emit(.frintz(res_ra.s(), res_ra.s())),
1877 .div_floor, .div_floor_optimized => try isel.emit(.frintm(res_ra.s(), res_ra.s())),
1878 .div_exact, .div_exact_optimized => {},
1879 }
1880 try isel.emit(.fdiv(res_ra.s(), lhs_ra.s(), rhs_ra.s()));
1881 },
1882 64 => {
1883 switch (air_tag) {
1884 else => unreachable,
1885 .div_trunc, .div_trunc_optimized => try isel.emit(.frintz(res_ra.d(), res_ra.d())),
1886 .div_floor, .div_floor_optimized => try isel.emit(.frintm(res_ra.d(), res_ra.d())),
1887 .div_exact, .div_exact_optimized => {},
1888 }
1889 try isel.emit(.fdiv(res_ra.d(), lhs_ra.d(), rhs_ra.d()));
1890 },
1891 }
1892 if (need_fcvt) {
1893 try isel.emit(.fcvt(rhs_ra.s(), rhs_mat.ra.h()));
1894 try isel.emit(.fcvt(lhs_ra.s(), lhs_mat.ra.h()));
1895 }
1896 try rhs_mat.finish(isel);
1897 try lhs_mat.finish(isel);
1898 },
1899 80, 128 => |bits| {
1900 try call.prepareReturn(isel);
1901 switch (bits) {
1902 else => unreachable,
1903 16, 32, 64, 128 => try call.returnLiveIn(isel, res_vi.value, .v0),
1904 80 => {
1905 var res_hi16_it = res_vi.value.field(ty, 8, 8);
1906 const res_hi16_vi = try res_hi16_it.only(isel);
1907 try call.returnLiveIn(isel, res_hi16_vi.?, .r1);
1908 var res_lo64_it = res_vi.value.field(ty, 0, 8);
1909 const res_lo64_vi = try res_lo64_it.only(isel);
1910 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
1911 },
1912 }
1913 try call.finishReturn(isel);
1914
1915 try call.prepareCallee(isel);
1916 switch (air_tag) {
1917 else => unreachable,
1918 .div_trunc, .div_trunc_optimized => {
1919 try isel.global_relocs.append(gpa, .{
1920 .global = switch (bits) {
1921 else => unreachable,
1922 16 => "__trunch",
1923 32 => "truncf",
1924 64 => "trunc",
1925 80 => "__truncx",
1926 128 => "truncq",
1927 },
1928 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
1929 });
1930 try isel.emit(.bl(0));
1931 },
1932 .div_floor, .div_floor_optimized => {
1933 try isel.global_relocs.append(gpa, .{
1934 .global = switch (bits) {
1935 else => unreachable,
1936 16 => "__floorh",
1937 32 => "floorf",
1938 64 => "floor",
1939 80 => "__floorx",
1940 128 => "floorq",
1941 },
1942 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
1943 });
1944 try isel.emit(.bl(0));
1945 },
1946 .div_exact, .div_exact_optimized => {},
1947 }
1948 try isel.global_relocs.append(gpa, .{
1949 .global = switch (bits) {
1950 else => unreachable,
1951 16 => "__divhf3",
1952 32 => "__divsf3",
1953 64 => "__divdf3",
1954 80 => "__divxf3",
1955 128 => "__divtf3",
1956 },
1957 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
1958 });
1959 try isel.emit(.bl(0));
1960 try call.finishCallee(isel);
1961
1962 try call.prepareParams(isel);
1963 const lhs_vi = try isel.use(bin_op.lhs);
1964 const rhs_vi = try isel.use(bin_op.rhs);
1965 switch (bits) {
1966 else => unreachable,
1967 16, 32, 64, 128 => {
1968 try call.paramLiveOut(isel, rhs_vi, .v1);
1969 try call.paramLiveOut(isel, lhs_vi, .v0);
1970 },
1971 80 => {
1972 var rhs_hi16_it = rhs_vi.field(ty, 8, 8);
1973 const rhs_hi16_vi = try rhs_hi16_it.only(isel);
1974 try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3);
1975 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
1976 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
1977 try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2);
1978 var lhs_hi16_it = lhs_vi.field(ty, 8, 8);
1979 const lhs_hi16_vi = try lhs_hi16_it.only(isel);
1980 try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1);
1981 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
1982 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
1983 try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0);
1984 },
1985 }
1986 try call.finishParams(isel);
1987 },
1988 }
1989 }
1990 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
1991 },
1992 .rem => |air_tag| {
1993 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
1994 defer res_vi.value.deref(isel);
1995
1996 const bin_op = air.data(air.inst_index).bin_op;
1997 const ty = isel.air.typeOf(bin_op.lhs, ip);
1998 if (!ty.isRuntimeFloat()) {
1999 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
2000 const int_info = ty.intInfo(zcu);
2001 if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
2002
2003 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
2004 const lhs_vi = try isel.use(bin_op.lhs);
2005 const rhs_vi = try isel.use(bin_op.rhs);
2006 const lhs_mat = try lhs_vi.matReg(isel);
2007 const rhs_mat = try rhs_vi.matReg(isel);
2008 const div_ra = try isel.allocIntReg();
2009 defer isel.freeReg(div_ra);
2010 switch (int_info.bits) {
2011 else => unreachable,
2012 1...32 => {
2013 try isel.emit(.msub(res_ra.w(), div_ra.w(), rhs_mat.ra.w(), lhs_mat.ra.w()));
2014 try isel.emit(switch (int_info.signedness) {
2015 .signed => .sdiv(div_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w()),
2016 .unsigned => .udiv(div_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w()),
2017 });
2018 },
2019 33...64 => {
2020 try isel.emit(.msub(res_ra.x(), div_ra.x(), rhs_mat.ra.x(), lhs_mat.ra.x()));
2021 try isel.emit(switch (int_info.signedness) {
2022 .signed => .sdiv(div_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()),
2023 .unsigned => .udiv(div_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()),
2024 });
2025 },
2026 }
2027 try rhs_mat.finish(isel);
2028 try lhs_mat.finish(isel);
2029 } else {
2030 const bits = ty.floatBits(isel.target);
2031
2032 try call.prepareReturn(isel);
2033 switch (bits) {
2034 else => unreachable,
2035 16, 32, 64, 128 => try call.returnLiveIn(isel, res_vi.value, .v0),
2036 80 => {
2037 var res_hi16_it = res_vi.value.field(ty, 8, 8);
2038 const res_hi16_vi = try res_hi16_it.only(isel);
2039 try call.returnLiveIn(isel, res_hi16_vi.?, .r1);
2040 var res_lo64_it = res_vi.value.field(ty, 0, 8);
2041 const res_lo64_vi = try res_lo64_it.only(isel);
2042 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
2043 },
2044 }
2045 try call.finishReturn(isel);
2046
2047 try call.prepareCallee(isel);
2048 try isel.global_relocs.append(gpa, .{
2049 .global = switch (bits) {
2050 else => unreachable,
2051 16 => "__fmodh",
2052 32 => "fmodf",
2053 64 => "fmod",
2054 80 => "__fmodx",
2055 128 => "fmodq",
2056 },
2057 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
2058 });
2059 try isel.emit(.bl(0));
2060 try call.finishCallee(isel);
2061
2062 try call.prepareParams(isel);
2063 const lhs_vi = try isel.use(bin_op.lhs);
2064 const rhs_vi = try isel.use(bin_op.rhs);
2065 switch (bits) {
2066 else => unreachable,
2067 16, 32, 64, 128 => {
2068 try call.paramLiveOut(isel, rhs_vi, .v1);
2069 try call.paramLiveOut(isel, lhs_vi, .v0);
2070 },
2071 80 => {
2072 var rhs_hi16_it = rhs_vi.field(ty, 8, 8);
2073 const rhs_hi16_vi = try rhs_hi16_it.only(isel);
2074 try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3);
2075 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
2076 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
2077 try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2);
2078 var lhs_hi16_it = lhs_vi.field(ty, 8, 8);
2079 const lhs_hi16_vi = try lhs_hi16_it.only(isel);
2080 try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1);
2081 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
2082 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
2083 try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0);
2084 },
2085 }
2086 try call.finishParams(isel);
2087 }
2088 }
2089 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2090 },
2091 .ptr_add, .ptr_sub => |air_tag| {
2092 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
2093 defer res_vi.value.deref(isel);
2094 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
2095
2096 const ty_pl = air.data(air.inst_index).ty_pl;
2097 const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data;
2098 const elem_size = ty_pl.ty.toType().elemType2(zcu).abiSize(zcu);
2099
2100 const base_vi = try isel.use(bin_op.lhs);
2101 var base_part_it = base_vi.field(ty_pl.ty.toType(), 0, 8);
2102 const base_part_vi = try base_part_it.only(isel);
2103 const base_part_mat = try base_part_vi.?.matReg(isel);
2104 const index_vi = try isel.use(bin_op.rhs);
2105 try isel.elemPtr(res_ra, base_part_mat.ra, switch (air_tag) {
2106 else => unreachable,
2107 .ptr_add => .add,
2108 .ptr_sub => .sub,
2109 }, elem_size, index_vi);
2110 try base_part_mat.finish(isel);
2111 }
2112 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2113 },
2114 .max, .min => |air_tag| {
2115 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
2116 defer res_vi.value.deref(isel);
2117
2118 const bin_op = air.data(air.inst_index).bin_op;
2119 const ty = isel.air.typeOf(bin_op.lhs, ip);
2120 if (!ty.isRuntimeFloat()) {
2121 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
2122 const int_info = ty.intInfo(zcu);
2123 if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
2124
2125 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
2126 const lhs_vi = try isel.use(bin_op.lhs);
2127 const rhs_vi = try isel.use(bin_op.rhs);
2128 const lhs_mat = try lhs_vi.matReg(isel);
2129 const rhs_mat = try rhs_vi.matReg(isel);
2130 const cond: codegen.aarch64.encoding.ConditionCode = switch (air_tag) {
2131 else => unreachable,
2132 .max => switch (int_info.signedness) {
2133 .signed => .ge,
2134 .unsigned => .hs,
2135 },
2136 .min => switch (int_info.signedness) {
2137 .signed => .lt,
2138 .unsigned => .lo,
2139 },
2140 };
2141 switch (int_info.bits) {
2142 else => unreachable,
2143 1...32 => {
2144 try isel.emit(.csel(res_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w(), cond));
2145 try isel.emit(.subs(.wzr, lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
2146 },
2147 33...64 => {
2148 try isel.emit(.csel(res_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), cond));
2149 try isel.emit(.subs(.xzr, lhs_mat.ra.x(), .{ .register = rhs_mat.ra.x() }));
2150 },
2151 }
2152 try rhs_mat.finish(isel);
2153 try lhs_mat.finish(isel);
2154 } else switch (ty.floatBits(isel.target)) {
2155 else => unreachable,
2156 16, 32, 64 => |bits| {
2157 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
2158 const need_fcvt = switch (bits) {
2159 else => unreachable,
2160 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
2161 32, 64 => false,
2162 };
2163 if (need_fcvt) try isel.emit(.fcvt(res_ra.h(), res_ra.s()));
2164 const lhs_vi = try isel.use(bin_op.lhs);
2165 const rhs_vi = try isel.use(bin_op.rhs);
2166 const lhs_mat = try lhs_vi.matReg(isel);
2167 const rhs_mat = try rhs_vi.matReg(isel);
2168 const lhs_ra = if (need_fcvt) try isel.allocVecReg() else lhs_mat.ra;
2169 defer if (need_fcvt) isel.freeReg(lhs_ra);
2170 const rhs_ra = if (need_fcvt) try isel.allocVecReg() else rhs_mat.ra;
2171 defer if (need_fcvt) isel.freeReg(rhs_ra);
2172 try isel.emit(bits: switch (bits) {
2173 else => unreachable,
2174 16 => if (need_fcvt) continue :bits 32 else switch (air_tag) {
2175 else => unreachable,
2176 .max => .fmaxnm(res_ra.h(), lhs_ra.h(), rhs_ra.h()),
2177 .min => .fminnm(res_ra.h(), lhs_ra.h(), rhs_ra.h()),
2178 },
2179 32 => switch (air_tag) {
2180 else => unreachable,
2181 .max => .fmaxnm(res_ra.s(), lhs_ra.s(), rhs_ra.s()),
2182 .min => .fminnm(res_ra.s(), lhs_ra.s(), rhs_ra.s()),
2183 },
2184 64 => switch (air_tag) {
2185 else => unreachable,
2186 .max => .fmaxnm(res_ra.d(), lhs_ra.d(), rhs_ra.d()),
2187 .min => .fminnm(res_ra.d(), lhs_ra.d(), rhs_ra.d()),
2188 },
2189 });
2190 if (need_fcvt) {
2191 try isel.emit(.fcvt(rhs_ra.s(), rhs_mat.ra.h()));
2192 try isel.emit(.fcvt(lhs_ra.s(), lhs_mat.ra.h()));
2193 }
2194 try rhs_mat.finish(isel);
2195 try lhs_mat.finish(isel);
2196 },
2197 80, 128 => |bits| {
2198 try call.prepareReturn(isel);
2199 switch (bits) {
2200 else => unreachable,
2201 16, 32, 64, 128 => try call.returnLiveIn(isel, res_vi.value, .v0),
2202 80 => {
2203 var res_hi16_it = res_vi.value.field(ty, 8, 8);
2204 const res_hi16_vi = try res_hi16_it.only(isel);
2205 try call.returnLiveIn(isel, res_hi16_vi.?, .r1);
2206 var res_lo64_it = res_vi.value.field(ty, 0, 8);
2207 const res_lo64_vi = try res_lo64_it.only(isel);
2208 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
2209 },
2210 }
2211 try call.finishReturn(isel);
2212
2213 try call.prepareCallee(isel);
2214 try isel.global_relocs.append(gpa, .{
2215 .global = switch (air_tag) {
2216 else => unreachable,
2217 .max => switch (bits) {
2218 else => unreachable,
2219 16 => "__fmaxh",
2220 32 => "fmaxf",
2221 64 => "fmax",
2222 80 => "__fmaxx",
2223 128 => "fmaxq",
2224 },
2225 .min => switch (bits) {
2226 else => unreachable,
2227 16 => "__fminh",
2228 32 => "fminf",
2229 64 => "fmin",
2230 80 => "__fminx",
2231 128 => "fminq",
2232 },
2233 },
2234 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
2235 });
2236 try isel.emit(.bl(0));
2237 try call.finishCallee(isel);
2238
2239 try call.prepareParams(isel);
2240 const lhs_vi = try isel.use(bin_op.lhs);
2241 const rhs_vi = try isel.use(bin_op.rhs);
2242 switch (bits) {
2243 else => unreachable,
2244 16, 32, 64, 128 => {
2245 try call.paramLiveOut(isel, rhs_vi, .v1);
2246 try call.paramLiveOut(isel, lhs_vi, .v0);
2247 },
2248 80 => {
2249 var rhs_hi16_it = rhs_vi.field(ty, 8, 8);
2250 const rhs_hi16_vi = try rhs_hi16_it.only(isel);
2251 try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3);
2252 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
2253 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
2254 try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2);
2255 var lhs_hi16_it = lhs_vi.field(ty, 8, 8);
2256 const lhs_hi16_vi = try lhs_hi16_it.only(isel);
2257 try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1);
2258 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
2259 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
2260 try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0);
2261 },
2262 }
2263 try call.finishParams(isel);
2264 },
2265 }
2266 }
2267 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2268 },
2269 .add_with_overflow, .sub_with_overflow => |air_tag| {
2270 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| {
2271 defer res_vi.value.deref(isel);
2272
2273 const ty_pl = air.data(air.inst_index).ty_pl;
2274 const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data;
2275 const ty = isel.air.typeOf(bin_op.lhs, ip);
2276 const lhs_vi = try isel.use(bin_op.lhs);
2277 const rhs_vi = try isel.use(bin_op.rhs);
2278 const ty_size = lhs_vi.size(isel);
2279 var overflow_it = res_vi.value.field(ty_pl.ty.toType(), ty_size, 1);
2280 const overflow_vi = try overflow_it.only(isel);
2281 var wrapped_it = res_vi.value.field(ty_pl.ty.toType(), 0, ty_size);
2282 const wrapped_vi = try wrapped_it.only(isel);
2283 try wrapped_vi.?.addOrSubtract(isel, ty, lhs_vi, switch (air_tag) {
2284 else => unreachable,
2285 .add_with_overflow => .add,
2286 .sub_with_overflow => .sub,
2287 }, rhs_vi, .{ .wrap = true, .overflow_ra = try overflow_vi.?.defReg(isel) orelse .zr });
2288 }
2289 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2290 },
2291 .alloc, .ret_ptr => |air_tag| {
2292 if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: {
2293 defer ptr_vi.value.deref(isel);
2294 switch (air_tag) {
2295 else => unreachable,
2296 .alloc => {},
2297 .ret_ptr => if (isel.live_values.get(Block.main)) |ret_vi| switch (ret_vi.parent(isel)) {
2298 .unallocated, .stack_slot => {},
2299 .value, .constant => unreachable,
2300 .address => break :unused,
2301 },
2302 }
2303 const ptr_ra = try ptr_vi.value.defReg(isel) orelse break :unused;
2304
2305 const ty = air.data(air.inst_index).ty;
2306 const slot_size = ty.childType(zcu).abiSize(zcu);
2307 const slot_align = ty.ptrAlignment(zcu);
2308 const slot_offset = slot_align.forward(isel.stack_size);
2309 isel.stack_size = @intCast(slot_offset + slot_size);
2310 const lo12: u12 = @truncate(slot_offset >> 0);
2311 const hi12: u12 = @intCast(slot_offset >> 12);
2312 if (hi12 > 0) try isel.emit(.add(
2313 ptr_ra.x(),
2314 if (lo12 > 0) ptr_ra.x() else .sp,
2315 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
2316 ));
2317 if (lo12 > 0 or hi12 == 0) try isel.emit(.add(ptr_ra.x(), .sp, .{ .immediate = lo12 }));
2318 }
2319 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2320 },
2321 .assembly => {
2322 const ty_pl = air.data(air.inst_index).ty_pl;
2323 const extra = isel.air.extraData(Air.Asm, ty_pl.payload);
2324 var extra_index = extra.end;
2325 const outputs: []const Air.Inst.Ref = @ptrCast(isel.air.extra.items[extra_index..][0..extra.data.flags.outputs_len]);
2326 extra_index += outputs.len;
2327 const inputs: []const Air.Inst.Ref = @ptrCast(isel.air.extra.items[extra_index..][0..extra.data.inputs_len]);
2328 extra_index += inputs.len;
2329
2330 var as: codegen.aarch64.Assemble = .{
2331 .source = undefined,
2332 .operands = .empty,
2333 };
2334 defer as.operands.deinit(gpa);
2335
2336 for (outputs) |output| {
2337 const extra_bytes = std.mem.sliceAsBytes(isel.air.extra.items[extra_index..]);
2338 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(isel.air.extra.items[extra_index..]), 0);
2339 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
2340 // This equation accounts for the fact that even if we have exactly 4 bytes
2341 // for the string, we still use the next u32 for the null terminator.
2342 extra_index += (constraint.len + name.len + (2 + 3)) / 4;
2343
2344 switch (output) {
2345 else => return isel.fail("invalid constraint: '{s}'", .{constraint}),
2346 .none => if (std.mem.startsWith(u8, constraint, "={") and std.mem.endsWith(u8, constraint, "}")) {
2347 const output_reg = Register.parse(constraint["={".len .. constraint.len - "}".len]) orelse
2348 return isel.fail("invalid constraint: '{s}'", .{constraint});
2349 const output_ra = output_reg.alias;
2350 if (isel.live_values.fetchRemove(air.inst_index)) |output_vi| {
2351 defer output_vi.value.deref(isel);
2352 try output_vi.value.defLiveIn(isel, output_reg.alias, comptime &.initFill(.free));
2353 isel.freeReg(output_ra);
2354 }
2355 if (!std.mem.eql(u8, name, "_")) {
2356 const operand_gop = try as.operands.getOrPut(gpa, name);
2357 if (operand_gop.found_existing) return isel.fail("duplicate output name: '{s}'", .{name});
2358 operand_gop.value_ptr.* = .{ .register = switch (ty_pl.ty.toType().abiSize(zcu)) {
2359 0 => unreachable,
2360 1...4 => output_ra.w(),
2361 5...8 => output_ra.x(),
2362 else => return isel.fail("too big output type: '{f}'", .{isel.fmtType(ty_pl.ty.toType())}),
2363 } };
2364 }
2365 } else if (std.mem.eql(u8, constraint, "=r")) {
2366 const output_ra = if (isel.live_values.fetchRemove(air.inst_index)) |output_vi| output_ra: {
2367 defer output_vi.value.deref(isel);
2368 break :output_ra try output_vi.value.defReg(isel) orelse try isel.allocIntReg();
2369 } else try isel.allocIntReg();
2370 if (!std.mem.eql(u8, name, "_")) {
2371 const operand_gop = try as.operands.getOrPut(gpa, name);
2372 if (operand_gop.found_existing) return isel.fail("duplicate output name: '{s}'", .{name});
2373 operand_gop.value_ptr.* = .{ .register = switch (ty_pl.ty.toType().abiSize(zcu)) {
2374 0 => unreachable,
2375 1...4 => output_ra.w(),
2376 5...8 => output_ra.x(),
2377 else => return isel.fail("too big output type: '{f}'", .{isel.fmtType(ty_pl.ty.toType())}),
2378 } };
2379 }
2380 } else return isel.fail("invalid constraint: '{s}'", .{constraint}),
2381 }
2382 }
2383
2384 const input_mats = try gpa.alloc(Value.Materialize, inputs.len);
2385 defer gpa.free(input_mats);
2386 const inputs_extra_index = extra_index;
2387 for (inputs, input_mats) |input, *input_mat| {
2388 const extra_bytes = std.mem.sliceAsBytes(isel.air.extra.items[extra_index..]);
2389 const constraint = std.mem.sliceTo(extra_bytes, 0);
2390 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
2391 // This equation accounts for the fact that even if we have exactly 4 bytes
2392 // for the string, we still use the next u32 for the null terminator.
2393 extra_index += (constraint.len + name.len + (2 + 3)) / 4;
2394
2395 if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) {
2396 const input_reg = Register.parse(constraint["{".len .. constraint.len - "}".len]) orelse
2397 return isel.fail("invalid constraint: '{s}'", .{constraint});
2398 input_mat.* = .{ .vi = try isel.use(input), .ra = input_reg.alias };
2399 if (!std.mem.eql(u8, name, "_")) {
2400 const operand_gop = try as.operands.getOrPut(gpa, name);
2401 if (operand_gop.found_existing) return isel.fail("duplicate input name: '{s}'", .{name});
2402 const input_ty = isel.air.typeOf(input, ip);
2403 operand_gop.value_ptr.* = .{ .register = switch (input_ty.abiSize(zcu)) {
2404 0 => unreachable,
2405 1...4 => input_reg.alias.w(),
2406 5...8 => input_reg.alias.x(),
2407 else => return isel.fail("too big input type: '{f}'", .{
2408 isel.fmtType(isel.air.typeOf(input, ip)),
2409 }),
2410 } };
2411 }
2412 } else if (std.mem.eql(u8, constraint, "r")) {
2413 const input_vi = try isel.use(input);
2414 input_mat.* = try input_vi.matReg(isel);
2415 if (!std.mem.eql(u8, name, "_")) {
2416 const operand_gop = try as.operands.getOrPut(gpa, name);
2417 if (operand_gop.found_existing) return isel.fail("duplicate input name: '{s}'", .{name});
2418 operand_gop.value_ptr.* = .{ .register = switch (input_vi.size(isel)) {
2419 0 => unreachable,
2420 1...4 => input_mat.ra.w(),
2421 5...8 => input_mat.ra.x(),
2422 else => return isel.fail("too big input type: '{f}'", .{
2423 isel.fmtType(isel.air.typeOf(input, ip)),
2424 }),
2425 } };
2426 }
2427 } else if (std.mem.eql(u8, name, "_")) {
2428 input_mat.vi = try isel.use(input);
2429 } else return isel.fail("invalid constraint: '{s}'", .{constraint});
2430 }
2431
2432 const clobbers = ip.indexToKey(extra.data.clobbers).aggregate;
2433 const clobbers_ty: ZigType = .fromInterned(clobbers.ty);
2434 for (0..clobbers_ty.structFieldCount(zcu)) |field_index| {
2435 switch (switch (clobbers.storage) {
2436 .bytes => unreachable,
2437 .elems => |elems| elems[field_index],
2438 .repeated_elem => |repeated_elem| repeated_elem,
2439 }) {
2440 else => unreachable,
2441 .bool_false => continue,
2442 .bool_true => {},
2443 }
2444 const clobber_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?;
2445 if (std.mem.eql(u8, clobber_name, "memory")) continue;
2446 if (std.mem.eql(u8, clobber_name, "nzcv")) continue;
2447 const clobber_reg = Register.parse(clobber_name) orelse
2448 return isel.fail("unable to parse clobber: '{s}'", .{clobber_name});
2449 const live_vi = isel.live_registers.getPtr(clobber_reg.alias);
2450 switch (live_vi.*) {
2451 _ => {},
2452 .allocating => return isel.fail("clobbered twice: '{s}'", .{clobber_name}),
2453 .free => live_vi.* = .allocating,
2454 }
2455 }
2456 for (0..clobbers_ty.structFieldCount(zcu)) |field_index| {
2457 switch (switch (clobbers.storage) {
2458 .bytes => unreachable,
2459 .elems => |elems| elems[field_index],
2460 .repeated_elem => |repeated_elem| repeated_elem,
2461 }) {
2462 else => unreachable,
2463 .bool_false => continue,
2464 .bool_true => {},
2465 }
2466 const clobber_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?;
2467 if (std.mem.eql(u8, clobber_name, "memory")) continue;
2468 if (std.mem.eql(u8, clobber_name, "nzcv")) continue;
2469 const clobber_ra = Register.parse(clobber_name).?.alias;
2470 const live_vi = isel.live_registers.getPtr(clobber_ra);
2471 switch (live_vi.*) {
2472 _ => {
2473 if (!try isel.fill(clobber_ra))
2474 return isel.fail("unable to clobber: '{s}'", .{clobber_name});
2475 assert(live_vi.* == .free);
2476 live_vi.* = .allocating;
2477 },
2478 .allocating => {},
2479 .free => unreachable,
2480 }
2481 }
2482
2483 as.source = std.mem.sliceAsBytes(isel.air.extra.items[extra_index..])[0..extra.data.source_len :0];
2484 const asm_start = isel.instructions.items.len;
2485 while (as.nextInstruction() catch |err| switch (err) {
2486 error.InvalidSyntax => {
2487 const remaining_source = std.mem.span(as.source);
2488 return isel.fail("unable to assemble: '{s}'", .{std.mem.trim(
2489 u8,
2490 as.source[0 .. std.mem.indexOfScalar(u8, remaining_source, '\n') orelse remaining_source.len],
2491 &std.ascii.whitespace,
2492 )});
2493 },
2494 }) |instruction| try isel.emit(instruction);
2495 std.mem.reverse(codegen.aarch64.encoding.Instruction, isel.instructions.items[asm_start..]);
2496
2497 extra_index = inputs_extra_index;
2498 for (input_mats) |input_mat| {
2499 const extra_bytes = std.mem.sliceAsBytes(isel.air.extra.items[extra_index..]);
2500 const constraint = std.mem.sliceTo(extra_bytes, 0);
2501 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
2502 // This equation accounts for the fact that even if we have exactly 4 bytes
2503 // for the string, we still use the next u32 for the null terminator.
2504 extra_index += (constraint.len + name.len + (2 + 3)) / 4;
2505
2506 if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) {
2507 try input_mat.vi.liveOut(isel, input_mat.ra);
2508 } else if (std.mem.eql(u8, constraint, "r")) {
2509 try input_mat.finish(isel);
2510 } else if (std.mem.eql(u8, name, "_")) {
2511 try input_mat.vi.mat(isel);
2512 } else unreachable;
2513 }
2514
2515 for (0..clobbers_ty.structFieldCount(zcu)) |field_index| {
2516 switch (switch (clobbers.storage) {
2517 .bytes => unreachable,
2518 .elems => |elems| elems[field_index],
2519 .repeated_elem => |repeated_elem| repeated_elem,
2520 }) {
2521 else => unreachable,
2522 .bool_false => continue,
2523 .bool_true => {},
2524 }
2525 const clobber_name = clobbers_ty.structFieldName(field_index, zcu).toSlice(ip).?;
2526 if (std.mem.eql(u8, clobber_name, "memory")) continue;
2527 if (std.mem.eql(u8, clobber_name, "cc")) continue;
2528 isel.freeReg(Register.parse(clobber_name).?.alias);
2529 }
2530
2531 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2532 },
2533 .bit_and, .bit_or, .xor, .bool_and, .bool_or => |air_tag| {
2534 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| {
2535 defer res_vi.value.deref(isel);
2536
2537 const bin_op = air.data(air.inst_index).bin_op;
2538 const ty = isel.air.typeOf(bin_op.lhs, ip);
2539 const int_info: std.builtin.Type.Int = if (ty.toIntern() == .bool_type)
2540 .{ .signedness = .unsigned, .bits = 1 }
2541 else if (ty.isAbiInt(zcu))
2542 ty.intInfo(zcu)
2543 else
2544 return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
2545 if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
2546
2547 const lhs_vi = try isel.use(bin_op.lhs);
2548 const rhs_vi = try isel.use(bin_op.rhs);
2549 var offset = res_vi.value.size(isel);
2550 while (offset > 0) {
2551 const size = @min(offset, 8);
2552 offset -= size;
2553 var res_part_it = res_vi.value.field(ty, offset, size);
2554 const res_part_vi = try res_part_it.only(isel);
2555 const res_part_ra = try res_part_vi.?.defReg(isel) orelse continue;
2556 var lhs_part_it = lhs_vi.field(ty, offset, size);
2557 const lhs_part_vi = try lhs_part_it.only(isel);
2558 const lhs_part_mat = try lhs_part_vi.?.matReg(isel);
2559 var rhs_part_it = rhs_vi.field(ty, offset, size);
2560 const rhs_part_vi = try rhs_part_it.only(isel);
2561 const rhs_part_mat = try rhs_part_vi.?.matReg(isel);
2562 try isel.emit(switch (air_tag) {
2563 else => unreachable,
2564 .bit_and, .bool_and => switch (size) {
2565 else => unreachable,
2566 1, 2, 4 => .@"and"(res_part_ra.w(), lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }),
2567 8 => .@"and"(res_part_ra.x(), lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }),
2568 },
2569 .bit_or, .bool_or => switch (size) {
2570 else => unreachable,
2571 1, 2, 4 => .orr(res_part_ra.w(), lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }),
2572 8 => .orr(res_part_ra.x(), lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }),
2573 },
2574 .xor => switch (size) {
2575 else => unreachable,
2576 1, 2, 4 => .eor(res_part_ra.w(), lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }),
2577 8 => .eor(res_part_ra.x(), lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }),
2578 },
2579 });
2580 try rhs_part_mat.finish(isel);
2581 try lhs_part_mat.finish(isel);
2582 }
2583 }
2584 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2585 },
2586 .shr, .shr_exact, .shl, .shl_exact => |air_tag| {
2587 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
2588 defer res_vi.value.deref(isel);
2589
2590 const bin_op = air.data(air.inst_index).bin_op;
2591 const ty = isel.air.typeOf(bin_op.lhs, ip);
2592 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
2593 const int_info = ty.intInfo(zcu);
2594 switch (int_info.bits) {
2595 0 => unreachable,
2596 1...64 => |bits| {
2597 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
2598 switch (air_tag) {
2599 else => unreachable,
2600 .shr, .shr_exact, .shl_exact => {},
2601 .shl => switch (bits) {
2602 else => unreachable,
2603 1...31 => try isel.emit(switch (int_info.signedness) {
2604 .signed => .sbfm(res_ra.w(), res_ra.w(), .{
2605 .N = .word,
2606 .immr = 0,
2607 .imms = @intCast(bits - 1),
2608 }),
2609 .unsigned => .ubfm(res_ra.w(), res_ra.w(), .{
2610 .N = .word,
2611 .immr = 0,
2612 .imms = @intCast(bits - 1),
2613 }),
2614 }),
2615 32 => {},
2616 33...63 => try isel.emit(switch (int_info.signedness) {
2617 .signed => .sbfm(res_ra.x(), res_ra.x(), .{
2618 .N = .doubleword,
2619 .immr = 0,
2620 .imms = @intCast(bits - 1),
2621 }),
2622 .unsigned => .ubfm(res_ra.x(), res_ra.x(), .{
2623 .N = .doubleword,
2624 .immr = 0,
2625 .imms = @intCast(bits - 1),
2626 }),
2627 }),
2628 64 => {},
2629 },
2630 }
2631
2632 const lhs_vi = try isel.use(bin_op.lhs);
2633 const rhs_vi = try isel.use(bin_op.rhs);
2634 const lhs_mat = try lhs_vi.matReg(isel);
2635 const rhs_mat = try rhs_vi.matReg(isel);
2636 try isel.emit(switch (air_tag) {
2637 else => unreachable,
2638 .shr, .shr_exact => switch (bits) {
2639 else => unreachable,
2640 1...32 => switch (int_info.signedness) {
2641 .signed => .asrv(res_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w()),
2642 .unsigned => .lsrv(res_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w()),
2643 },
2644 33...64 => switch (int_info.signedness) {
2645 .signed => .asrv(res_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()),
2646 .unsigned => .lsrv(res_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()),
2647 },
2648 },
2649 .shl, .shl_exact => switch (bits) {
2650 else => unreachable,
2651 1...32 => .lslv(res_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w()),
2652 33...64 => .lslv(res_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()),
2653 },
2654 });
2655 try rhs_mat.finish(isel);
2656 try lhs_mat.finish(isel);
2657 },
2658 65...128 => |bits| {
2659 var res_hi64_it = res_vi.value.field(ty, 8, 8);
2660 const res_hi64_vi = try res_hi64_it.only(isel);
2661 const res_hi64_ra = try res_hi64_vi.?.defReg(isel);
2662 var res_lo64_it = res_vi.value.field(ty, 0, 8);
2663 const res_lo64_vi = try res_lo64_it.only(isel);
2664 const res_lo64_ra = try res_lo64_vi.?.defReg(isel);
2665 if (res_hi64_ra == null and res_lo64_ra == null) break :unused;
2666 if (res_hi64_ra) |res_ra| switch (air_tag) {
2667 else => unreachable,
2668 .shr, .shr_exact, .shl_exact => {},
2669 .shl => switch (bits) {
2670 else => unreachable,
2671 65...127 => try isel.emit(switch (int_info.signedness) {
2672 .signed => .sbfm(res_ra.x(), res_ra.x(), .{
2673 .N = .doubleword,
2674 .immr = 0,
2675 .imms = @intCast(bits - 64 - 1),
2676 }),
2677 .unsigned => .ubfm(res_ra.x(), res_ra.x(), .{
2678 .N = .doubleword,
2679 .immr = 0,
2680 .imms = @intCast(bits - 64 - 1),
2681 }),
2682 }),
2683 128 => {},
2684 },
2685 };
2686
2687 const lhs_vi = try isel.use(bin_op.lhs);
2688 const lhs_hi64_mat = lhs_hi64_mat: {
2689 const res_lock: RegLock = switch (air_tag) {
2690 else => unreachable,
2691 .shr, .shr_exact => switch (int_info.signedness) {
2692 .signed => if (res_lo64_ra) |res_ra| isel.lockReg(res_ra) else .empty,
2693 .unsigned => .empty,
2694 },
2695 .shl, .shl_exact => .empty,
2696 };
2697 defer res_lock.unlock(isel);
2698 var lhs_hi64_it = lhs_vi.field(ty, 8, 8);
2699 const lhs_hi64_vi = try lhs_hi64_it.only(isel);
2700 break :lhs_hi64_mat try lhs_hi64_vi.?.matReg(isel);
2701 };
2702 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
2703 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
2704 const lhs_lo64_mat = try lhs_lo64_vi.?.matReg(isel);
2705 const rhs_vi = try isel.use(bin_op.rhs);
2706 const rhs_mat = try rhs_vi.matReg(isel);
2707 const lo64_ra = lo64_ra: {
2708 const res_lock: RegLock = switch (air_tag) {
2709 else => unreachable,
2710 .shr, .shr_exact => switch (int_info.signedness) {
2711 .signed => if (res_lo64_ra) |res_ra| isel.tryLockReg(res_ra) else .empty,
2712 .unsigned => .empty,
2713 },
2714 .shl, .shl_exact => if (res_hi64_ra) |res_ra| isel.tryLockReg(res_ra) else .empty,
2715 };
2716 defer res_lock.unlock(isel);
2717 break :lo64_ra try isel.allocIntReg();
2718 };
2719 defer isel.freeReg(lo64_ra);
2720 const hi64_ra = hi64_ra: {
2721 const res_lock: RegLock = switch (air_tag) {
2722 else => unreachable,
2723 .shr, .shr_exact => if (res_lo64_ra) |res_ra| isel.tryLockReg(res_ra) else .empty,
2724 .shl, .shl_exact => .empty,
2725 };
2726 defer res_lock.unlock(isel);
2727 break :hi64_ra try isel.allocIntReg();
2728 };
2729 defer isel.freeReg(hi64_ra);
2730 switch (air_tag) {
2731 else => unreachable,
2732 .shr, .shr_exact => {
2733 if (res_hi64_ra) |res_ra| switch (int_info.signedness) {
2734 .signed => {
2735 try isel.emit(.csel(res_ra.x(), hi64_ra.x(), lo64_ra.x(), .eq));
2736 try isel.emit(.sbfm(lo64_ra.x(), lhs_hi64_mat.ra.x(), .{
2737 .N = .doubleword,
2738 .immr = @intCast(bits - 64 - 1),
2739 .imms = @intCast(bits - 64 - 1),
2740 }));
2741 },
2742 .unsigned => try isel.emit(.csel(res_ra.x(), hi64_ra.x(), .xzr, .eq)),
2743 };
2744 if (res_lo64_ra) |res_ra| try isel.emit(.csel(res_ra.x(), lo64_ra.x(), hi64_ra.x(), .eq));
2745 switch (int_info.signedness) {
2746 .signed => try isel.emit(.asrv(hi64_ra.x(), lhs_hi64_mat.ra.x(), rhs_mat.ra.x())),
2747 .unsigned => try isel.emit(.lsrv(hi64_ra.x(), lhs_hi64_mat.ra.x(), rhs_mat.ra.x())),
2748 }
2749 },
2750 .shl, .shl_exact => {
2751 if (res_lo64_ra) |res_ra| try isel.emit(.csel(res_ra.x(), lo64_ra.x(), .xzr, .eq));
2752 if (res_hi64_ra) |res_ra| try isel.emit(.csel(res_ra.x(), hi64_ra.x(), lo64_ra.x(), .eq));
2753 try isel.emit(.lslv(lo64_ra.x(), lhs_lo64_mat.ra.x(), rhs_mat.ra.x()));
2754 },
2755 }
2756 try isel.emit(.ands(.wzr, rhs_mat.ra.w(), .{ .immediate = .{ .N = .word, .immr = 32 - 6, .imms = 0 } }));
2757 switch (air_tag) {
2758 else => unreachable,
2759 .shr, .shr_exact => if (res_lo64_ra) |_| {
2760 try isel.emit(.orr(
2761 lo64_ra.x(),
2762 lo64_ra.x(),
2763 .{ .shifted_register = .{ .register = hi64_ra.x(), .shift = .{ .lsl = 1 } } },
2764 ));
2765 try isel.emit(.lslv(hi64_ra.x(), lhs_hi64_mat.ra.x(), hi64_ra.x()));
2766 try isel.emit(.lsrv(lo64_ra.x(), lhs_lo64_mat.ra.x(), rhs_mat.ra.x()));
2767 try isel.emit(.orn(hi64_ra.w(), .wzr, .{ .register = rhs_mat.ra.w() }));
2768 },
2769 .shl, .shl_exact => if (res_hi64_ra) |_| {
2770 try isel.emit(.orr(
2771 hi64_ra.x(),
2772 hi64_ra.x(),
2773 .{ .shifted_register = .{ .register = lo64_ra.x(), .shift = .{ .lsr = 1 } } },
2774 ));
2775 try isel.emit(.lsrv(lo64_ra.x(), lhs_lo64_mat.ra.x(), lo64_ra.x()));
2776 try isel.emit(.lslv(hi64_ra.x(), lhs_hi64_mat.ra.x(), rhs_mat.ra.x()));
2777 try isel.emit(.orn(lo64_ra.w(), .wzr, .{ .register = rhs_mat.ra.w() }));
2778 },
2779 }
2780 try rhs_mat.finish(isel);
2781 try lhs_lo64_mat.finish(isel);
2782 try lhs_hi64_mat.finish(isel);
2783 break :unused;
2784 },
2785 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
2786 }
2787 }
2788 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2789 },
2790 .not => |air_tag| {
2791 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| {
2792 defer res_vi.value.deref(isel);
2793
2794 const ty_op = air.data(air.inst_index).ty_op;
2795 const ty = ty_op.ty.toType();
2796 const int_info: std.builtin.Type.Int = int_info: {
2797 if (ty_op.ty == .bool_type) break :int_info .{ .signedness = .unsigned, .bits = 1 };
2798 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
2799 break :int_info ty.intInfo(zcu);
2800 };
2801 if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
2802
2803 const src_vi = try isel.use(ty_op.operand);
2804 var offset = res_vi.value.size(isel);
2805 while (offset > 0) {
2806 const size = @min(offset, 8);
2807 offset -= size;
2808 var res_part_it = res_vi.value.field(ty, offset, size);
2809 const res_part_vi = try res_part_it.only(isel);
2810 const res_part_ra = try res_part_vi.?.defReg(isel) orelse continue;
2811 var src_part_it = src_vi.field(ty, offset, size);
2812 const src_part_vi = try src_part_it.only(isel);
2813 const src_part_mat = try src_part_vi.?.matReg(isel);
2814 try isel.emit(switch (int_info.signedness) {
2815 .signed => switch (size) {
2816 else => unreachable,
2817 1, 2, 4 => .orn(res_part_ra.w(), .wzr, .{ .register = src_part_mat.ra.w() }),
2818 8 => .orn(res_part_ra.x(), .xzr, .{ .register = src_part_mat.ra.x() }),
2819 },
2820 .unsigned => switch (@min(int_info.bits - 8 * offset, 64)) {
2821 else => unreachable,
2822 1...31 => |bits| .eor(res_part_ra.w(), src_part_mat.ra.w(), .{ .immediate = .{
2823 .N = .word,
2824 .immr = 0,
2825 .imms = @intCast(bits - 1),
2826 } }),
2827 32 => .orn(res_part_ra.w(), .wzr, .{ .register = src_part_mat.ra.w() }),
2828 33...63 => |bits| .eor(res_part_ra.x(), src_part_mat.ra.x(), .{ .immediate = .{
2829 .N = .doubleword,
2830 .immr = 0,
2831 .imms = @intCast(bits - 1),
2832 } }),
2833 64 => .orn(res_part_ra.x(), .xzr, .{ .register = src_part_mat.ra.x() }),
2834 },
2835 });
2836 try src_part_mat.finish(isel);
2837 }
2838 }
2839 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2840 },
2841 .bitcast => |air_tag| {
2842 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
2843 defer dst_vi.value.deref(isel);
2844 const ty_op = air.data(air.inst_index).ty_op;
2845 const dst_ty = ty_op.ty.toType();
2846 const dst_tag = dst_ty.zigTypeTag(zcu);
2847 const src_ty = isel.air.typeOf(ty_op.operand, ip);
2848 const src_tag = src_ty.zigTypeTag(zcu);
2849 if (dst_ty.isAbiInt(zcu) and (src_tag == .bool or src_ty.isAbiInt(zcu))) {
2850 const dst_int_info = dst_ty.intInfo(zcu);
2851 const src_int_info: std.builtin.Type.Int = if (src_tag == .bool) .{ .signedness = undefined, .bits = 1 } else src_ty.intInfo(zcu);
2852 assert(dst_int_info.bits == src_int_info.bits);
2853 if (dst_tag != .@"struct" and src_tag != .@"struct" and src_tag != .bool and dst_int_info.signedness == src_int_info.signedness) {
2854 try dst_vi.value.move(isel, ty_op.operand);
2855 } else switch (dst_int_info.bits) {
2856 0 => unreachable,
2857 1...31 => |dst_bits| {
2858 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
2859 const src_vi = try isel.use(ty_op.operand);
2860 const src_mat = try src_vi.matReg(isel);
2861 try isel.emit(switch (dst_int_info.signedness) {
2862 .signed => .sbfm(dst_ra.w(), src_mat.ra.w(), .{
2863 .N = .word,
2864 .immr = 0,
2865 .imms = @intCast(dst_bits - 1),
2866 }),
2867 .unsigned => .ubfm(dst_ra.w(), src_mat.ra.w(), .{
2868 .N = .word,
2869 .immr = 0,
2870 .imms = @intCast(dst_bits - 1),
2871 }),
2872 });
2873 try src_mat.finish(isel);
2874 },
2875 32 => try dst_vi.value.move(isel, ty_op.operand),
2876 33...63 => |dst_bits| {
2877 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
2878 const src_vi = try isel.use(ty_op.operand);
2879 const src_mat = try src_vi.matReg(isel);
2880 try isel.emit(switch (dst_int_info.signedness) {
2881 .signed => .sbfm(dst_ra.x(), src_mat.ra.x(), .{
2882 .N = .doubleword,
2883 .immr = 0,
2884 .imms = @intCast(dst_bits - 1),
2885 }),
2886 .unsigned => .ubfm(dst_ra.x(), src_mat.ra.x(), .{
2887 .N = .doubleword,
2888 .immr = 0,
2889 .imms = @intCast(dst_bits - 1),
2890 }),
2891 });
2892 try src_mat.finish(isel);
2893 },
2894 64 => try dst_vi.value.move(isel, ty_op.operand),
2895 65...127 => |dst_bits| {
2896 const src_vi = try isel.use(ty_op.operand);
2897 var dst_hi64_it = dst_vi.value.field(dst_ty, 8, 8);
2898 const dst_hi64_vi = try dst_hi64_it.only(isel);
2899 if (try dst_hi64_vi.?.defReg(isel)) |dst_hi64_ra| {
2900 var src_hi64_it = src_vi.field(src_ty, 8, 8);
2901 const src_hi64_vi = try src_hi64_it.only(isel);
2902 const src_hi64_mat = try src_hi64_vi.?.matReg(isel);
2903 try isel.emit(switch (dst_int_info.signedness) {
2904 .signed => .sbfm(dst_hi64_ra.x(), src_hi64_mat.ra.x(), .{
2905 .N = .doubleword,
2906 .immr = 0,
2907 .imms = @intCast(dst_bits - 64 - 1),
2908 }),
2909 .unsigned => .ubfm(dst_hi64_ra.x(), src_hi64_mat.ra.x(), .{
2910 .N = .doubleword,
2911 .immr = 0,
2912 .imms = @intCast(dst_bits - 64 - 1),
2913 }),
2914 });
2915 try src_hi64_mat.finish(isel);
2916 }
2917 var dst_lo64_it = dst_vi.value.field(dst_ty, 0, 8);
2918 const dst_lo64_vi = try dst_lo64_it.only(isel);
2919 if (try dst_lo64_vi.?.defReg(isel)) |dst_lo64_ra| {
2920 var src_lo64_it = src_vi.field(src_ty, 0, 8);
2921 const src_lo64_vi = try src_lo64_it.only(isel);
2922 try src_lo64_vi.?.liveOut(isel, dst_lo64_ra);
2923 }
2924 },
2925 128 => try dst_vi.value.move(isel, ty_op.operand),
2926 else => return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }),
2927 }
2928 } else if ((dst_ty.isPtrAtRuntime(zcu) or dst_ty.isAbiInt(zcu)) and (src_ty.isPtrAtRuntime(zcu) or src_ty.isAbiInt(zcu))) {
2929 try dst_vi.value.move(isel, ty_op.operand);
2930 } else if (dst_ty.isSliceAtRuntime(zcu) and src_ty.isSliceAtRuntime(zcu)) {
2931 try dst_vi.value.move(isel, ty_op.operand);
2932 } else if (dst_tag == .error_union and src_tag == .error_union) {
2933 assert(dst_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu) ==
2934 src_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu));
2935 if (dst_ty.errorUnionPayload(zcu).toIntern() == src_ty.errorUnionPayload(zcu).toIntern()) {
2936 try dst_vi.value.move(isel, ty_op.operand);
2937 } else return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
2938 } else if (dst_tag == .float and src_tag == .float) {
2939 assert(dst_ty.floatBits(isel.target) == src_ty.floatBits(isel.target));
2940 try dst_vi.value.move(isel, ty_op.operand);
2941 } else if (dst_ty.isAbiInt(zcu) and src_tag == .float) {
2942 const dst_int_info = dst_ty.intInfo(zcu);
2943 assert(dst_int_info.bits == src_ty.floatBits(isel.target));
2944 switch (dst_int_info.bits) {
2945 else => unreachable,
2946 16 => {
2947 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
2948 const src_vi = try isel.use(ty_op.operand);
2949 const src_mat = try src_vi.matReg(isel);
2950 switch (dst_int_info.signedness) {
2951 .signed => try isel.emit(.smov(dst_ra.w(), src_mat.ra.@"h[]"(0))),
2952 .unsigned => try isel.emit(if (isel.target.cpu.has(.aarch64, .fullfp16))
2953 .fmov(dst_ra.w(), .{ .register = src_mat.ra.h() })
2954 else
2955 .umov(dst_ra.w(), src_mat.ra.@"h[]"(0))),
2956 }
2957 try src_mat.finish(isel);
2958 },
2959 32 => {
2960 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
2961 const src_vi = try isel.use(ty_op.operand);
2962 const src_mat = try src_vi.matReg(isel);
2963 try isel.emit(.fmov(dst_ra.w(), .{ .register = src_mat.ra.s() }));
2964 try src_mat.finish(isel);
2965 },
2966 64 => {
2967 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
2968 const src_vi = try isel.use(ty_op.operand);
2969 const src_mat = try src_vi.matReg(isel);
2970 try isel.emit(.fmov(dst_ra.x(), .{ .register = src_mat.ra.d() }));
2971 try src_mat.finish(isel);
2972 },
2973 80 => switch (dst_int_info.signedness) {
2974 .signed => {
2975 const src_vi = try isel.use(ty_op.operand);
2976 var dst_hi16_it = dst_vi.value.field(dst_ty, 8, 8);
2977 const dst_hi16_vi = try dst_hi16_it.only(isel);
2978 if (try dst_hi16_vi.?.defReg(isel)) |dst_hi16_ra| {
2979 var src_hi16_it = src_vi.field(src_ty, 8, 8);
2980 const src_hi16_vi = try src_hi16_it.only(isel);
2981 const src_hi16_mat = try src_hi16_vi.?.matReg(isel);
2982 try isel.emit(.sbfm(dst_hi16_ra.x(), src_hi16_mat.ra.x(), .{
2983 .N = .doubleword,
2984 .immr = 0,
2985 .imms = 16 - 1,
2986 }));
2987 try src_hi16_mat.finish(isel);
2988 }
2989 var dst_lo64_it = dst_vi.value.field(dst_ty, 0, 8);
2990 const dst_lo64_vi = try dst_lo64_it.only(isel);
2991 if (try dst_lo64_vi.?.defReg(isel)) |dst_lo64_ra| {
2992 var src_lo64_it = src_vi.field(src_ty, 0, 8);
2993 const src_lo64_vi = try src_lo64_it.only(isel);
2994 try src_lo64_vi.?.liveOut(isel, dst_lo64_ra);
2995 }
2996 },
2997 else => try dst_vi.value.move(isel, ty_op.operand),
2998 },
2999 128 => {
3000 const src_vi = try isel.use(ty_op.operand);
3001 const src_mat = try src_vi.matReg(isel);
3002 var dst_hi64_it = dst_vi.value.field(dst_ty, 8, 8);
3003 const dst_hi64_vi = try dst_hi64_it.only(isel);
3004 if (try dst_hi64_vi.?.defReg(isel)) |dst_hi64_ra| try isel.emit(.fmov(dst_hi64_ra.x(), .{ .register = src_mat.ra.@"d[]"(1) }));
3005 var dst_lo64_it = dst_vi.value.field(dst_ty, 0, 8);
3006 const dst_lo64_vi = try dst_lo64_it.only(isel);
3007 if (try dst_lo64_vi.?.defReg(isel)) |dst_lo64_ra| try isel.emit(.fmov(dst_lo64_ra.x(), .{ .register = src_mat.ra.d() }));
3008 try src_mat.finish(isel);
3009 },
3010 }
3011 } else if (dst_tag == .float and src_ty.isAbiInt(zcu)) {
3012 const src_int_info = src_ty.intInfo(zcu);
3013 assert(dst_ty.floatBits(isel.target) == src_int_info.bits);
3014 switch (src_int_info.bits) {
3015 else => unreachable,
3016 16 => {
3017 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
3018 const src_vi = try isel.use(ty_op.operand);
3019 const src_mat = try src_vi.matReg(isel);
3020 try isel.emit(.fmov(
3021 if (isel.target.cpu.has(.aarch64, .fullfp16)) dst_ra.h() else dst_ra.s(),
3022 .{ .register = src_mat.ra.w() },
3023 ));
3024 try src_mat.finish(isel);
3025 },
3026 32 => {
3027 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
3028 const src_vi = try isel.use(ty_op.operand);
3029 const src_mat = try src_vi.matReg(isel);
3030 try isel.emit(.fmov(dst_ra.s(), .{ .register = src_mat.ra.w() }));
3031 try src_mat.finish(isel);
3032 },
3033 64 => {
3034 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
3035 const src_vi = try isel.use(ty_op.operand);
3036 const src_mat = try src_vi.matReg(isel);
3037 try isel.emit(.fmov(dst_ra.d(), .{ .register = src_mat.ra.x() }));
3038 try src_mat.finish(isel);
3039 },
3040 80 => switch (src_int_info.signedness) {
3041 .signed => {
3042 const src_vi = try isel.use(ty_op.operand);
3043 var dst_hi16_it = dst_vi.value.field(dst_ty, 8, 8);
3044 const dst_hi16_vi = try dst_hi16_it.only(isel);
3045 if (try dst_hi16_vi.?.defReg(isel)) |dst_hi16_ra| {
3046 var src_hi16_it = src_vi.field(src_ty, 8, 8);
3047 const src_hi16_vi = try src_hi16_it.only(isel);
3048 const src_hi16_mat = try src_hi16_vi.?.matReg(isel);
3049 try isel.emit(.ubfm(dst_hi16_ra.x(), src_hi16_mat.ra.x(), .{
3050 .N = .doubleword,
3051 .immr = 0,
3052 .imms = 16 - 1,
3053 }));
3054 try src_hi16_mat.finish(isel);
3055 }
3056 var dst_lo64_it = dst_vi.value.field(dst_ty, 0, 8);
3057 const dst_lo64_vi = try dst_lo64_it.only(isel);
3058 if (try dst_lo64_vi.?.defReg(isel)) |dst_lo64_ra| {
3059 var src_lo64_it = src_vi.field(src_ty, 0, 8);
3060 const src_lo64_vi = try src_lo64_it.only(isel);
3061 try src_lo64_vi.?.liveOut(isel, dst_lo64_ra);
3062 }
3063 },
3064 else => try dst_vi.value.move(isel, ty_op.operand),
3065 },
3066 128 => {
3067 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
3068 const src_vi = try isel.use(ty_op.operand);
3069 var src_hi64_it = src_vi.field(src_ty, 8, 8);
3070 const src_hi64_vi = try src_hi64_it.only(isel);
3071 const src_hi64_mat = try src_hi64_vi.?.matReg(isel);
3072 try isel.emit(.fmov(dst_ra.@"d[]"(1), .{ .register = src_hi64_mat.ra.x() }));
3073 try src_hi64_mat.finish(isel);
3074 var src_lo64_it = src_vi.field(src_ty, 0, 8);
3075 const src_lo64_vi = try src_lo64_it.only(isel);
3076 const src_lo64_mat = try src_lo64_vi.?.matReg(isel);
3077 try isel.emit(.fmov(dst_ra.d(), .{ .register = src_lo64_mat.ra.x() }));
3078 try src_lo64_mat.finish(isel);
3079 },
3080 }
3081 } else if (dst_ty.isAbiInt(zcu) and src_tag == .array and src_ty.childType(zcu).isAbiInt(zcu)) {
3082 const dst_int_info = dst_ty.intInfo(zcu);
3083 const src_child_int_info = src_ty.childType(zcu).intInfo(zcu);
3084 const src_len = src_ty.arrayLenIncludingSentinel(zcu);
3085 assert(dst_int_info.bits == src_child_int_info.bits * src_len);
3086 const src_child_size = src_ty.childType(zcu).abiSize(zcu);
3087 if (8 * src_child_size == src_child_int_info.bits) {
3088 try dst_vi.value.defAddr(isel, dst_ty, dst_int_info, comptime &.initFill(.free)) orelse break :unused;
3089
3090 try call.prepareReturn(isel);
3091 try call.finishReturn(isel);
3092
3093 try call.prepareCallee(isel);
3094 try isel.global_relocs.append(gpa, .{
3095 .global = "memcpy",
3096 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
3097 });
3098 try isel.emit(.bl(0));
3099 try call.finishCallee(isel);
3100
3101 try call.prepareParams(isel);
3102 const src_vi = try isel.use(ty_op.operand);
3103 try isel.movImmediate(.x2, src_child_size * src_len);
3104 try call.paramAddress(isel, src_vi, .r1);
3105 try call.paramAddress(isel, dst_vi.value, .r0);
3106 try call.finishParams(isel);
3107 } else return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
3108 } else if (dst_tag == .array and dst_ty.childType(zcu).isAbiInt(zcu) and src_ty.isAbiInt(zcu)) {
3109 const dst_child_int_info = dst_ty.childType(zcu).intInfo(zcu);
3110 const src_int_info = src_ty.intInfo(zcu);
3111 const dst_len = dst_ty.arrayLenIncludingSentinel(zcu);
3112 assert(dst_child_int_info.bits * dst_len == src_int_info.bits);
3113 const dst_child_size = dst_ty.childType(zcu).abiSize(zcu);
3114 if (8 * dst_child_size == dst_child_int_info.bits) {
3115 try dst_vi.value.defAddr(isel, dst_ty, null, comptime &.initFill(.free)) orelse break :unused;
3116
3117 try call.prepareReturn(isel);
3118 try call.finishReturn(isel);
3119
3120 try call.prepareCallee(isel);
3121 try isel.global_relocs.append(gpa, .{
3122 .global = "memcpy",
3123 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
3124 });
3125 try isel.emit(.bl(0));
3126 try call.finishCallee(isel);
3127
3128 try call.prepareParams(isel);
3129 const src_vi = try isel.use(ty_op.operand);
3130 try isel.movImmediate(.x2, dst_child_size * dst_len);
3131 try call.paramAddress(isel, src_vi, .r1);
3132 try call.paramAddress(isel, dst_vi.value, .r0);
3133 try call.finishParams(isel);
3134 } else return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
3135 } else return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
3136 }
3137 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3138 },
3139 .block => {
3140 const ty_pl = air.data(air.inst_index).ty_pl;
3141 const extra = isel.air.extraData(Air.Block, ty_pl.payload);
3142
3143 if (ty_pl.ty != .noreturn_type) {
3144 isel.blocks.putAssumeCapacityNoClobber(air.inst_index, .{
3145 .live_registers = isel.live_registers,
3146 .target_label = @intCast(isel.instructions.items.len),
3147 });
3148 }
3149 try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
3150 if (ty_pl.ty != .noreturn_type) {
3151 const block_entry = isel.blocks.pop().?;
3152 assert(block_entry.key == air.inst_index);
3153 if (isel.live_values.fetchRemove(air.inst_index)) |result_vi| result_vi.value.deref(isel);
3154 }
3155 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3156 },
3157 .loop => {
3158 const ty_pl = air.data(air.inst_index).ty_pl;
3159 const extra = isel.air.extraData(Air.Block, ty_pl.payload);
3160 const loops = isel.loops.values();
3161 const loop_index = isel.loops.getIndex(air.inst_index).?;
3162 const loop = &loops[loop_index];
3163
3164 tracking_log.debug("{f}", .{
3165 isel.fmtDom(air.inst_index, loop.dom, @intCast(isel.blocks.count())),
3166 });
3167 tracking_log.debug("{f}", .{isel.fmtLoopLive(air.inst_index)});
3168 assert(loop.depth == isel.blocks.count());
3169
3170 if (false) {
3171 // loops are dumb...
3172 for (isel.loop_live.list.items[loop.live..loops[loop_index + 1].live]) |live_inst| {
3173 const live_vi = try isel.use(live_inst.toRef());
3174 try live_vi.mat(isel);
3175 }
3176
3177 // IT'S DOM TIME!!!
3178 for (isel.blocks.values(), 0..) |*block, dom_index| {
3179 if (@as(u1, @truncate(isel.dom.items[
3180 loop.dom + dom_index / @bitSizeOf(DomInt)
3181 ] >> @truncate(dom_index))) == 0) continue;
3182 var live_reg_it = block.live_registers.iterator();
3183 while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) {
3184 _ => |live_vi| try live_vi.mat(isel),
3185 .allocating => unreachable,
3186 .free => {},
3187 };
3188 }
3189 }
3190
3191 loop.live_registers = isel.live_registers;
3192 loop.repeat_list = Loop.empty_list;
3193 try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
3194 try isel.merge(&loop.live_registers, .{ .fill_extra = true });
3195
3196 var repeat_label = loop.repeat_list;
3197 assert(repeat_label != Loop.empty_list);
3198 while (repeat_label != Loop.empty_list) {
3199 const instruction = &isel.instructions.items[repeat_label];
3200 const next_repeat_label = instruction.*;
3201 instruction.* = .b(-@as(i28, @intCast((isel.instructions.items.len - 1 - repeat_label) << 2)));
3202 repeat_label = @bitCast(next_repeat_label);
3203 }
3204
3205 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3206 },
3207 .repeat => {
3208 const repeat = air.data(air.inst_index).repeat;
3209 try isel.loops.getPtr(repeat.loop_inst).?.branch(isel);
3210 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3211 },
3212 .br => {
3213 const br = air.data(air.inst_index).br;
3214 const block = isel.blocks.getPtr(br.block_inst).?;
3215 try block.branch(isel);
3216 if (isel.live_values.get(br.block_inst)) |dst_vi| try dst_vi.move(isel, br.operand);
3217 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3218 },
3219 .trap => {
3220 try isel.emit(.brk(0x1));
3221 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3222 },
3223 .breakpoint => {
3224 try isel.emit(.brk(0xf000));
3225 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3226 },
3227 .call => {
3228 const pl_op = air.data(air.inst_index).pl_op;
3229 const extra = isel.air.extraData(Air.Call, pl_op.payload);
3230 const args: []const Air.Inst.Ref = @ptrCast(isel.air.extra.items[extra.end..][0..extra.data.args_len]);
3231
3232 try call.prepareReturn(isel);
3233 const maybe_def_ret_vi = isel.live_values.fetchRemove(air.inst_index);
3234 var maybe_ret_addr_vi: ?Value.Index = null;
3235 if (maybe_def_ret_vi) |def_ret_vi| {
3236 defer def_ret_vi.value.deref(isel);
3237
3238 var ret_it: CallAbiIterator = .init;
3239 const ret_vi = try ret_it.ret(isel, isel.air.typeOfIndex(air.inst_index, ip));
3240 defer ret_vi.?.deref(isel);
3241 switch (ret_vi.?.parent(isel)) {
3242 .unallocated, .stack_slot => if (ret_vi.?.hint(isel)) |ret_ra| {
3243 try call.returnLiveIn(isel, def_ret_vi.value, ret_ra);
3244 } else {
3245 var def_ret_part_it = def_ret_vi.value.parts(isel);
3246 var ret_part_it = ret_vi.?.parts(isel);
3247 while (def_ret_part_it.next()) |ret_part_vi| {
3248 try call.returnLiveIn(isel, ret_part_vi, ret_part_it.next().?.hint(isel).?);
3249 }
3250 },
3251 .value, .constant => unreachable,
3252 .address => |address_vi| {
3253 maybe_ret_addr_vi = address_vi;
3254 _ = try def_ret_vi.value.defAddr(
3255 isel,
3256 isel.air.typeOfIndex(air.inst_index, ip),
3257 null,
3258 &call.caller_saved_regs,
3259 );
3260 },
3261 }
3262 }
3263 try call.finishReturn(isel);
3264
3265 try call.prepareCallee(isel);
3266 if (pl_op.operand.toInterned()) |ct_callee| {
3267 try isel.nav_relocs.append(gpa, switch (ip.indexToKey(ct_callee)) {
3268 else => unreachable,
3269 inline .@"extern", .func => |func| .{
3270 .nav = func.owner_nav,
3271 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
3272 },
3273 .ptr => |ptr| .{
3274 .nav = ptr.base_addr.nav,
3275 .reloc = .{
3276 .label = @intCast(isel.instructions.items.len),
3277 .addend = ptr.byte_offset,
3278 },
3279 },
3280 });
3281 try isel.emit(.bl(0));
3282 } else {
3283 const callee_vi = try isel.use(pl_op.operand);
3284 const callee_mat = try callee_vi.matReg(isel);
3285 try isel.emit(.blr(callee_mat.ra.x()));
3286 try callee_mat.finish(isel);
3287 }
3288 try call.finishCallee(isel);
3289
3290 try call.prepareParams(isel);
3291 if (maybe_ret_addr_vi) |ret_addr_vi| try call.paramAddress(
3292 isel,
3293 maybe_def_ret_vi.?.value,
3294 ret_addr_vi.hint(isel).?,
3295 );
3296 var param_it: CallAbiIterator = .init;
3297 for (args) |arg| {
3298 const param_vi = try param_it.param(isel, isel.air.typeOf(arg, ip)) orelse continue;
3299 defer param_vi.deref(isel);
3300 const arg_vi = try isel.use(arg);
3301 const passed_vi = switch (param_vi.parent(isel)) {
3302 .unallocated, .stack_slot => param_vi,
3303 .value, .constant => unreachable,
3304 .address => |address_vi| {
3305 try call.paramAddress(isel, arg_vi, address_vi.hint(isel).?);
3306 continue;
3307 },
3308 };
3309 if (passed_vi.hint(isel)) |param_ra| {
3310 try call.paramLiveOut(isel, arg_vi, param_ra);
3311 } else {
3312 var param_part_it = passed_vi.parts(isel);
3313 var arg_part_it = arg_vi.parts(isel);
3314 if (arg_part_it.only()) |_| {
3315 try isel.values.ensureUnusedCapacity(isel.pt.zcu.gpa, param_part_it.remaining);
3316 arg_vi.setParts(isel, param_part_it.remaining);
3317 while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart(
3318 isel,
3319 param_part_vi.get(isel).offset_from_parent,
3320 param_part_vi.size(isel),
3321 );
3322 param_part_it = passed_vi.parts(isel);
3323 arg_part_it = arg_vi.parts(isel);
3324 }
3325 while (param_part_it.next()) |param_part_vi| {
3326 const arg_part_vi = arg_part_it.next().?;
3327 assert(arg_part_vi.get(isel).offset_from_parent ==
3328 param_part_vi.get(isel).offset_from_parent);
3329 assert(arg_part_vi.size(isel) == param_part_vi.size(isel));
3330 try call.paramLiveOut(isel, arg_part_vi, param_part_vi.hint(isel).?);
3331 }
3332 }
3333 }
3334 try call.finishParams(isel);
3335
3336 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3337 },
3338 .clz => |air_tag| {
3339 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
3340 defer res_vi.value.deref(isel);
3341
3342 const ty_op = air.data(air.inst_index).ty_op;
3343 const ty = isel.air.typeOf(ty_op.operand, ip);
3344 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
3345 const int_info = ty.intInfo(zcu);
3346 switch (int_info.bits) {
3347 0 => unreachable,
3348 1...64 => {
3349 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3350 const src_vi = try isel.use(ty_op.operand);
3351 const src_mat = try src_vi.matReg(isel);
3352 try isel.clzLimb(res_ra, int_info, src_mat.ra);
3353 try src_mat.finish(isel);
3354 },
3355 65...128 => |bits| {
3356 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3357 const src_vi = try isel.use(ty_op.operand);
3358 var src_hi64_it = src_vi.field(ty, 8, 8);
3359 const src_hi64_vi = try src_hi64_it.only(isel);
3360 const src_hi64_mat = try src_hi64_vi.?.matReg(isel);
3361 var src_lo64_it = src_vi.field(ty, 0, 8);
3362 const src_lo64_vi = try src_lo64_it.only(isel);
3363 const src_lo64_mat = try src_lo64_vi.?.matReg(isel);
3364 const lo64_ra = try isel.allocIntReg();
3365 defer isel.freeReg(lo64_ra);
3366 const hi64_ra = try isel.allocIntReg();
3367 defer isel.freeReg(hi64_ra);
3368 try isel.emit(.csel(res_ra.w(), lo64_ra.w(), hi64_ra.w(), .eq));
3369 try isel.emit(.add(lo64_ra.w(), lo64_ra.w(), .{ .immediate = @intCast(bits - 64) }));
3370 try isel.emit(.subs(.xzr, src_hi64_mat.ra.x(), .{ .immediate = 0 }));
3371 try isel.clzLimb(hi64_ra, .{ .signedness = int_info.signedness, .bits = bits - 64 }, src_hi64_mat.ra);
3372 try isel.clzLimb(lo64_ra, .{ .signedness = .unsigned, .bits = 64 }, src_lo64_mat.ra);
3373 try src_hi64_mat.finish(isel);
3374 try src_lo64_mat.finish(isel);
3375 },
3376 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
3377 }
3378 }
3379 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3380 },
3381 .ctz => |air_tag| {
3382 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
3383 defer res_vi.value.deref(isel);
3384
3385 const ty_op = air.data(air.inst_index).ty_op;
3386 const ty = isel.air.typeOf(ty_op.operand, ip);
3387 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
3388 const int_info = ty.intInfo(zcu);
3389 switch (int_info.bits) {
3390 0 => unreachable,
3391 1...64 => {
3392 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3393 const src_vi = try isel.use(ty_op.operand);
3394 const src_mat = try src_vi.matReg(isel);
3395 try isel.ctzLimb(res_ra, int_info, src_mat.ra);
3396 try src_mat.finish(isel);
3397 },
3398 65...128 => |bits| {
3399 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3400 const src_vi = try isel.use(ty_op.operand);
3401 var src_hi64_it = src_vi.field(ty, 8, 8);
3402 const src_hi64_vi = try src_hi64_it.only(isel);
3403 const src_hi64_mat = try src_hi64_vi.?.matReg(isel);
3404 var src_lo64_it = src_vi.field(ty, 0, 8);
3405 const src_lo64_vi = try src_lo64_it.only(isel);
3406 const src_lo64_mat = try src_lo64_vi.?.matReg(isel);
3407 const lo64_ra = try isel.allocIntReg();
3408 defer isel.freeReg(lo64_ra);
3409 const hi64_ra = try isel.allocIntReg();
3410 defer isel.freeReg(hi64_ra);
3411 try isel.emit(.csel(res_ra.w(), lo64_ra.w(), hi64_ra.w(), .ne));
3412 try isel.emit(.add(hi64_ra.w(), hi64_ra.w(), .{ .immediate = 64 }));
3413 try isel.emit(.subs(.xzr, src_lo64_mat.ra.x(), .{ .immediate = 0 }));
3414 try isel.ctzLimb(hi64_ra, .{ .signedness = .unsigned, .bits = 64 }, src_hi64_mat.ra);
3415 try isel.ctzLimb(lo64_ra, .{ .signedness = int_info.signedness, .bits = bits - 64 }, src_lo64_mat.ra);
3416 try src_hi64_mat.finish(isel);
3417 try src_lo64_mat.finish(isel);
3418 },
3419 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
3420 }
3421 }
3422 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3423 },
3424 .popcount => |air_tag| {
3425 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
3426 defer res_vi.value.deref(isel);
3427
3428 const ty_op = air.data(air.inst_index).ty_op;
3429 const ty = isel.air.typeOf(ty_op.operand, ip);
3430 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
3431 const int_info = ty.intInfo(zcu);
3432 if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
3433
3434 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3435 const src_vi = try isel.use(ty_op.operand);
3436 const src_mat = try src_vi.matReg(isel);
3437 const vec_ra = try isel.allocVecReg();
3438 defer isel.freeReg(vec_ra);
3439 try isel.emit(.umov(res_ra.w(), vec_ra.@"b[]"(0)));
3440 switch (int_info.bits) {
3441 else => unreachable,
3442 1...8 => {},
3443 9...16 => try isel.emit(.addp(vec_ra.@"8b"(), vec_ra.@"8b"(), .{ .vector = vec_ra.@"8b"() })),
3444 17...64 => try isel.emit(.addv(vec_ra.b(), vec_ra.@"8b"())),
3445 }
3446 try isel.emit(.cnt(vec_ra.@"8b"(), vec_ra.@"8b"()));
3447 switch (int_info.bits) {
3448 else => unreachable,
3449 1...31 => |bits| switch (int_info.signedness) {
3450 .signed => {
3451 try isel.emit(.fmov(vec_ra.s(), .{ .register = res_ra.w() }));
3452 try isel.emit(.ubfm(res_ra.w(), src_mat.ra.w(), .{
3453 .N = .word,
3454 .immr = 0,
3455 .imms = @intCast(bits - 1),
3456 }));
3457 },
3458 .unsigned => try isel.emit(.fmov(vec_ra.s(), .{ .register = src_mat.ra.w() })),
3459 },
3460 32 => try isel.emit(.fmov(vec_ra.s(), .{ .register = src_mat.ra.w() })),
3461 33...63 => |bits| switch (int_info.signedness) {
3462 .signed => {
3463 try isel.emit(.fmov(vec_ra.d(), .{ .register = res_ra.x() }));
3464 try isel.emit(.ubfm(res_ra.x(), src_mat.ra.x(), .{
3465 .N = .doubleword,
3466 .immr = 0,
3467 .imms = @intCast(bits - 1),
3468 }));
3469 },
3470 .unsigned => try isel.emit(.fmov(vec_ra.d(), .{ .register = src_mat.ra.x() })),
3471 },
3472 64 => try isel.emit(.fmov(vec_ra.d(), .{ .register = src_mat.ra.x() })),
3473 }
3474 try src_mat.finish(isel);
3475 }
3476 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3477 },
3478 .byte_swap => |air_tag| {
3479 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
3480 defer res_vi.value.deref(isel);
3481
3482 const ty_op = air.data(air.inst_index).ty_op;
3483 const ty = ty_op.ty.toType();
3484 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
3485 const int_info = ty.intInfo(zcu);
3486 if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
3487
3488 if (int_info.bits == 8) break :unused try res_vi.value.move(isel, ty_op.operand);
3489 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3490 const src_vi = try isel.use(ty_op.operand);
3491 const src_mat = try src_vi.matReg(isel);
3492 switch (int_info.bits) {
3493 else => unreachable,
3494 16 => switch (int_info.signedness) {
3495 .signed => {
3496 try isel.emit(.sbfm(res_ra.w(), res_ra.w(), .{
3497 .N = .word,
3498 .immr = 32 - 16,
3499 .imms = 32 - 1,
3500 }));
3501 try isel.emit(.rev(res_ra.w(), src_mat.ra.w()));
3502 },
3503 .unsigned => try isel.emit(.rev16(res_ra.w(), src_mat.ra.w())),
3504 },
3505 24 => {
3506 switch (int_info.signedness) {
3507 .signed => try isel.emit(.sbfm(res_ra.w(), res_ra.w(), .{
3508 .N = .word,
3509 .immr = 32 - 24,
3510 .imms = 32 - 1,
3511 })),
3512 .unsigned => try isel.emit(.ubfm(res_ra.w(), res_ra.w(), .{
3513 .N = .word,
3514 .immr = 32 - 24,
3515 .imms = 32 - 1,
3516 })),
3517 }
3518 try isel.emit(.rev(res_ra.w(), src_mat.ra.w()));
3519 },
3520 32 => try isel.emit(.rev(res_ra.w(), src_mat.ra.w())),
3521 40, 48, 56 => |bits| {
3522 switch (int_info.signedness) {
3523 .signed => try isel.emit(.sbfm(res_ra.x(), res_ra.x(), .{
3524 .N = .doubleword,
3525 .immr = @intCast(64 - bits),
3526 .imms = 64 - 1,
3527 })),
3528 .unsigned => try isel.emit(.ubfm(res_ra.x(), res_ra.x(), .{
3529 .N = .doubleword,
3530 .immr = @intCast(64 - bits),
3531 .imms = 64 - 1,
3532 })),
3533 }
3534 try isel.emit(.rev(res_ra.x(), src_mat.ra.x()));
3535 },
3536 64 => try isel.emit(.rev(res_ra.x(), src_mat.ra.x())),
3537 }
3538 try src_mat.finish(isel);
3539 }
3540 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3541 },
3542 .bit_reverse => |air_tag| {
3543 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
3544 defer res_vi.value.deref(isel);
3545
3546 const ty_op = air.data(air.inst_index).ty_op;
3547 const ty = ty_op.ty.toType();
3548 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
3549 const int_info = ty.intInfo(zcu);
3550 if (int_info.bits > 64) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
3551
3552 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3553 const src_vi = try isel.use(ty_op.operand);
3554 const src_mat = try src_vi.matReg(isel);
3555 switch (int_info.bits) {
3556 else => unreachable,
3557 1...31 => |bits| {
3558 switch (int_info.signedness) {
3559 .signed => try isel.emit(.sbfm(res_ra.w(), res_ra.w(), .{
3560 .N = .word,
3561 .immr = @intCast(32 - bits),
3562 .imms = 32 - 1,
3563 })),
3564 .unsigned => try isel.emit(.ubfm(res_ra.w(), res_ra.w(), .{
3565 .N = .word,
3566 .immr = @intCast(32 - bits),
3567 .imms = 32 - 1,
3568 })),
3569 }
3570 try isel.emit(.rbit(res_ra.w(), src_mat.ra.w()));
3571 },
3572 32 => try isel.emit(.rbit(res_ra.w(), src_mat.ra.w())),
3573 33...63 => |bits| {
3574 switch (int_info.signedness) {
3575 .signed => try isel.emit(.sbfm(res_ra.x(), res_ra.x(), .{
3576 .N = .doubleword,
3577 .immr = @intCast(64 - bits),
3578 .imms = 64 - 1,
3579 })),
3580 .unsigned => try isel.emit(.ubfm(res_ra.x(), res_ra.x(), .{
3581 .N = .doubleword,
3582 .immr = @intCast(64 - bits),
3583 .imms = 64 - 1,
3584 })),
3585 }
3586 try isel.emit(.rbit(res_ra.x(), src_mat.ra.x()));
3587 },
3588 64 => try isel.emit(.rbit(res_ra.x(), src_mat.ra.x())),
3589 }
3590 try src_mat.finish(isel);
3591 }
3592 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3593 },
3594 .sqrt, .floor, .ceil, .round, .trunc_float => |air_tag| {
3595 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
3596 defer res_vi.value.deref(isel);
3597
3598 const un_op = air.data(air.inst_index).un_op;
3599 const ty = isel.air.typeOf(un_op, ip);
3600 switch (ty.floatBits(isel.target)) {
3601 else => unreachable,
3602 16, 32, 64 => |bits| {
3603 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3604 const need_fcvt = switch (bits) {
3605 else => unreachable,
3606 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
3607 32, 64 => false,
3608 };
3609 if (need_fcvt) try isel.emit(.fcvt(res_ra.h(), res_ra.s()));
3610 const src_vi = try isel.use(un_op);
3611 const src_mat = try src_vi.matReg(isel);
3612 const src_ra = if (need_fcvt) try isel.allocVecReg() else src_mat.ra;
3613 defer if (need_fcvt) isel.freeReg(src_ra);
3614 try isel.emit(bits: switch (bits) {
3615 else => unreachable,
3616 16 => if (need_fcvt) continue :bits 32 else switch (air_tag) {
3617 else => unreachable,
3618 .sqrt => .fsqrt(res_ra.h(), src_ra.h()),
3619 .floor => .frintm(res_ra.h(), src_ra.h()),
3620 .ceil => .frintp(res_ra.h(), src_ra.h()),
3621 .round => .frinta(res_ra.h(), src_ra.h()),
3622 .trunc_float => .frintz(res_ra.h(), src_ra.h()),
3623 },
3624 32 => switch (air_tag) {
3625 else => unreachable,
3626 .sqrt => .fsqrt(res_ra.s(), src_ra.s()),
3627 .floor => .frintm(res_ra.s(), src_ra.s()),
3628 .ceil => .frintp(res_ra.s(), src_ra.s()),
3629 .round => .frinta(res_ra.s(), src_ra.s()),
3630 .trunc_float => .frintz(res_ra.s(), src_ra.s()),
3631 },
3632 64 => switch (air_tag) {
3633 else => unreachable,
3634 .sqrt => .fsqrt(res_ra.d(), src_ra.d()),
3635 .floor => .frintm(res_ra.d(), src_ra.d()),
3636 .ceil => .frintp(res_ra.d(), src_ra.d()),
3637 .round => .frinta(res_ra.d(), src_ra.d()),
3638 .trunc_float => .frintz(res_ra.d(), src_ra.d()),
3639 },
3640 });
3641 if (need_fcvt) try isel.emit(.fcvt(src_ra.s(), src_mat.ra.h()));
3642 try src_mat.finish(isel);
3643 },
3644 80, 128 => |bits| {
3645 try call.prepareReturn(isel);
3646 switch (bits) {
3647 else => unreachable,
3648 16, 32, 64, 128 => try call.returnLiveIn(isel, res_vi.value, .v0),
3649 80 => {
3650 var res_hi16_it = res_vi.value.field(ty, 8, 8);
3651 const res_hi16_vi = try res_hi16_it.only(isel);
3652 try call.returnLiveIn(isel, res_hi16_vi.?, .r1);
3653 var res_lo64_it = res_vi.value.field(ty, 0, 8);
3654 const res_lo64_vi = try res_lo64_it.only(isel);
3655 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
3656 },
3657 }
3658 try call.finishReturn(isel);
3659
3660 try call.prepareCallee(isel);
3661 try isel.global_relocs.append(gpa, .{
3662 .global = switch (air_tag) {
3663 else => unreachable,
3664 .sqrt => switch (bits) {
3665 else => unreachable,
3666 16 => "__sqrth",
3667 32 => "sqrtf",
3668 64 => "sqrt",
3669 80 => "__sqrtx",
3670 128 => "sqrtq",
3671 },
3672 .floor => switch (bits) {
3673 else => unreachable,
3674 16 => "__floorh",
3675 32 => "floorf",
3676 64 => "floor",
3677 80 => "__floorx",
3678 128 => "floorq",
3679 },
3680 .ceil => switch (bits) {
3681 else => unreachable,
3682 16 => "__ceilh",
3683 32 => "ceilf",
3684 64 => "ceil",
3685 80 => "__ceilx",
3686 128 => "ceilq",
3687 },
3688 .round => switch (bits) {
3689 else => unreachable,
3690 16 => "__roundh",
3691 32 => "roundf",
3692 64 => "round",
3693 80 => "__roundx",
3694 128 => "roundq",
3695 },
3696 .trunc_float => switch (bits) {
3697 else => unreachable,
3698 16 => "__trunch",
3699 32 => "truncf",
3700 64 => "trunc",
3701 80 => "__truncx",
3702 128 => "truncq",
3703 },
3704 },
3705 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
3706 });
3707 try isel.emit(.bl(0));
3708 try call.finishCallee(isel);
3709
3710 try call.prepareParams(isel);
3711 const src_vi = try isel.use(un_op);
3712 switch (bits) {
3713 else => unreachable,
3714 16, 32, 64, 128 => try call.paramLiveOut(isel, src_vi, .v0),
3715 80 => {
3716 var src_hi16_it = src_vi.field(ty, 8, 8);
3717 const src_hi16_vi = try src_hi16_it.only(isel);
3718 try call.paramLiveOut(isel, src_hi16_vi.?, .r1);
3719 var src_lo64_it = src_vi.field(ty, 0, 8);
3720 const src_lo64_vi = try src_lo64_it.only(isel);
3721 try call.paramLiveOut(isel, src_lo64_vi.?, .r0);
3722 },
3723 }
3724 try call.finishParams(isel);
3725 },
3726 }
3727 }
3728 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3729 },
3730 .sin, .cos, .tan, .exp, .exp2, .log, .log2, .log10 => |air_tag| {
3731 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| {
3732 defer res_vi.value.deref(isel);
3733
3734 const un_op = air.data(air.inst_index).un_op;
3735 const ty = isel.air.typeOf(un_op, ip);
3736 const bits = ty.floatBits(isel.target);
3737 try call.prepareReturn(isel);
3738 switch (bits) {
3739 else => unreachable,
3740 16, 32, 64, 128 => try call.returnLiveIn(isel, res_vi.value, .v0),
3741 80 => {
3742 var res_hi16_it = res_vi.value.field(ty, 8, 8);
3743 const res_hi16_vi = try res_hi16_it.only(isel);
3744 try call.returnLiveIn(isel, res_hi16_vi.?, .r1);
3745 var res_lo64_it = res_vi.value.field(ty, 0, 8);
3746 const res_lo64_vi = try res_lo64_it.only(isel);
3747 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
3748 },
3749 }
3750 try call.finishReturn(isel);
3751
3752 try call.prepareCallee(isel);
3753 try isel.global_relocs.append(gpa, .{
3754 .global = switch (air_tag) {
3755 else => unreachable,
3756 .sin => switch (bits) {
3757 else => unreachable,
3758 16 => "__sinh",
3759 32 => "sinf",
3760 64 => "sin",
3761 80 => "__sinx",
3762 128 => "sinq",
3763 },
3764 .cos => switch (bits) {
3765 else => unreachable,
3766 16 => "__cosh",
3767 32 => "cosf",
3768 64 => "cos",
3769 80 => "__cosx",
3770 128 => "cosq",
3771 },
3772 .tan => switch (bits) {
3773 else => unreachable,
3774 16 => "__tanh",
3775 32 => "tanf",
3776 64 => "tan",
3777 80 => "__tanx",
3778 128 => "tanq",
3779 },
3780 .exp => switch (bits) {
3781 else => unreachable,
3782 16 => "__exph",
3783 32 => "expf",
3784 64 => "exp",
3785 80 => "__expx",
3786 128 => "expq",
3787 },
3788 .exp2 => switch (bits) {
3789 else => unreachable,
3790 16 => "__exp2h",
3791 32 => "exp2f",
3792 64 => "exp2",
3793 80 => "__exp2x",
3794 128 => "exp2q",
3795 },
3796 .log => switch (bits) {
3797 else => unreachable,
3798 16 => "__logh",
3799 32 => "logf",
3800 64 => "log",
3801 80 => "__logx",
3802 128 => "logq",
3803 },
3804 .log2 => switch (bits) {
3805 else => unreachable,
3806 16 => "__log2h",
3807 32 => "log2f",
3808 64 => "log2",
3809 80 => "__log2x",
3810 128 => "log2q",
3811 },
3812 .log10 => switch (bits) {
3813 else => unreachable,
3814 16 => "__log10h",
3815 32 => "log10f",
3816 64 => "log10",
3817 80 => "__log10x",
3818 128 => "log10q",
3819 },
3820 },
3821 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
3822 });
3823 try isel.emit(.bl(0));
3824 try call.finishCallee(isel);
3825
3826 try call.prepareParams(isel);
3827 const src_vi = try isel.use(un_op);
3828 switch (bits) {
3829 else => unreachable,
3830 16, 32, 64, 128 => try call.paramLiveOut(isel, src_vi, .v0),
3831 80 => {
3832 var src_hi16_it = src_vi.field(ty, 8, 8);
3833 const src_hi16_vi = try src_hi16_it.only(isel);
3834 try call.paramLiveOut(isel, src_hi16_vi.?, .r1);
3835 var src_lo64_it = src_vi.field(ty, 0, 8);
3836 const src_lo64_vi = try src_lo64_it.only(isel);
3837 try call.paramLiveOut(isel, src_lo64_vi.?, .r0);
3838 },
3839 }
3840 try call.finishParams(isel);
3841 }
3842 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3843 },
3844 .abs => |air_tag| {
3845 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
3846 defer res_vi.value.deref(isel);
3847
3848 const ty_op = air.data(air.inst_index).ty_op;
3849 const ty = ty_op.ty.toType();
3850 if (!ty.isRuntimeFloat()) {
3851 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
3852 switch (ty.intInfo(zcu).bits) {
3853 0 => unreachable,
3854 1...32 => {
3855 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3856 const src_vi = try isel.use(ty_op.operand);
3857 const src_mat = try src_vi.matReg(isel);
3858 try isel.emit(.csneg(res_ra.w(), src_mat.ra.w(), src_mat.ra.w(), .pl));
3859 try isel.emit(.subs(.wzr, src_mat.ra.w(), .{ .immediate = 0 }));
3860 try src_mat.finish(isel);
3861 },
3862 33...64 => {
3863 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3864 const src_vi = try isel.use(ty_op.operand);
3865 const src_mat = try src_vi.matReg(isel);
3866 try isel.emit(.csneg(res_ra.x(), src_mat.ra.x(), src_mat.ra.x(), .pl));
3867 try isel.emit(.subs(.xzr, src_mat.ra.x(), .{ .immediate = 0 }));
3868 try src_mat.finish(isel);
3869 },
3870 65...128 => {
3871 var res_hi64_it = res_vi.value.field(ty, 8, 8);
3872 const res_hi64_vi = try res_hi64_it.only(isel);
3873 const res_hi64_ra = try res_hi64_vi.?.defReg(isel);
3874 var res_lo64_it = res_vi.value.field(ty, 0, 8);
3875 const res_lo64_vi = try res_lo64_it.only(isel);
3876 const res_lo64_ra = try res_lo64_vi.?.defReg(isel);
3877 if (res_hi64_ra == null and res_lo64_ra == null) break :unused;
3878 const src_ty = isel.air.typeOf(ty_op.operand, ip);
3879 const src_vi = try isel.use(ty_op.operand);
3880 var src_hi64_it = src_vi.field(src_ty, 8, 8);
3881 const src_hi64_vi = try src_hi64_it.only(isel);
3882 const src_hi64_mat = try src_hi64_vi.?.matReg(isel);
3883 var src_lo64_it = src_vi.field(src_ty, 0, 8);
3884 const src_lo64_vi = try src_lo64_it.only(isel);
3885 const src_lo64_mat = try src_lo64_vi.?.matReg(isel);
3886 const lo64_ra = try isel.allocIntReg();
3887 defer isel.freeReg(lo64_ra);
3888 const hi64_ra, const mask_ra = alloc_ras: {
3889 const res_lo64_lock: RegLock = if (res_lo64_ra) |res_ra| isel.tryLockReg(res_ra) else .empty;
3890 defer res_lo64_lock.unlock(isel);
3891 break :alloc_ras .{ try isel.allocIntReg(), try isel.allocIntReg() };
3892 };
3893 defer {
3894 isel.freeReg(hi64_ra);
3895 isel.freeReg(mask_ra);
3896 }
3897 if (res_hi64_ra) |res_ra| try isel.emit(.sbc(res_ra.x(), hi64_ra.x(), mask_ra.x()));
3898 try isel.emit(.subs(
3899 if (res_lo64_ra) |res_ra| res_ra.x() else .xzr,
3900 lo64_ra.x(),
3901 .{ .register = mask_ra.x() },
3902 ));
3903 if (res_hi64_ra) |_| try isel.emit(.eor(hi64_ra.x(), src_hi64_mat.ra.x(), .{ .register = mask_ra.x() }));
3904 try isel.emit(.eor(lo64_ra.x(), src_lo64_mat.ra.x(), .{ .register = mask_ra.x() }));
3905 try isel.emit(.sbfm(mask_ra.x(), src_hi64_mat.ra.x(), .{
3906 .N = .doubleword,
3907 .immr = 64 - 1,
3908 .imms = 64 - 1,
3909 }));
3910 try src_lo64_mat.finish(isel);
3911 try src_hi64_mat.finish(isel);
3912 },
3913 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
3914 }
3915 } else switch (ty.floatBits(isel.target)) {
3916 else => unreachable,
3917 16 => {
3918 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3919 const src_vi = try isel.use(ty_op.operand);
3920 const src_mat = try src_vi.matReg(isel);
3921 try isel.emit(if (isel.target.cpu.has(.aarch64, .fullfp16))
3922 .fabs(res_ra.h(), src_mat.ra.h())
3923 else
3924 .bic(res_ra.@"4h"(), res_ra.@"4h"(), .{ .shifted_immediate = .{
3925 .immediate = 0b10000000,
3926 .lsl = 8,
3927 } }));
3928 try src_mat.finish(isel);
3929 },
3930 32 => {
3931 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3932 const src_vi = try isel.use(ty_op.operand);
3933 const src_mat = try src_vi.matReg(isel);
3934 try isel.emit(.fabs(res_ra.s(), src_mat.ra.s()));
3935 try src_mat.finish(isel);
3936 },
3937 64 => {
3938 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3939 const src_vi = try isel.use(ty_op.operand);
3940 const src_mat = try src_vi.matReg(isel);
3941 try isel.emit(.fabs(res_ra.d(), src_mat.ra.d()));
3942 try src_mat.finish(isel);
3943 },
3944 80 => {
3945 const src_vi = try isel.use(ty_op.operand);
3946 var res_hi16_it = res_vi.value.field(ty, 8, 8);
3947 const res_hi16_vi = try res_hi16_it.only(isel);
3948 if (try res_hi16_vi.?.defReg(isel)) |res_hi16_ra| {
3949 var src_hi16_it = src_vi.field(ty, 8, 8);
3950 const src_hi16_vi = try src_hi16_it.only(isel);
3951 const src_hi16_mat = try src_hi16_vi.?.matReg(isel);
3952 try isel.emit(.@"and"(res_hi16_ra.w(), src_hi16_mat.ra.w(), .{ .immediate = .{
3953 .N = .word,
3954 .immr = 0,
3955 .imms = 15 - 1,
3956 } }));
3957 try src_hi16_mat.finish(isel);
3958 }
3959 var res_lo64_it = res_vi.value.field(ty, 0, 8);
3960 const res_lo64_vi = try res_lo64_it.only(isel);
3961 if (try res_lo64_vi.?.defReg(isel)) |res_lo64_ra| {
3962 var src_lo64_it = src_vi.field(ty, 0, 8);
3963 const src_lo64_vi = try src_lo64_it.only(isel);
3964 try src_lo64_vi.?.liveOut(isel, res_lo64_ra);
3965 }
3966 },
3967 128 => {
3968 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3969 const src_vi = try isel.use(ty_op.operand);
3970 const src_mat = try src_vi.matReg(isel);
3971 const neg_zero_ra = try isel.allocVecReg();
3972 defer isel.freeReg(neg_zero_ra);
3973 try isel.emit(.bic(res_ra.@"16b"(), src_mat.ra.@"16b"(), .{ .register = neg_zero_ra.@"16b"() }));
3974 try isel.literals.appendNTimes(gpa, 0, -%isel.literals.items.len % 4);
3975 try isel.literal_relocs.append(gpa, .{
3976 .label = @intCast(isel.instructions.items.len),
3977 });
3978 try isel.emit(.ldr(neg_zero_ra.q(), .{
3979 .literal = @intCast((isel.instructions.items.len + 1 + isel.literals.items.len) << 2),
3980 }));
3981 try isel.emitLiteral(&(.{0} ** 15 ++ .{0x80}));
3982 try src_mat.finish(isel);
3983 },
3984 }
3985 }
3986 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3987 },
3988 .neg, .neg_optimized => {
3989 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
3990 defer res_vi.value.deref(isel);
3991
3992 const un_op = air.data(air.inst_index).un_op;
3993 const ty = isel.air.typeOf(un_op, ip);
3994 switch (ty.floatBits(isel.target)) {
3995 else => unreachable,
3996 16 => {
3997 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
3998 const src_vi = try isel.use(un_op);
3999 const src_mat = try src_vi.matReg(isel);
4000 if (isel.target.cpu.has(.aarch64, .fullfp16)) {
4001 try isel.emit(.fneg(res_ra.h(), src_mat.ra.h()));
4002 } else {
4003 const neg_zero_ra = try isel.allocVecReg();
4004 defer isel.freeReg(neg_zero_ra);
4005 try isel.emit(.eor(res_ra.@"8b"(), res_ra.@"8b"(), .{ .register = neg_zero_ra.@"8b"() }));
4006 try isel.emit(.movi(neg_zero_ra.@"4h"(), 0b10000000, .{ .lsl = 8 }));
4007 }
4008 try src_mat.finish(isel);
4009 },
4010 32 => {
4011 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
4012 const src_vi = try isel.use(un_op);
4013 const src_mat = try src_vi.matReg(isel);
4014 try isel.emit(.fneg(res_ra.s(), src_mat.ra.s()));
4015 try src_mat.finish(isel);
4016 },
4017 64 => {
4018 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
4019 const src_vi = try isel.use(un_op);
4020 const src_mat = try src_vi.matReg(isel);
4021 try isel.emit(.fneg(res_ra.d(), src_mat.ra.d()));
4022 try src_mat.finish(isel);
4023 },
4024 80 => {
4025 const src_vi = try isel.use(un_op);
4026 var res_hi16_it = res_vi.value.field(ty, 8, 8);
4027 const res_hi16_vi = try res_hi16_it.only(isel);
4028 if (try res_hi16_vi.?.defReg(isel)) |res_hi16_ra| {
4029 var src_hi16_it = src_vi.field(ty, 8, 8);
4030 const src_hi16_vi = try src_hi16_it.only(isel);
4031 const src_hi16_mat = try src_hi16_vi.?.matReg(isel);
4032 try isel.emit(.eor(res_hi16_ra.w(), src_hi16_mat.ra.w(), .{ .immediate = .{
4033 .N = .word,
4034 .immr = 32 - 15,
4035 .imms = 1 - 1,
4036 } }));
4037 try src_hi16_mat.finish(isel);
4038 }
4039 var res_lo64_it = res_vi.value.field(ty, 0, 8);
4040 const res_lo64_vi = try res_lo64_it.only(isel);
4041 if (try res_lo64_vi.?.defReg(isel)) |res_lo64_ra| {
4042 var src_lo64_it = src_vi.field(ty, 0, 8);
4043 const src_lo64_vi = try src_lo64_it.only(isel);
4044 try src_lo64_vi.?.liveOut(isel, res_lo64_ra);
4045 }
4046 },
4047 128 => {
4048 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
4049 const src_vi = try isel.use(un_op);
4050 const src_mat = try src_vi.matReg(isel);
4051 const neg_zero_ra = try isel.allocVecReg();
4052 defer isel.freeReg(neg_zero_ra);
4053 try isel.emit(.eor(res_ra.@"16b"(), src_mat.ra.@"16b"(), .{ .register = neg_zero_ra.@"16b"() }));
4054 try isel.literals.appendNTimes(gpa, 0, -%isel.literals.items.len % 4);
4055 try isel.literal_relocs.append(gpa, .{
4056 .label = @intCast(isel.instructions.items.len),
4057 });
4058 try isel.emit(.ldr(neg_zero_ra.q(), .{
4059 .literal = @intCast((isel.instructions.items.len + 1 + isel.literals.items.len) << 2),
4060 }));
4061 try isel.emitLiteral(&(.{0} ** 15 ++ .{0x80}));
4062 try src_mat.finish(isel);
4063 },
4064 }
4065 }
4066 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4067 },
4068 .cmp_lt, .cmp_lte, .cmp_eq, .cmp_gte, .cmp_gt, .cmp_neq => |air_tag| {
4069 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
4070 defer res_vi.value.deref(isel);
4071
4072 var bin_op = air.data(air.inst_index).bin_op;
4073 const ty = isel.air.typeOf(bin_op.lhs, ip);
4074 if (!ty.isRuntimeFloat()) {
4075 const int_info: std.builtin.Type.Int = if (ty.toIntern() == .bool_type)
4076 .{ .signedness = .unsigned, .bits = 1 }
4077 else if (ty.isAbiInt(zcu))
4078 ty.intInfo(zcu)
4079 else if (ty.isPtrAtRuntime(zcu))
4080 .{ .signedness = .unsigned, .bits = 64 }
4081 else
4082 return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
4083 if (int_info.bits > 256) return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
4084
4085 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
4086 try isel.emit(.csinc(res_ra.w(), .wzr, .wzr, .invert(cond: switch (air_tag) {
4087 else => unreachable,
4088 .cmp_lt => switch (int_info.signedness) {
4089 .signed => .lt,
4090 .unsigned => .lo,
4091 },
4092 .cmp_lte => switch (int_info.bits) {
4093 else => unreachable,
4094 1...64 => switch (int_info.signedness) {
4095 .signed => .le,
4096 .unsigned => .ls,
4097 },
4098 65...128 => {
4099 std.mem.swap(Air.Inst.Ref, &bin_op.lhs, &bin_op.rhs);
4100 continue :cond .cmp_gte;
4101 },
4102 },
4103 .cmp_eq => .eq,
4104 .cmp_gte => switch (int_info.signedness) {
4105 .signed => .ge,
4106 .unsigned => .hs,
4107 },
4108 .cmp_gt => switch (int_info.bits) {
4109 else => unreachable,
4110 1...64 => switch (int_info.signedness) {
4111 .signed => .gt,
4112 .unsigned => .hi,
4113 },
4114 65...128 => {
4115 std.mem.swap(Air.Inst.Ref, &bin_op.lhs, &bin_op.rhs);
4116 continue :cond .cmp_lt;
4117 },
4118 },
4119 .cmp_neq => .ne,
4120 })));
4121
4122 const lhs_vi = try isel.use(bin_op.lhs);
4123 const rhs_vi = try isel.use(bin_op.rhs);
4124 var part_offset = lhs_vi.size(isel);
4125 while (part_offset > 0) {
4126 const part_size = @min(part_offset, 8);
4127 part_offset -= part_size;
4128 var lhs_part_it = lhs_vi.field(ty, part_offset, part_size);
4129 const lhs_part_vi = try lhs_part_it.only(isel);
4130 const lhs_part_mat = try lhs_part_vi.?.matReg(isel);
4131 var rhs_part_it = rhs_vi.field(ty, part_offset, part_size);
4132 const rhs_part_vi = try rhs_part_it.only(isel);
4133 const rhs_part_mat = try rhs_part_vi.?.matReg(isel);
4134 try isel.emit(switch (part_size) {
4135 else => unreachable,
4136 1...4 => switch (part_offset) {
4137 0 => .subs(.wzr, lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }),
4138 else => switch (air_tag) {
4139 else => unreachable,
4140 .cmp_lt, .cmp_lte, .cmp_gte, .cmp_gt => .sbcs(
4141 .wzr,
4142 lhs_part_mat.ra.w(),
4143 rhs_part_mat.ra.w(),
4144 ),
4145 .cmp_eq, .cmp_neq => .ccmp(
4146 lhs_part_mat.ra.w(),
4147 .{ .register = rhs_part_mat.ra.w() },
4148 .{ .n = false, .z = false, .c = false, .v = false },
4149 .eq,
4150 ),
4151 },
4152 },
4153 5...8 => switch (part_offset) {
4154 0 => .subs(.xzr, lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }),
4155 else => switch (air_tag) {
4156 else => unreachable,
4157 .cmp_lt, .cmp_lte, .cmp_gte, .cmp_gt => .sbcs(
4158 .xzr,
4159 lhs_part_mat.ra.x(),
4160 rhs_part_mat.ra.x(),
4161 ),
4162 .cmp_eq, .cmp_neq => .ccmp(
4163 lhs_part_mat.ra.x(),
4164 .{ .register = rhs_part_mat.ra.x() },
4165 .{ .n = false, .z = false, .c = false, .v = false },
4166 .eq,
4167 ),
4168 },
4169 },
4170 });
4171 try rhs_part_mat.finish(isel);
4172 try lhs_part_mat.finish(isel);
4173 }
4174 } else switch (ty.floatBits(isel.target)) {
4175 else => unreachable,
4176 16, 32, 64 => |bits| {
4177 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
4178 const need_fcvt = switch (bits) {
4179 else => unreachable,
4180 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
4181 32, 64 => false,
4182 };
4183 try isel.emit(.csinc(res_ra.w(), .wzr, .wzr, .invert(switch (air_tag) {
4184 else => unreachable,
4185 .cmp_lt => .lo,
4186 .cmp_lte => .ls,
4187 .cmp_eq => .eq,
4188 .cmp_gte => .ge,
4189 .cmp_gt => .gt,
4190 .cmp_neq => .ne,
4191 })));
4192
4193 const lhs_vi = try isel.use(bin_op.lhs);
4194 const rhs_vi = try isel.use(bin_op.rhs);
4195 const lhs_mat = try lhs_vi.matReg(isel);
4196 const rhs_mat = try rhs_vi.matReg(isel);
4197 const lhs_ra = if (need_fcvt) try isel.allocVecReg() else lhs_mat.ra;
4198 defer if (need_fcvt) isel.freeReg(lhs_ra);
4199 const rhs_ra = if (need_fcvt) try isel.allocVecReg() else rhs_mat.ra;
4200 defer if (need_fcvt) isel.freeReg(rhs_ra);
4201 try isel.emit(bits: switch (bits) {
4202 else => unreachable,
4203 16 => if (need_fcvt)
4204 continue :bits 32
4205 else
4206 .fcmp(lhs_ra.h(), .{ .register = rhs_ra.h() }),
4207 32 => .fcmp(lhs_ra.s(), .{ .register = rhs_ra.s() }),
4208 64 => .fcmp(lhs_ra.d(), .{ .register = rhs_ra.d() }),
4209 });
4210 if (need_fcvt) {
4211 try isel.emit(.fcvt(rhs_ra.s(), rhs_mat.ra.h()));
4212 try isel.emit(.fcvt(lhs_ra.s(), lhs_mat.ra.h()));
4213 }
4214 try rhs_mat.finish(isel);
4215 try lhs_mat.finish(isel);
4216 },
4217 80, 128 => |bits| {
4218 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
4219
4220 try call.prepareReturn(isel);
4221 try call.returnFill(isel, .r0);
4222 try isel.emit(.csinc(res_ra.w(), .wzr, .wzr, .invert(cond: switch (air_tag) {
4223 else => unreachable,
4224 .cmp_lt => .lt,
4225 .cmp_lte => .le,
4226 .cmp_eq => .eq,
4227 .cmp_gte => {
4228 std.mem.swap(Air.Inst.Ref, &bin_op.lhs, &bin_op.rhs);
4229 continue :cond .cmp_lte;
4230 },
4231 .cmp_gt => {
4232 std.mem.swap(Air.Inst.Ref, &bin_op.lhs, &bin_op.rhs);
4233 continue :cond .cmp_lt;
4234 },
4235 .cmp_neq => .ne,
4236 })));
4237 try isel.emit(.subs(.wzr, .w0, .{ .immediate = 0 }));
4238 try call.finishReturn(isel);
4239
4240 try call.prepareCallee(isel);
4241 try isel.global_relocs.append(gpa, .{
4242 .global = switch (bits) {
4243 else => unreachable,
4244 16 => "__cmphf2",
4245 32 => "__cmpsf2",
4246 64 => "__cmpdf2",
4247 80 => "__cmpxf2",
4248 128 => "__cmptf2",
4249 },
4250 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
4251 });
4252 try isel.emit(.bl(0));
4253 try call.finishCallee(isel);
4254
4255 try call.prepareParams(isel);
4256 const lhs_vi = try isel.use(bin_op.lhs);
4257 const rhs_vi = try isel.use(bin_op.rhs);
4258 switch (bits) {
4259 else => unreachable,
4260 16, 32, 64, 128 => {
4261 try call.paramLiveOut(isel, rhs_vi, .v1);
4262 try call.paramLiveOut(isel, lhs_vi, .v0);
4263 },
4264 80 => {
4265 var rhs_hi16_it = rhs_vi.field(ty, 8, 8);
4266 const rhs_hi16_vi = try rhs_hi16_it.only(isel);
4267 try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3);
4268 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
4269 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
4270 try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2);
4271 var lhs_hi16_it = lhs_vi.field(ty, 8, 8);
4272 const lhs_hi16_vi = try lhs_hi16_it.only(isel);
4273 try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1);
4274 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
4275 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
4276 try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0);
4277 },
4278 }
4279 try call.finishParams(isel);
4280 },
4281 }
4282 }
4283 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4284 },
4285 .cond_br => {
4286 const pl_op = air.data(air.inst_index).pl_op;
4287 const extra = isel.air.extraData(Air.CondBr, pl_op.payload);
4288
4289 try isel.body(@ptrCast(isel.air.extra.items[extra.end + extra.data.then_body_len ..][0..extra.data.else_body_len]));
4290 const else_label = isel.instructions.items.len;
4291 const else_live_registers = isel.live_registers;
4292 try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.then_body_len]));
4293 try isel.merge(&else_live_registers, .{});
4294
4295 const cond_vi = try isel.use(pl_op.operand);
4296 const cond_mat = try cond_vi.matReg(isel);
4297 try isel.emit(.tbz(
4298 cond_mat.ra.x(),
4299 0,
4300 @intCast((isel.instructions.items.len + 1 - else_label) << 2),
4301 ));
4302 try cond_mat.finish(isel);
4303
4304 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4305 },
4306 .switch_br => {
4307 const switch_br = isel.air.unwrapSwitch(air.inst_index);
4308 const cond_ty = isel.air.typeOf(switch_br.operand, ip);
4309 const cond_int_info: std.builtin.Type.Int = if (cond_ty.toIntern() == .bool_type)
4310 .{ .signedness = .unsigned, .bits = 1 }
4311 else if (cond_ty.isAbiInt(zcu))
4312 cond_ty.intInfo(zcu)
4313 else
4314 return isel.fail("bad switch cond {f}", .{isel.fmtType(cond_ty)});
4315
4316 var final_case = true;
4317 if (switch_br.else_body_len > 0) {
4318 var cases_it = switch_br.iterateCases();
4319 while (cases_it.next()) |_| {}
4320 try isel.body(cases_it.elseBody());
4321 assert(final_case);
4322 final_case = false;
4323 }
4324 const zero_reg: Register = switch (cond_int_info.bits) {
4325 else => unreachable,
4326 1...32 => .wzr,
4327 33...64 => .xzr,
4328 };
4329 var cond_mat: ?Value.Materialize = null;
4330 var cond_reg: Register = undefined;
4331 var temp_reg: Register = undefined;
4332 var cases_it = switch_br.iterateCases();
4333 while (cases_it.next()) |case| {
4334 const next_label = isel.instructions.items.len;
4335 const next_live_registers = isel.live_registers;
4336 try isel.body(case.body);
4337 if (final_case) {
4338 final_case = false;
4339 continue;
4340 }
4341 try isel.merge(&next_live_registers, .{});
4342 if (cond_mat == null) {
4343 var cond_vi = try isel.use(switch_br.operand);
4344 cond_mat = try cond_vi.matReg(isel);
4345 const temp_ra = try isel.allocIntReg();
4346 cond_reg, temp_reg = switch (cond_int_info.bits) {
4347 else => unreachable,
4348 1...32 => .{ cond_mat.?.ra.w(), temp_ra.w() },
4349 33...64 => .{ cond_mat.?.ra.x(), temp_ra.x() },
4350 };
4351 }
4352 if (case.ranges.len == 0 and case.items.len == 1 and Constant.fromInterned(
4353 case.items[0].toInterned().?,
4354 ).orderAgainstZero(zcu).compare(.eq)) {
4355 try isel.emit(.cbnz(
4356 cond_reg,
4357 @intCast((isel.instructions.items.len + 1 - next_label) << 2),
4358 ));
4359 continue;
4360 }
4361 try isel.emit(.@"b."(
4362 .invert(switch (case.ranges.len) {
4363 0 => .eq,
4364 else => .ls,
4365 }),
4366 @intCast((isel.instructions.items.len + 1 - next_label) << 2),
4367 ));
4368 var case_range_index = case.ranges.len;
4369 while (case_range_index > 0) {
4370 case_range_index -= 1;
4371
4372 const low_val: Constant = .fromInterned(case.ranges[case_range_index][0].toInterned().?);
4373 var low_bigint_space: Constant.BigIntSpace = undefined;
4374 const low_bigint = low_val.toBigInt(&low_bigint_space, zcu);
4375 const low_int: i64 = if (low_bigint.positive) @bitCast(
4376 low_bigint.toInt(u64) catch
4377 return isel.fail("too big case range start: {f}", .{isel.fmtConstant(low_val)}),
4378 ) else low_bigint.toInt(i64) catch
4379 return isel.fail("too big case range start: {f}", .{isel.fmtConstant(low_val)});
4380
4381 const high_val: Constant = .fromInterned(case.ranges[case_range_index][1].toInterned().?);
4382 var high_bigint_space: Constant.BigIntSpace = undefined;
4383 const high_bigint = high_val.toBigInt(&high_bigint_space, zcu);
4384 const high_int: i64 = if (high_bigint.positive) @bitCast(
4385 high_bigint.toInt(u64) catch
4386 return isel.fail("too big case range end: {f}", .{isel.fmtConstant(high_val)}),
4387 ) else high_bigint.toInt(i64) catch
4388 return isel.fail("too big case range end: {f}", .{isel.fmtConstant(high_val)});
4389
4390 const delta_int = high_int -% low_int;
4391 if (case_range_index > 0) {
4392 return isel.fail("case range", .{});
4393 } else if (case.items.len > 0) {
4394 return isel.fail("case range", .{});
4395 } else {
4396 const adjusted_reg = switch (low_int) {
4397 0 => cond_reg,
4398 else => temp_reg,
4399 };
4400
4401 if (std.math.cast(u12, delta_int)) |pos_imm| try isel.emit(.subs(
4402 zero_reg,
4403 adjusted_reg,
4404 .{ .immediate = pos_imm },
4405 )) else if (std.math.cast(u12, -delta_int)) |neg_imm| try isel.emit(.adds(
4406 zero_reg,
4407 adjusted_reg,
4408 .{ .immediate = neg_imm },
4409 )) else if (if (@as(i12, @truncate(delta_int)) == 0)
4410 std.math.cast(u12, delta_int >> 12)
4411 else
4412 null) |pos_imm_lsr_12| try isel.emit(.subs(
4413 zero_reg,
4414 adjusted_reg,
4415 .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } },
4416 )) else if (if (@as(i12, @truncate(-delta_int)) == 0)
4417 std.math.cast(u12, -delta_int >> 12)
4418 else
4419 null) |neg_imm_lsr_12| try isel.emit(.adds(
4420 zero_reg,
4421 adjusted_reg,
4422 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
4423 )) else {
4424 try isel.movImmediate(temp_reg, @bitCast(delta_int));
4425 try isel.emit(.subs(zero_reg, adjusted_reg, .{ .register = temp_reg }));
4426 }
4427
4428 switch (low_int) {
4429 0 => {},
4430 else => {
4431 if (std.math.cast(u12, low_int)) |pos_imm| try isel.emit(.sub(
4432 adjusted_reg,
4433 cond_reg,
4434 .{ .immediate = pos_imm },
4435 )) else if (std.math.cast(u12, -low_int)) |neg_imm| try isel.emit(.add(
4436 adjusted_reg,
4437 cond_reg,
4438 .{ .immediate = neg_imm },
4439 )) else if (if (@as(i12, @truncate(low_int)) == 0)
4440 std.math.cast(u12, low_int >> 12)
4441 else
4442 null) |pos_imm_lsr_12| try isel.emit(.sub(
4443 adjusted_reg,
4444 cond_reg,
4445 .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } },
4446 )) else if (if (@as(i12, @truncate(-low_int)) == 0)
4447 std.math.cast(u12, -low_int >> 12)
4448 else
4449 null) |neg_imm_lsr_12| try isel.emit(.add(
4450 adjusted_reg,
4451 cond_reg,
4452 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
4453 )) else {
4454 try isel.movImmediate(temp_reg, @bitCast(low_int));
4455 try isel.emit(.subs(adjusted_reg, cond_reg, .{ .register = temp_reg }));
4456 }
4457 },
4458 }
4459 }
4460 }
4461 var case_item_index = case.items.len;
4462 while (case_item_index > 0) {
4463 case_item_index -= 1;
4464
4465 const item_val: Constant = .fromInterned(case.items[case_item_index].toInterned().?);
4466 var item_bigint_space: Constant.BigIntSpace = undefined;
4467 const item_bigint = item_val.toBigInt(&item_bigint_space, zcu);
4468 const item_int: i64 = if (item_bigint.positive) @bitCast(
4469 item_bigint.toInt(u64) catch
4470 return isel.fail("too big case item: {f}", .{isel.fmtConstant(item_val)}),
4471 ) else item_bigint.toInt(i64) catch
4472 return isel.fail("too big case item: {f}", .{isel.fmtConstant(item_val)});
4473
4474 if (case_item_index > 0) {
4475 if (std.math.cast(u5, item_int)) |pos_imm| try isel.emit(.ccmp(
4476 cond_reg,
4477 .{ .immediate = pos_imm },
4478 .{ .n = false, .z = true, .c = false, .v = false },
4479 .ne,
4480 )) else if (std.math.cast(u5, -item_int)) |neg_imm| try isel.emit(.ccmn(
4481 cond_reg,
4482 .{ .immediate = neg_imm },
4483 .{ .n = false, .z = true, .c = false, .v = false },
4484 .ne,
4485 )) else {
4486 try isel.movImmediate(temp_reg, @bitCast(item_int));
4487 try isel.emit(.ccmp(
4488 cond_reg,
4489 .{ .register = temp_reg },
4490 .{ .n = false, .z = true, .c = false, .v = false },
4491 .ne,
4492 ));
4493 }
4494 } else {
4495 if (std.math.cast(u12, item_int)) |pos_imm| try isel.emit(.subs(
4496 zero_reg,
4497 cond_reg,
4498 .{ .immediate = pos_imm },
4499 )) else if (std.math.cast(u12, -item_int)) |neg_imm| try isel.emit(.adds(
4500 zero_reg,
4501 cond_reg,
4502 .{ .immediate = neg_imm },
4503 )) else if (if (@as(i12, @truncate(item_int)) == 0)
4504 std.math.cast(u12, item_int >> 12)
4505 else
4506 null) |pos_imm_lsr_12| try isel.emit(.subs(
4507 zero_reg,
4508 cond_reg,
4509 .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } },
4510 )) else if (if (@as(i12, @truncate(-item_int)) == 0)
4511 std.math.cast(u12, -item_int >> 12)
4512 else
4513 null) |neg_imm_lsr_12| try isel.emit(.adds(
4514 zero_reg,
4515 cond_reg,
4516 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
4517 )) else {
4518 try isel.movImmediate(temp_reg, @bitCast(item_int));
4519 try isel.emit(.subs(zero_reg, cond_reg, .{ .register = temp_reg }));
4520 }
4521 }
4522 }
4523 }
4524 if (cond_mat) |mat| {
4525 try mat.finish(isel);
4526 isel.freeReg(temp_reg.alias);
4527 }
4528 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4529 },
4530 .@"try", .try_cold => {
4531 const pl_op = air.data(air.inst_index).pl_op;
4532 const extra = isel.air.extraData(Air.Try, pl_op.payload);
4533 const error_union_ty = isel.air.typeOf(pl_op.operand, ip);
4534 const error_union_info = ip.indexToKey(error_union_ty.toIntern()).error_union_type;
4535 const payload_ty: ZigType = .fromInterned(error_union_info.payload_type);
4536
4537 const error_union_vi = try isel.use(pl_op.operand);
4538 if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| {
4539 defer payload_vi.value.deref(isel);
4540
4541 var payload_part_it = error_union_vi.field(
4542 error_union_ty,
4543 codegen.errUnionPayloadOffset(payload_ty, zcu),
4544 payload_vi.value.size(isel),
4545 );
4546 const payload_part_vi = try payload_part_it.only(isel);
4547 try payload_vi.value.copy(isel, payload_ty, payload_part_vi.?);
4548 }
4549
4550 const cont_label = isel.instructions.items.len;
4551 const cont_live_registers = isel.live_registers;
4552 try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
4553 try isel.merge(&cont_live_registers, .{});
4554
4555 var error_set_part_it = error_union_vi.field(
4556 error_union_ty,
4557 codegen.errUnionErrorOffset(payload_ty, zcu),
4558 ZigType.fromInterned(error_union_info.error_set_type).abiSize(zcu),
4559 );
4560 const error_set_part_vi = try error_set_part_it.only(isel);
4561 const error_set_part_mat = try error_set_part_vi.?.matReg(isel);
4562 try isel.emit(.cbz(
4563 switch (error_set_part_vi.?.size(isel)) {
4564 else => unreachable,
4565 1...4 => error_set_part_mat.ra.w(),
4566 5...8 => error_set_part_mat.ra.x(),
4567 },
4568 @intCast((isel.instructions.items.len + 1 - cont_label) << 2),
4569 ));
4570 try error_set_part_mat.finish(isel);
4571
4572 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4573 },
4574 .dbg_stmt => {
4575 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4576 },
4577 .dbg_empty_stmt => {
4578 try isel.emit(.nop());
4579 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4580 },
4581 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => {
4582 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4583 },
4584 .is_null, .is_non_null => |air_tag| {
4585 if (isel.live_values.fetchRemove(air.inst_index)) |is_vi| unused: {
4586 defer is_vi.value.deref(isel);
4587 const is_ra = try is_vi.value.defReg(isel) orelse break :unused;
4588
4589 const un_op = air.data(air.inst_index).un_op;
4590 const opt_ty = isel.air.typeOf(un_op, ip);
4591 const payload_ty = opt_ty.optionalChild(zcu);
4592 const payload_size = payload_ty.abiSize(zcu);
4593 const has_value_offset, const has_value_size = if (!opt_ty.optionalReprIsPayload(zcu))
4594 .{ payload_size, 1 }
4595 else if (payload_ty.isSlice(zcu))
4596 .{ 0, 8 }
4597 else
4598 .{ 0, payload_size };
4599
4600 try isel.emit(.csinc(is_ra.w(), .wzr, .wzr, .invert(switch (air_tag) {
4601 else => unreachable,
4602 .is_null => .eq,
4603 .is_non_null => .ne,
4604 })));
4605 const opt_vi = try isel.use(un_op);
4606 var has_value_part_it = opt_vi.field(opt_ty, has_value_offset, has_value_size);
4607 const has_value_part_vi = try has_value_part_it.only(isel);
4608 const has_value_part_mat = try has_value_part_vi.?.matReg(isel);
4609 try isel.emit(switch (has_value_size) {
4610 else => unreachable,
4611 1...4 => .subs(.wzr, has_value_part_mat.ra.w(), .{ .immediate = 0 }),
4612 5...8 => .subs(.xzr, has_value_part_mat.ra.x(), .{ .immediate = 0 }),
4613 });
4614 try has_value_part_mat.finish(isel);
4615 }
4616 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4617 },
4618 .is_err, .is_non_err => |air_tag| {
4619 if (isel.live_values.fetchRemove(air.inst_index)) |is_vi| unused: {
4620 defer is_vi.value.deref(isel);
4621 const is_ra = try is_vi.value.defReg(isel) orelse break :unused;
4622
4623 const un_op = air.data(air.inst_index).un_op;
4624 const error_union_ty = isel.air.typeOf(un_op, ip);
4625 const error_union_info = ip.indexToKey(error_union_ty.toIntern()).error_union_type;
4626 const error_set_ty: ZigType = .fromInterned(error_union_info.error_set_type);
4627 const payload_ty: ZigType = .fromInterned(error_union_info.payload_type);
4628 const error_set_offset = codegen.errUnionErrorOffset(payload_ty, zcu);
4629 const error_set_size = error_set_ty.abiSize(zcu);
4630
4631 try isel.emit(.csinc(is_ra.w(), .wzr, .wzr, .invert(switch (air_tag) {
4632 else => unreachable,
4633 .is_err => .ne,
4634 .is_non_err => .eq,
4635 })));
4636 const error_union_vi = try isel.use(un_op);
4637 var error_set_part_it = error_union_vi.field(error_union_ty, error_set_offset, error_set_size);
4638 const error_set_part_vi = try error_set_part_it.only(isel);
4639 const error_set_part_mat = try error_set_part_vi.?.matReg(isel);
4640 try isel.emit(.ands(.wzr, error_set_part_mat.ra.w(), .{ .immediate = .{
4641 .N = .word,
4642 .immr = 0,
4643 .imms = @intCast(8 * error_set_size - 1),
4644 } }));
4645 try error_set_part_mat.finish(isel);
4646 }
4647 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4648 },
4649 .load => {
4650 const ty_op = air.data(air.inst_index).ty_op;
4651 const ptr_ty = isel.air.typeOf(ty_op.operand, ip);
4652 const ptr_info = ptr_ty.ptrInfo(zcu);
4653 if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed load", .{});
4654
4655 if (ptr_info.flags.is_volatile) _ = try isel.use(air.inst_index.toRef());
4656 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
4657 defer dst_vi.value.deref(isel);
4658 switch (dst_vi.value.size(isel)) {
4659 0 => unreachable,
4660 1...Value.max_parts => {
4661 const ptr_vi = try isel.use(ty_op.operand);
4662 const ptr_mat = try ptr_vi.matReg(isel);
4663 _ = try dst_vi.value.load(isel, ty_op.ty.toType(), ptr_mat.ra, .{
4664 .@"volatile" = ptr_info.flags.is_volatile,
4665 });
4666 try ptr_mat.finish(isel);
4667 },
4668 else => |size| {
4669 try dst_vi.value.defAddr(isel, .fromInterned(ptr_info.child), null, comptime &.initFill(.free)) orelse break :unused;
4670
4671 try call.prepareReturn(isel);
4672 try call.finishReturn(isel);
4673
4674 try call.prepareCallee(isel);
4675 try isel.global_relocs.append(gpa, .{
4676 .global = "memcpy",
4677 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
4678 });
4679 try isel.emit(.bl(0));
4680 try call.finishCallee(isel);
4681
4682 try call.prepareParams(isel);
4683 const ptr_vi = try isel.use(ty_op.operand);
4684 try isel.movImmediate(.x2, size);
4685 try call.paramLiveOut(isel, ptr_vi, .r1);
4686 try call.paramAddress(isel, dst_vi.value, .r0);
4687 try call.finishParams(isel);
4688 },
4689 }
4690 }
4691
4692 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4693 },
4694 .ret, .ret_safe => {
4695 assert(isel.blocks.keys()[0] == Block.main);
4696 try isel.blocks.values()[0].branch(isel);
4697 if (isel.live_values.get(Block.main)) |ret_vi| {
4698 const un_op = air.data(air.inst_index).un_op;
4699 const src_vi = try isel.use(un_op);
4700 switch (ret_vi.parent(isel)) {
4701 .unallocated, .stack_slot => if (ret_vi.hint(isel)) |ret_ra| {
4702 try src_vi.liveOut(isel, ret_ra);
4703 } else {
4704 var ret_part_it = ret_vi.parts(isel);
4705 var src_part_it = src_vi.parts(isel);
4706 if (src_part_it.only()) |_| {
4707 try isel.values.ensureUnusedCapacity(gpa, ret_part_it.remaining);
4708 src_vi.setParts(isel, ret_part_it.remaining);
4709 while (ret_part_it.next()) |ret_part_vi| {
4710 const src_part_vi = src_vi.addPart(
4711 isel,
4712 ret_part_vi.get(isel).offset_from_parent,
4713 ret_part_vi.size(isel),
4714 );
4715 switch (ret_part_vi.signedness(isel)) {
4716 .signed => src_part_vi.setSignedness(isel, .signed),
4717 .unsigned => {},
4718 }
4719 if (ret_part_vi.isVector(isel)) src_part_vi.setIsVector(isel);
4720 }
4721 ret_part_it = ret_vi.parts(isel);
4722 src_part_it = src_vi.parts(isel);
4723 }
4724 while (ret_part_it.next()) |ret_part_vi| {
4725 const src_part_vi = src_part_it.next().?;
4726 assert(ret_part_vi.get(isel).offset_from_parent == src_part_vi.get(isel).offset_from_parent);
4727 assert(ret_part_vi.size(isel) == src_part_vi.size(isel));
4728 try src_part_vi.liveOut(isel, ret_part_vi.hint(isel).?);
4729 }
4730 },
4731 .value, .constant => unreachable,
4732 .address => |address_vi| {
4733 const ptr_mat = try address_vi.matReg(isel);
4734 try src_vi.store(isel, isel.air.typeOf(un_op, ip), ptr_mat.ra, .{});
4735 try ptr_mat.finish(isel);
4736 },
4737 }
4738 }
4739 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4740 },
4741 .ret_load => {
4742 const un_op = air.data(air.inst_index).un_op;
4743 const ptr_ty = isel.air.typeOf(un_op, ip);
4744 const ptr_info = ptr_ty.ptrInfo(zcu);
4745 if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed load", .{});
4746
4747 assert(isel.blocks.keys()[0] == Block.main);
4748 try isel.blocks.values()[0].branch(isel);
4749 if (isel.live_values.get(Block.main)) |ret_vi| switch (ret_vi.parent(isel)) {
4750 .unallocated, .stack_slot => {
4751 var ret_part_it: Value.PartIterator = if (ret_vi.hint(isel)) |_| .initOne(ret_vi) else ret_vi.parts(isel);
4752 while (ret_part_it.next()) |ret_part_vi| try ret_part_vi.liveOut(isel, ret_part_vi.hint(isel).?);
4753 const ptr_vi = try isel.use(un_op);
4754 const ptr_mat = try ptr_vi.matReg(isel);
4755 _ = try ret_vi.load(isel, .fromInterned(ptr_info.child), ptr_mat.ra, .{});
4756 try ptr_mat.finish(isel);
4757 },
4758 .value, .constant => unreachable,
4759 .address => {},
4760 };
4761 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4762 },
4763 .store, .store_safe, .atomic_store_unordered => {
4764 const bin_op = air.data(air.inst_index).bin_op;
4765 const ptr_ty = isel.air.typeOf(bin_op.lhs, ip);
4766 const ptr_info = ptr_ty.ptrInfo(zcu);
4767 if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed store", .{});
4768 if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val)) {
4769 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4770 break :air_tag;
4771 };
4772
4773 const src_vi = try isel.use(bin_op.rhs);
4774 const size = src_vi.size(isel);
4775 if (ZigType.fromInterned(ptr_info.child).zigTypeTag(zcu) != .@"union") switch (size) {
4776 0 => unreachable,
4777 1...Value.max_parts => {
4778 const ptr_vi = try isel.use(bin_op.lhs);
4779 const ptr_mat = try ptr_vi.matReg(isel);
4780 try src_vi.store(isel, isel.air.typeOf(bin_op.rhs, ip), ptr_mat.ra, .{
4781 .@"volatile" = ptr_info.flags.is_volatile,
4782 });
4783 try ptr_mat.finish(isel);
4784
4785 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4786 break :air_tag;
4787 },
4788 else => {},
4789 };
4790 try call.prepareReturn(isel);
4791 try call.finishReturn(isel);
4792
4793 try call.prepareCallee(isel);
4794 try isel.global_relocs.append(gpa, .{
4795 .global = "memcpy",
4796 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
4797 });
4798 try isel.emit(.bl(0));
4799 try call.finishCallee(isel);
4800
4801 try call.prepareParams(isel);
4802 const ptr_vi = try isel.use(bin_op.lhs);
4803 try isel.movImmediate(.x2, size);
4804 try call.paramAddress(isel, src_vi, .r1);
4805 try call.paramLiveOut(isel, ptr_vi, .r0);
4806 try call.finishParams(isel);
4807
4808 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4809 },
4810 .unreach => if (air.next()) |next_air_tag| continue :air_tag next_air_tag,
4811 .fptrunc, .fpext => {
4812 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
4813 defer dst_vi.value.deref(isel);
4814
4815 const ty_op = air.data(air.inst_index).ty_op;
4816 const dst_ty = ty_op.ty.toType();
4817 const dst_bits = dst_ty.floatBits(isel.target);
4818 const src_ty = isel.air.typeOf(ty_op.operand, ip);
4819 const src_bits = src_ty.floatBits(isel.target);
4820 assert(dst_bits != src_bits);
4821 switch (@max(dst_bits, src_bits)) {
4822 else => unreachable,
4823 16, 32, 64 => {
4824 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
4825 const src_vi = try isel.use(ty_op.operand);
4826 const src_mat = try src_vi.matReg(isel);
4827 try isel.emit(.fcvt(switch (dst_bits) {
4828 else => unreachable,
4829 16 => dst_ra.h(),
4830 32 => dst_ra.s(),
4831 64 => dst_ra.d(),
4832 }, switch (src_bits) {
4833 else => unreachable,
4834 16 => src_mat.ra.h(),
4835 32 => src_mat.ra.s(),
4836 64 => src_mat.ra.d(),
4837 }));
4838 try src_mat.finish(isel);
4839 },
4840 80, 128 => {
4841 try call.prepareReturn(isel);
4842 switch (dst_bits) {
4843 else => unreachable,
4844 16, 32, 64, 128 => try call.returnLiveIn(isel, dst_vi.value, .v0),
4845 80 => {
4846 var dst_hi16_it = dst_vi.value.field(dst_ty, 8, 8);
4847 const dst_hi16_vi = try dst_hi16_it.only(isel);
4848 try call.returnLiveIn(isel, dst_hi16_vi.?, .r1);
4849 var dst_lo64_it = dst_vi.value.field(dst_ty, 0, 8);
4850 const dst_lo64_vi = try dst_lo64_it.only(isel);
4851 try call.returnLiveIn(isel, dst_lo64_vi.?, .r0);
4852 },
4853 }
4854 try call.finishReturn(isel);
4855
4856 try call.prepareCallee(isel);
4857 try isel.global_relocs.append(gpa, .{
4858 .global = switch (dst_bits) {
4859 else => unreachable,
4860 16 => switch (src_bits) {
4861 else => unreachable,
4862 32 => "__truncsfhf2",
4863 64 => "__truncdfhf2",
4864 80 => "__truncxfhf2",
4865 128 => "__trunctfhf2",
4866 },
4867 32 => switch (src_bits) {
4868 else => unreachable,
4869 16 => "__extendhfsf2",
4870 64 => "__truncdfsf2",
4871 80 => "__truncxfsf2",
4872 128 => "__trunctfsf2",
4873 },
4874 64 => switch (src_bits) {
4875 else => unreachable,
4876 16 => "__extendhfdf2",
4877 32 => "__extendsfdf2",
4878 80 => "__truncxfdf2",
4879 128 => "__trunctfdf2",
4880 },
4881 80 => switch (src_bits) {
4882 else => unreachable,
4883 16 => "__extendhfxf2",
4884 32 => "__extendsfxf2",
4885 64 => "__extenddfxf2",
4886 128 => "__trunctfxf2",
4887 },
4888 128 => switch (src_bits) {
4889 else => unreachable,
4890 16 => "__extendhftf2",
4891 32 => "__extendsftf2",
4892 64 => "__extenddftf2",
4893 80 => "__extendxftf2",
4894 },
4895 },
4896 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
4897 });
4898 try isel.emit(.bl(0));
4899 try call.finishCallee(isel);
4900
4901 try call.prepareParams(isel);
4902 const src_vi = try isel.use(ty_op.operand);
4903 switch (src_bits) {
4904 else => unreachable,
4905 16, 32, 64, 128 => try call.paramLiveOut(isel, src_vi, .v0),
4906 80 => {
4907 var src_hi16_it = src_vi.field(src_ty, 8, 8);
4908 const src_hi16_vi = try src_hi16_it.only(isel);
4909 try call.paramLiveOut(isel, src_hi16_vi.?, .r1);
4910 var src_lo64_it = src_vi.field(src_ty, 0, 8);
4911 const src_lo64_vi = try src_lo64_it.only(isel);
4912 try call.paramLiveOut(isel, src_lo64_vi.?, .r0);
4913 },
4914 }
4915 try call.finishParams(isel);
4916 },
4917 }
4918 }
4919 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4920 },
4921 .intcast => |air_tag| {
4922 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
4923 defer dst_vi.value.deref(isel);
4924
4925 const ty_op = air.data(air.inst_index).ty_op;
4926 const dst_ty = ty_op.ty.toType();
4927 const dst_int_info = dst_ty.intInfo(zcu);
4928 const src_ty = isel.air.typeOf(ty_op.operand, ip);
4929 const src_int_info = src_ty.intInfo(zcu);
4930 const can_be_negative = dst_int_info.signedness == .signed and
4931 src_int_info.signedness == .signed;
4932 if ((dst_int_info.bits <= 8 and src_int_info.bits <= 8) or
4933 (dst_int_info.bits > 8 and dst_int_info.bits <= 16 and
4934 src_int_info.bits > 8 and src_int_info.bits <= 16) or
4935 (dst_int_info.bits > 16 and dst_int_info.bits <= 32 and
4936 src_int_info.bits > 16 and src_int_info.bits <= 32) or
4937 (dst_int_info.bits > 32 and dst_int_info.bits <= 64 and
4938 src_int_info.bits > 32 and src_int_info.bits <= 64) or
4939 (dst_int_info.bits > 64 and src_int_info.bits > 64 and
4940 (dst_int_info.bits - 1) / 128 == (src_int_info.bits - 1) / 128))
4941 {
4942 try dst_vi.value.move(isel, ty_op.operand);
4943 } else if (dst_int_info.bits <= 32 and src_int_info.bits <= 64) {
4944 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
4945 const src_vi = try isel.use(ty_op.operand);
4946 const src_mat = try src_vi.matReg(isel);
4947 try isel.emit(.orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }));
4948 try src_mat.finish(isel);
4949 } else if (dst_int_info.bits <= 64 and src_int_info.bits <= 32) {
4950 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
4951 const src_vi = try isel.use(ty_op.operand);
4952 const src_mat = try src_vi.matReg(isel);
4953 try isel.emit(if (can_be_negative) .sbfm(dst_ra.x(), src_mat.ra.x(), .{
4954 .N = .doubleword,
4955 .immr = 0,
4956 .imms = @intCast(src_int_info.bits - 1),
4957 }) else .orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }));
4958 try src_mat.finish(isel);
4959 } else if (dst_int_info.bits <= 32 and src_int_info.bits <= 128) {
4960 assert(src_int_info.bits > 64);
4961 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
4962 const src_vi = try isel.use(ty_op.operand);
4963
4964 var src_lo64_it = src_vi.field(src_ty, 0, 8);
4965 const src_lo64_vi = try src_lo64_it.only(isel);
4966 const src_lo64_mat = try src_lo64_vi.?.matReg(isel);
4967 try isel.emit(.orr(dst_ra.w(), .wzr, .{ .register = src_lo64_mat.ra.w() }));
4968 try src_lo64_mat.finish(isel);
4969 } else if (dst_int_info.bits <= 64 and src_int_info.bits <= 128) {
4970 assert(dst_int_info.bits > 32 and src_int_info.bits > 64);
4971 const src_vi = try isel.use(ty_op.operand);
4972
4973 var src_lo64_it = src_vi.field(src_ty, 0, 8);
4974 const src_lo64_vi = try src_lo64_it.only(isel);
4975 try dst_vi.value.copy(isel, dst_ty, src_lo64_vi.?);
4976 } else if (dst_int_info.bits <= 128 and src_int_info.bits <= 64) {
4977 assert(dst_int_info.bits > 64);
4978 const src_vi = try isel.use(ty_op.operand);
4979
4980 var dst_lo64_it = dst_vi.value.field(dst_ty, 0, 8);
4981 const dst_lo64_vi = try dst_lo64_it.only(isel);
4982 if (src_int_info.bits <= 32) unused_lo64: {
4983 const dst_lo64_ra = try dst_lo64_vi.?.defReg(isel) orelse break :unused_lo64;
4984 const src_mat = try src_vi.matReg(isel);
4985 try isel.emit(if (can_be_negative) .sbfm(dst_lo64_ra.x(), src_mat.ra.x(), .{
4986 .N = .doubleword,
4987 .immr = 0,
4988 .imms = @intCast(src_int_info.bits - 1),
4989 }) else .orr(dst_lo64_ra.w(), .wzr, .{ .register = src_mat.ra.w() }));
4990 try src_mat.finish(isel);
4991 } else try dst_lo64_vi.?.copy(isel, src_ty, src_vi);
4992
4993 var dst_hi64_it = dst_vi.value.field(dst_ty, 8, 8);
4994 const dst_hi64_vi = try dst_hi64_it.only(isel);
4995 const dst_hi64_ra = try dst_hi64_vi.?.defReg(isel);
4996 if (dst_hi64_ra) |dst_ra| switch (can_be_negative) {
4997 false => try isel.emit(.orr(dst_ra.x(), .xzr, .{ .register = .xzr })),
4998 true => {
4999 const src_mat = try src_vi.matReg(isel);
5000 try isel.emit(.sbfm(dst_ra.x(), src_mat.ra.x(), .{
5001 .N = .doubleword,
5002 .immr = @intCast(src_int_info.bits - 1),
5003 .imms = @intCast(src_int_info.bits - 1),
5004 }));
5005 try src_mat.finish(isel);
5006 },
5007 };
5008 } else return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
5009 }
5010 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5011 },
5012 .trunc => |air_tag| {
5013 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
5014 defer dst_vi.value.deref(isel);
5015
5016 const ty_op = air.data(air.inst_index).ty_op;
5017 const dst_ty = ty_op.ty.toType();
5018 const src_ty = isel.air.typeOf(ty_op.operand, ip);
5019 if (!dst_ty.isAbiInt(zcu) or !src_ty.isAbiInt(zcu)) return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
5020 const dst_int_info = dst_ty.intInfo(zcu);
5021 switch (dst_int_info.bits) {
5022 0 => unreachable,
5023 1...64 => |dst_bits| {
5024 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
5025 const src_vi = try isel.use(ty_op.operand);
5026 var src_part_it = src_vi.field(src_ty, 0, @min(src_vi.size(isel), 8));
5027 const src_part_vi = try src_part_it.only(isel);
5028 const src_part_mat = try src_part_vi.?.matReg(isel);
5029 try isel.emit(switch (dst_bits) {
5030 else => unreachable,
5031 1...31 => |bits| switch (dst_int_info.signedness) {
5032 .signed => .sbfm(dst_ra.w(), src_part_mat.ra.w(), .{
5033 .N = .word,
5034 .immr = 0,
5035 .imms = @intCast(bits - 1),
5036 }),
5037 .unsigned => .ubfm(dst_ra.w(), src_part_mat.ra.w(), .{
5038 .N = .word,
5039 .immr = 0,
5040 .imms = @intCast(bits - 1),
5041 }),
5042 },
5043 32 => .orr(dst_ra.w(), .wzr, .{ .register = src_part_mat.ra.w() }),
5044 33...63 => |bits| switch (dst_int_info.signedness) {
5045 .signed => .sbfm(dst_ra.x(), src_part_mat.ra.x(), .{
5046 .N = .doubleword,
5047 .immr = 0,
5048 .imms = @intCast(bits - 1),
5049 }),
5050 .unsigned => .ubfm(dst_ra.x(), src_part_mat.ra.x(), .{
5051 .N = .doubleword,
5052 .immr = 0,
5053 .imms = @intCast(bits - 1),
5054 }),
5055 },
5056 64 => .orr(dst_ra.x(), .xzr, .{ .register = src_part_mat.ra.x() }),
5057 });
5058 try src_part_mat.finish(isel);
5059 },
5060 65...128 => |dst_bits| switch (src_ty.intInfo(zcu).bits) {
5061 0 => unreachable,
5062 65...128 => {
5063 const src_vi = try isel.use(ty_op.operand);
5064 var dst_hi64_it = dst_vi.value.field(dst_ty, 8, 8);
5065 const dst_hi64_vi = try dst_hi64_it.only(isel);
5066 if (try dst_hi64_vi.?.defReg(isel)) |dst_hi64_ra| {
5067 var src_hi64_it = src_vi.field(src_ty, 8, 8);
5068 const src_hi64_vi = try src_hi64_it.only(isel);
5069 const src_hi64_mat = try src_hi64_vi.?.matReg(isel);
5070 try isel.emit(switch (dst_int_info.signedness) {
5071 .signed => .sbfm(dst_hi64_ra.x(), src_hi64_mat.ra.x(), .{
5072 .N = .doubleword,
5073 .immr = 0,
5074 .imms = @intCast(dst_bits - 64 - 1),
5075 }),
5076 .unsigned => .ubfm(dst_hi64_ra.x(), src_hi64_mat.ra.x(), .{
5077 .N = .doubleword,
5078 .immr = 0,
5079 .imms = @intCast(dst_bits - 64 - 1),
5080 }),
5081 });
5082 try src_hi64_mat.finish(isel);
5083 }
5084 var dst_lo64_it = dst_vi.value.field(dst_ty, 0, 8);
5085 const dst_lo64_vi = try dst_lo64_it.only(isel);
5086 if (try dst_lo64_vi.?.defReg(isel)) |dst_lo64_ra| {
5087 var src_lo64_it = src_vi.field(src_ty, 0, 8);
5088 const src_lo64_vi = try src_lo64_it.only(isel);
5089 try src_lo64_vi.?.liveOut(isel, dst_lo64_ra);
5090 }
5091 },
5092 else => return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }),
5093 },
5094 else => return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }),
5095 }
5096 }
5097 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5098 },
5099 .optional_payload_ptr => {
5100 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| {
5101 defer dst_vi.value.deref(isel);
5102 const ty_op = air.data(air.inst_index).ty_op;
5103 try dst_vi.value.move(isel, ty_op.operand);
5104 }
5105 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5106 },
5107 .optional_payload => {
5108 if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| unused: {
5109 defer payload_vi.value.deref(isel);
5110
5111 const ty_op = air.data(air.inst_index).ty_op;
5112 const opt_ty = isel.air.typeOf(ty_op.operand, ip);
5113 if (opt_ty.optionalReprIsPayload(zcu)) {
5114 try payload_vi.value.move(isel, ty_op.operand);
5115 break :unused;
5116 }
5117
5118 const opt_vi = try isel.use(ty_op.operand);
5119 var payload_part_it = opt_vi.field(opt_ty, 0, payload_vi.value.size(isel));
5120 const payload_part_vi = try payload_part_it.only(isel);
5121 try payload_vi.value.copy(isel, ty_op.ty.toType(), payload_part_vi.?);
5122 }
5123 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5124 },
5125 .wrap_optional => {
5126 if (isel.live_values.fetchRemove(air.inst_index)) |opt_vi| unused: {
5127 defer opt_vi.value.deref(isel);
5128
5129 const ty_op = air.data(air.inst_index).ty_op;
5130 if (ty_op.ty.toType().optionalReprIsPayload(zcu)) {
5131 try opt_vi.value.move(isel, ty_op.operand);
5132 break :unused;
5133 }
5134
5135 const payload_size = isel.air.typeOf(ty_op.operand, ip).abiSize(zcu);
5136 var payload_part_it = opt_vi.value.field(ty_op.ty.toType(), 0, payload_size);
5137 const payload_part_vi = try payload_part_it.only(isel);
5138 try payload_part_vi.?.move(isel, ty_op.operand);
5139 var has_value_part_it = opt_vi.value.field(ty_op.ty.toType(), payload_size, 1);
5140 const has_value_part_vi = try has_value_part_it.only(isel);
5141 const has_value_part_ra = try has_value_part_vi.?.defReg(isel) orelse break :unused;
5142 try isel.emit(.movz(has_value_part_ra.w(), 1, .{ .lsl = .@"0" }));
5143 }
5144 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5145 },
5146 .unwrap_errunion_payload => {
5147 if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| {
5148 defer payload_vi.value.deref(isel);
5149
5150 const ty_op = air.data(air.inst_index).ty_op;
5151 const error_union_ty = isel.air.typeOf(ty_op.operand, ip);
5152
5153 const error_union_vi = try isel.use(ty_op.operand);
5154 var payload_part_it = error_union_vi.field(
5155 error_union_ty,
5156 codegen.errUnionPayloadOffset(ty_op.ty.toType(), zcu),
5157 payload_vi.value.size(isel),
5158 );
5159 const payload_part_vi = try payload_part_it.only(isel);
5160 try payload_vi.value.copy(isel, ty_op.ty.toType(), payload_part_vi.?);
5161 }
5162 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5163 },
5164 .unwrap_errunion_err => {
5165 if (isel.live_values.fetchRemove(air.inst_index)) |error_set_vi| {
5166 defer error_set_vi.value.deref(isel);
5167
5168 const ty_op = air.data(air.inst_index).ty_op;
5169 const error_union_ty = isel.air.typeOf(ty_op.operand, ip);
5170
5171 const error_union_vi = try isel.use(ty_op.operand);
5172 var error_set_part_it = error_union_vi.field(
5173 error_union_ty,
5174 codegen.errUnionErrorOffset(error_union_ty.errorUnionPayload(zcu), zcu),
5175 error_set_vi.value.size(isel),
5176 );
5177 const error_set_part_vi = try error_set_part_it.only(isel);
5178 try error_set_vi.value.copy(isel, ty_op.ty.toType(), error_set_part_vi.?);
5179 }
5180 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5181 },
5182 .wrap_errunion_payload => {
5183 if (isel.live_values.fetchRemove(air.inst_index)) |error_union_vi| {
5184 defer error_union_vi.value.deref(isel);
5185
5186 const ty_op = air.data(air.inst_index).ty_op;
5187 const error_union_ty = ty_op.ty.toType();
5188 const error_union_info = ip.indexToKey(error_union_ty.toIntern()).error_union_type;
5189 const error_set_ty: ZigType = .fromInterned(error_union_info.error_set_type);
5190 const payload_ty: ZigType = .fromInterned(error_union_info.payload_type);
5191 const error_set_offset = codegen.errUnionErrorOffset(payload_ty, zcu);
5192 const payload_offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
5193 const error_set_size = error_set_ty.abiSize(zcu);
5194 const payload_size = payload_ty.abiSize(zcu);
5195
5196 var payload_part_it = error_union_vi.value.field(error_union_ty, payload_offset, payload_size);
5197 const payload_part_vi = try payload_part_it.only(isel);
5198 try payload_part_vi.?.move(isel, ty_op.operand);
5199 var error_set_part_it = error_union_vi.value.field(error_union_ty, error_set_offset, error_set_size);
5200 const error_set_part_vi = try error_set_part_it.only(isel);
5201 if (try error_set_part_vi.?.defReg(isel)) |error_set_part_ra| try isel.emit(switch (error_set_size) {
5202 else => unreachable,
5203 1...4 => .orr(error_set_part_ra.w(), .wzr, .{ .register = .wzr }),
5204 5...8 => .orr(error_set_part_ra.x(), .xzr, .{ .register = .xzr }),
5205 });
5206 }
5207 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5208 },
5209 .wrap_errunion_err => {
5210 if (isel.live_values.fetchRemove(air.inst_index)) |error_union_vi| {
5211 defer error_union_vi.value.deref(isel);
5212
5213 const ty_op = air.data(air.inst_index).ty_op;
5214 const error_union_ty = ty_op.ty.toType();
5215 const error_union_info = ip.indexToKey(error_union_ty.toIntern()).error_union_type;
5216 const error_set_ty: ZigType = .fromInterned(error_union_info.error_set_type);
5217 const payload_ty: ZigType = .fromInterned(error_union_info.payload_type);
5218 const error_set_offset = codegen.errUnionErrorOffset(payload_ty, zcu);
5219 const payload_offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
5220 const error_set_size = error_set_ty.abiSize(zcu);
5221 const payload_size = payload_ty.abiSize(zcu);
5222
5223 if (payload_size > 0) {
5224 var payload_part_it = error_union_vi.value.field(error_union_ty, payload_offset, payload_size);
5225 const payload_part_vi = try payload_part_it.only(isel);
5226 if (try payload_part_vi.?.defReg(isel)) |payload_part_ra| try isel.emit(switch (payload_size) {
5227 else => unreachable,
5228 1...4 => .orr(payload_part_ra.w(), .wzr, .{ .immediate = .{
5229 .N = .word,
5230 .immr = 0b000001,
5231 .imms = 0b111100,
5232 } }),
5233 5...8 => .orr(payload_part_ra.x(), .xzr, .{ .immediate = .{
5234 .N = .word,
5235 .immr = 0b000001,
5236 .imms = 0b111100,
5237 } }),
5238 });
5239 }
5240 var error_set_part_it = error_union_vi.value.field(error_union_ty, error_set_offset, error_set_size);
5241 const error_set_part_vi = try error_set_part_it.only(isel);
5242 try error_set_part_vi.?.move(isel, ty_op.operand);
5243 }
5244 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5245 },
5246 .struct_field_ptr => {
5247 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
5248 defer dst_vi.value.deref(isel);
5249 const ty_pl = air.data(air.inst_index).ty_pl;
5250 const extra = isel.air.extraData(Air.StructField, ty_pl.payload).data;
5251 switch (codegen.fieldOffset(
5252 isel.air.typeOf(extra.struct_operand, ip),
5253 ty_pl.ty.toType(),
5254 extra.field_index,
5255 zcu,
5256 )) {
5257 0 => try dst_vi.value.move(isel, extra.struct_operand),
5258 else => |field_offset| {
5259 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
5260 const src_vi = try isel.use(extra.struct_operand);
5261 const src_mat = try src_vi.matReg(isel);
5262 const lo12: u12 = @truncate(field_offset >> 0);
5263 const hi12: u12 = @intCast(field_offset >> 12);
5264 if (hi12 > 0) try isel.emit(.add(
5265 dst_ra.x(),
5266 if (lo12 > 0) dst_ra.x() else src_mat.ra.x(),
5267 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
5268 ));
5269 if (lo12 > 0) try isel.emit(.add(dst_ra.x(), src_mat.ra.x(), .{ .immediate = lo12 }));
5270 try src_mat.finish(isel);
5271 },
5272 }
5273 }
5274 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5275 },
5276 .struct_field_ptr_index_0,
5277 .struct_field_ptr_index_1,
5278 .struct_field_ptr_index_2,
5279 .struct_field_ptr_index_3,
5280 => |air_tag| {
5281 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
5282 defer dst_vi.value.deref(isel);
5283 const ty_op = air.data(air.inst_index).ty_op;
5284 switch (codegen.fieldOffset(
5285 isel.air.typeOf(ty_op.operand, ip),
5286 ty_op.ty.toType(),
5287 switch (air_tag) {
5288 else => unreachable,
5289 .struct_field_ptr_index_0 => 0,
5290 .struct_field_ptr_index_1 => 1,
5291 .struct_field_ptr_index_2 => 2,
5292 .struct_field_ptr_index_3 => 3,
5293 },
5294 zcu,
5295 )) {
5296 0 => try dst_vi.value.move(isel, ty_op.operand),
5297 else => |field_offset| {
5298 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
5299 const src_vi = try isel.use(ty_op.operand);
5300 const src_mat = try src_vi.matReg(isel);
5301 const lo12: u12 = @truncate(field_offset >> 0);
5302 const hi12: u12 = @intCast(field_offset >> 12);
5303 if (hi12 > 0) try isel.emit(.add(
5304 dst_ra.x(),
5305 if (lo12 > 0) dst_ra.x() else src_mat.ra.x(),
5306 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
5307 ));
5308 if (lo12 > 0) try isel.emit(.add(dst_ra.x(), src_mat.ra.x(), .{ .immediate = lo12 }));
5309 try src_mat.finish(isel);
5310 },
5311 }
5312 }
5313 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5314 },
5315 .struct_field_val => {
5316 if (isel.live_values.fetchRemove(air.inst_index)) |field_vi| {
5317 defer field_vi.value.deref(isel);
5318
5319 const ty_pl = air.data(air.inst_index).ty_pl;
5320 const extra = isel.air.extraData(Air.StructField, ty_pl.payload).data;
5321 const agg_ty = isel.air.typeOf(extra.struct_operand, ip);
5322 const field_ty = ty_pl.ty.toType();
5323 const field_bit_offset, const field_bit_size, const is_packed = switch (agg_ty.containerLayout(zcu)) {
5324 .auto, .@"extern" => .{
5325 8 * agg_ty.structFieldOffset(extra.field_index, zcu),
5326 8 * field_ty.abiSize(zcu),
5327 false,
5328 },
5329 .@"packed" => .{
5330 if (zcu.typeToPackedStruct(agg_ty)) |loaded_struct|
5331 zcu.structPackedFieldBitOffset(loaded_struct, extra.field_index)
5332 else
5333 0,
5334 field_ty.bitSize(zcu),
5335 true,
5336 },
5337 };
5338 if (is_packed) return isel.fail("packed field of {f}", .{
5339 isel.fmtType(agg_ty),
5340 });
5341
5342 const agg_vi = try isel.use(extra.struct_operand);
5343 var agg_part_it = agg_vi.field(agg_ty, @divExact(field_bit_offset, 8), @divExact(field_bit_size, 8));
5344 while (try agg_part_it.next(isel)) |agg_part| {
5345 var field_part_it = field_vi.value.field(ty_pl.ty.toType(), agg_part.offset, agg_part.vi.size(isel));
5346 const field_part_vi = try field_part_it.only(isel);
5347 if (field_part_vi.? == agg_part.vi) continue;
5348 var field_subpart_it = field_part_vi.?.parts(isel);
5349 const field_part_offset = if (field_subpart_it.only()) |field_subpart_vi|
5350 field_subpart_vi.get(isel).offset_from_parent
5351 else
5352 0;
5353 while (field_subpart_it.next()) |field_subpart_vi| {
5354 const field_subpart_ra = try field_subpart_vi.defReg(isel) orelse continue;
5355 const field_subpart_offset, const field_subpart_size = field_subpart_vi.position(isel);
5356 var agg_subpart_it = agg_part.vi.field(
5357 field_ty,
5358 agg_part.offset + field_subpart_offset - field_part_offset,
5359 field_subpart_size,
5360 );
5361 const agg_subpart_vi = try agg_subpart_it.only(isel);
5362 try agg_subpart_vi.?.liveOut(isel, field_subpart_ra);
5363 }
5364 }
5365 }
5366 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5367 },
5368 .slice => {
5369 if (isel.live_values.fetchRemove(air.inst_index)) |slice_vi| {
5370 defer slice_vi.value.deref(isel);
5371 const ty_pl = air.data(air.inst_index).ty_pl;
5372 const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data;
5373 var ptr_part_it = slice_vi.value.field(ty_pl.ty.toType(), 0, 8);
5374 const ptr_part_vi = try ptr_part_it.only(isel);
5375 try ptr_part_vi.?.move(isel, bin_op.lhs);
5376 var len_part_it = slice_vi.value.field(ty_pl.ty.toType(), 8, 8);
5377 const len_part_vi = try len_part_it.only(isel);
5378 try len_part_vi.?.move(isel, bin_op.rhs);
5379 }
5380 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5381 },
5382 .slice_len => {
5383 if (isel.live_values.fetchRemove(air.inst_index)) |len_vi| {
5384 defer len_vi.value.deref(isel);
5385 const ty_op = air.data(air.inst_index).ty_op;
5386 const slice_vi = try isel.use(ty_op.operand);
5387 var len_part_it = slice_vi.field(isel.air.typeOf(ty_op.operand, ip), 8, 8);
5388 const len_part_vi = try len_part_it.only(isel);
5389 try len_vi.value.copy(isel, ty_op.ty.toType(), len_part_vi.?);
5390 }
5391 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5392 },
5393 .slice_ptr => {
5394 if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| {
5395 defer ptr_vi.value.deref(isel);
5396 const ty_op = air.data(air.inst_index).ty_op;
5397 const slice_vi = try isel.use(ty_op.operand);
5398 var ptr_part_it = slice_vi.field(isel.air.typeOf(ty_op.operand, ip), 0, 8);
5399 const ptr_part_vi = try ptr_part_it.only(isel);
5400 try ptr_vi.value.copy(isel, ty_op.ty.toType(), ptr_part_vi.?);
5401 }
5402 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5403 },
5404 .array_elem_val => {
5405 if (isel.live_values.fetchRemove(air.inst_index)) |elem_vi| unused: {
5406 defer elem_vi.value.deref(isel);
5407
5408 const bin_op = air.data(air.inst_index).bin_op;
5409 const array_ty = isel.air.typeOf(bin_op.lhs, ip);
5410 const elem_ty = array_ty.childType(zcu);
5411 const elem_size = elem_ty.abiSize(zcu);
5412 if (elem_size <= 16 and array_ty.arrayLenIncludingSentinel(zcu) <= Value.max_parts) if (bin_op.rhs.toInterned()) |index_val| {
5413 const elem_offset = elem_size * Constant.fromInterned(index_val).toUnsignedInt(zcu);
5414 const array_vi = try isel.use(bin_op.lhs);
5415 var elem_part_it = array_vi.field(array_ty, elem_offset, elem_size);
5416 const elem_part_vi = try elem_part_it.only(isel);
5417 try elem_vi.value.copy(isel, elem_ty, elem_part_vi.?);
5418 break :unused;
5419 };
5420 switch (elem_size) {
5421 0 => unreachable,
5422 1, 2, 4, 8 => {
5423 const elem_ra = try elem_vi.value.defReg(isel) orelse break :unused;
5424 const array_ptr_ra = try isel.allocIntReg();
5425 defer isel.freeReg(array_ptr_ra);
5426 const index_vi = try isel.use(bin_op.rhs);
5427 const index_mat = try index_vi.matReg(isel);
5428 try isel.emit(switch (elem_size) {
5429 else => unreachable,
5430 1 => if (elem_vi.value.isVector(isel)) .ldr(elem_ra.b(), .{ .extended_register = .{
5431 .base = array_ptr_ra.x(),
5432 .index = index_mat.ra.x(),
5433 .extend = .{ .lsl = 0 },
5434 } }) else switch (elem_vi.value.signedness(isel)) {
5435 .signed => .ldrsb(elem_ra.w(), .{ .extended_register = .{
5436 .base = array_ptr_ra.x(),
5437 .index = index_mat.ra.x(),
5438 .extend = .{ .lsl = 0 },
5439 } }),
5440 .unsigned => .ldrb(elem_ra.w(), .{ .extended_register = .{
5441 .base = array_ptr_ra.x(),
5442 .index = index_mat.ra.x(),
5443 .extend = .{ .lsl = 0 },
5444 } }),
5445 },
5446 2 => if (elem_vi.value.isVector(isel)) .ldr(elem_ra.h(), .{ .extended_register = .{
5447 .base = array_ptr_ra.x(),
5448 .index = index_mat.ra.x(),
5449 .extend = .{ .lsl = 1 },
5450 } }) else switch (elem_vi.value.signedness(isel)) {
5451 .signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{
5452 .base = array_ptr_ra.x(),
5453 .index = index_mat.ra.x(),
5454 .extend = .{ .lsl = 1 },
5455 } }),
5456 .unsigned => .ldrh(elem_ra.w(), .{ .extended_register = .{
5457 .base = array_ptr_ra.x(),
5458 .index = index_mat.ra.x(),
5459 .extend = .{ .lsl = 1 },
5460 } }),
5461 },
5462 4 => .ldr(if (elem_vi.value.isVector(isel)) elem_ra.s() else elem_ra.w(), .{ .extended_register = .{
5463 .base = array_ptr_ra.x(),
5464 .index = index_mat.ra.x(),
5465 .extend = .{ .lsl = 2 },
5466 } }),
5467 8 => .ldr(if (elem_vi.value.isVector(isel)) elem_ra.d() else elem_ra.x(), .{ .extended_register = .{
5468 .base = array_ptr_ra.x(),
5469 .index = index_mat.ra.x(),
5470 .extend = .{ .lsl = 3 },
5471 } }),
5472 16 => .ldr(elem_ra.q(), .{ .extended_register = .{
5473 .base = array_ptr_ra.x(),
5474 .index = index_mat.ra.x(),
5475 .extend = .{ .lsl = 4 },
5476 } }),
5477 });
5478 try index_mat.finish(isel);
5479 const array_vi = try isel.use(bin_op.lhs);
5480 try array_vi.address(isel, 0, array_ptr_ra);
5481 },
5482 else => {
5483 const ptr_ra = try isel.allocIntReg();
5484 defer isel.freeReg(ptr_ra);
5485 if (!try elem_vi.value.load(isel, elem_ty, ptr_ra, .{})) break :unused;
5486 const index_vi = try isel.use(bin_op.rhs);
5487 try isel.elemPtr(ptr_ra, ptr_ra, .add, elem_size, index_vi);
5488 const array_vi = try isel.use(bin_op.lhs);
5489 try array_vi.address(isel, 0, ptr_ra);
5490 },
5491 }
5492 }
5493 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5494 },
5495 .slice_elem_val => {
5496 if (isel.live_values.fetchRemove(air.inst_index)) |elem_vi| unused: {
5497 defer elem_vi.value.deref(isel);
5498
5499 const bin_op = air.data(air.inst_index).bin_op;
5500 const slice_ty = isel.air.typeOf(bin_op.lhs, ip);
5501 const ptr_info = slice_ty.ptrInfo(zcu);
5502 const elem_size = elem_vi.value.size(isel);
5503 const elem_is_vector = elem_vi.value.isVector(isel);
5504 if (switch (elem_size) {
5505 0 => unreachable,
5506 1, 2, 4, 8 => true,
5507 16 => elem_is_vector,
5508 else => false,
5509 }) {
5510 const elem_ra = try elem_vi.value.defReg(isel) orelse break :unused;
5511 const slice_vi = try isel.use(bin_op.lhs);
5512 const index_vi = try isel.use(bin_op.rhs);
5513 var ptr_part_it = slice_vi.field(slice_ty, 0, 8);
5514 const ptr_part_vi = try ptr_part_it.only(isel);
5515 const base_mat = try ptr_part_vi.?.matReg(isel);
5516 const index_mat = try index_vi.matReg(isel);
5517 try isel.emit(switch (elem_size) {
5518 else => unreachable,
5519 1 => if (elem_is_vector) .ldr(elem_ra.b(), .{ .extended_register = .{
5520 .base = base_mat.ra.x(),
5521 .index = index_mat.ra.x(),
5522 .extend = .{ .lsl = 0 },
5523 } }) else switch (elem_vi.value.signedness(isel)) {
5524 .signed => .ldrsb(elem_ra.w(), .{ .extended_register = .{
5525 .base = base_mat.ra.x(),
5526 .index = index_mat.ra.x(),
5527 .extend = .{ .lsl = 0 },
5528 } }),
5529 .unsigned => .ldrb(elem_ra.w(), .{ .extended_register = .{
5530 .base = base_mat.ra.x(),
5531 .index = index_mat.ra.x(),
5532 .extend = .{ .lsl = 0 },
5533 } }),
5534 },
5535 2 => if (elem_is_vector) .ldr(elem_ra.h(), .{ .extended_register = .{
5536 .base = base_mat.ra.x(),
5537 .index = index_mat.ra.x(),
5538 .extend = .{ .lsl = 0 },
5539 } }) else switch (elem_vi.value.signedness(isel)) {
5540 .signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{
5541 .base = base_mat.ra.x(),
5542 .index = index_mat.ra.x(),
5543 .extend = .{ .lsl = 1 },
5544 } }),
5545 .unsigned => .ldrh(elem_ra.w(), .{ .extended_register = .{
5546 .base = base_mat.ra.x(),
5547 .index = index_mat.ra.x(),
5548 .extend = .{ .lsl = 1 },
5549 } }),
5550 },
5551 4 => .ldr(if (elem_is_vector) elem_ra.s() else elem_ra.w(), .{ .extended_register = .{
5552 .base = base_mat.ra.x(),
5553 .index = index_mat.ra.x(),
5554 .extend = .{ .lsl = 2 },
5555 } }),
5556 8 => .ldr(if (elem_is_vector) elem_ra.d() else elem_ra.x(), .{ .extended_register = .{
5557 .base = base_mat.ra.x(),
5558 .index = index_mat.ra.x(),
5559 .extend = .{ .lsl = 3 },
5560 } }),
5561 16 => .ldr(elem_ra.q(), .{ .extended_register = .{
5562 .base = base_mat.ra.x(),
5563 .index = index_mat.ra.x(),
5564 .extend = .{ .lsl = 4 },
5565 } }),
5566 });
5567 try index_mat.finish(isel);
5568 try base_mat.finish(isel);
5569 break :unused;
5570 } else {
5571 const elem_ptr_ra = try isel.allocIntReg();
5572 defer isel.freeReg(elem_ptr_ra);
5573 if (!try elem_vi.value.load(isel, slice_ty.elemType2(zcu), elem_ptr_ra, .{
5574 .@"volatile" = ptr_info.flags.is_volatile,
5575 })) break :unused;
5576 const slice_vi = try isel.use(bin_op.lhs);
5577 var ptr_part_it = slice_vi.field(slice_ty, 0, 8);
5578 const ptr_part_vi = try ptr_part_it.only(isel);
5579 const ptr_part_mat = try ptr_part_vi.?.matReg(isel);
5580 const index_vi = try isel.use(bin_op.rhs);
5581 try isel.elemPtr(elem_ptr_ra, ptr_part_mat.ra, .add, elem_size, index_vi);
5582 try ptr_part_mat.finish(isel);
5583 }
5584 }
5585 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5586 },
5587 .slice_elem_ptr => {
5588 if (isel.live_values.fetchRemove(air.inst_index)) |elem_ptr_vi| unused: {
5589 defer elem_ptr_vi.value.deref(isel);
5590 const elem_ptr_ra = try elem_ptr_vi.value.defReg(isel) orelse break :unused;
5591
5592 const ty_pl = air.data(air.inst_index).ty_pl;
5593 const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data;
5594 const elem_size = ty_pl.ty.toType().childType(zcu).abiSize(zcu);
5595
5596 const slice_vi = try isel.use(bin_op.lhs);
5597 var ptr_part_it = slice_vi.field(isel.air.typeOf(bin_op.lhs, ip), 0, 8);
5598 const ptr_part_vi = try ptr_part_it.only(isel);
5599 const ptr_part_mat = try ptr_part_vi.?.matReg(isel);
5600 const index_vi = try isel.use(bin_op.rhs);
5601 try isel.elemPtr(elem_ptr_ra, ptr_part_mat.ra, .add, elem_size, index_vi);
5602 try ptr_part_mat.finish(isel);
5603 }
5604 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5605 },
5606 .ptr_elem_val => {
5607 if (isel.live_values.fetchRemove(air.inst_index)) |elem_vi| unused: {
5608 defer elem_vi.value.deref(isel);
5609
5610 const bin_op = air.data(air.inst_index).bin_op;
5611 const ptr_ty = isel.air.typeOf(bin_op.lhs, ip);
5612 const ptr_info = ptr_ty.ptrInfo(zcu);
5613 const elem_size = elem_vi.value.size(isel);
5614 switch (elem_size) {
5615 0 => unreachable,
5616 1, 2, 4, 8 => {
5617 const elem_ra = try elem_vi.value.defReg(isel) orelse break :unused;
5618 const base_vi = try isel.use(bin_op.lhs);
5619 const index_vi = try isel.use(bin_op.rhs);
5620 const base_mat = try base_vi.matReg(isel);
5621 const index_mat = try index_vi.matReg(isel);
5622 try isel.emit(switch (elem_size) {
5623 else => unreachable,
5624 1 => switch (elem_vi.value.signedness(isel)) {
5625 .signed => .ldrsb(elem_ra.w(), .{ .extended_register = .{
5626 .base = base_mat.ra.x(),
5627 .index = index_mat.ra.x(),
5628 .extend = .{ .lsl = 0 },
5629 } }),
5630 .unsigned => .ldrb(elem_ra.w(), .{ .extended_register = .{
5631 .base = base_mat.ra.x(),
5632 .index = index_mat.ra.x(),
5633 .extend = .{ .lsl = 0 },
5634 } }),
5635 },
5636 2 => switch (elem_vi.value.signedness(isel)) {
5637 .signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{
5638 .base = base_mat.ra.x(),
5639 .index = index_mat.ra.x(),
5640 .extend = .{ .lsl = 1 },
5641 } }),
5642 .unsigned => .ldrh(elem_ra.w(), .{ .extended_register = .{
5643 .base = base_mat.ra.x(),
5644 .index = index_mat.ra.x(),
5645 .extend = .{ .lsl = 1 },
5646 } }),
5647 },
5648 4 => .ldr(elem_ra.w(), .{ .extended_register = .{
5649 .base = base_mat.ra.x(),
5650 .index = index_mat.ra.x(),
5651 .extend = .{ .lsl = 2 },
5652 } }),
5653 8 => .ldr(elem_ra.x(), .{ .extended_register = .{
5654 .base = base_mat.ra.x(),
5655 .index = index_mat.ra.x(),
5656 .extend = .{ .lsl = 3 },
5657 } }),
5658 });
5659 try index_mat.finish(isel);
5660 try base_mat.finish(isel);
5661 },
5662 else => {
5663 const elem_ptr_ra = try isel.allocIntReg();
5664 defer isel.freeReg(elem_ptr_ra);
5665 if (!try elem_vi.value.load(isel, ptr_ty.elemType2(zcu), elem_ptr_ra, .{
5666 .@"volatile" = ptr_info.flags.is_volatile,
5667 })) break :unused;
5668 const base_vi = try isel.use(bin_op.lhs);
5669 const base_mat = try base_vi.matReg(isel);
5670 const index_vi = try isel.use(bin_op.rhs);
5671 try isel.elemPtr(elem_ptr_ra, base_mat.ra, .add, elem_size, index_vi);
5672 try base_mat.finish(isel);
5673 },
5674 }
5675 }
5676 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5677 },
5678 .ptr_elem_ptr => {
5679 if (isel.live_values.fetchRemove(air.inst_index)) |elem_ptr_vi| unused: {
5680 defer elem_ptr_vi.value.deref(isel);
5681 const elem_ptr_ra = try elem_ptr_vi.value.defReg(isel) orelse break :unused;
5682
5683 const ty_pl = air.data(air.inst_index).ty_pl;
5684 const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data;
5685 const elem_size = ty_pl.ty.toType().childType(zcu).abiSize(zcu);
5686
5687 const base_vi = try isel.use(bin_op.lhs);
5688 const base_mat = try base_vi.matReg(isel);
5689 const index_vi = try isel.use(bin_op.rhs);
5690 try isel.elemPtr(elem_ptr_ra, base_mat.ra, .add, elem_size, index_vi);
5691 try base_mat.finish(isel);
5692 }
5693 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5694 },
5695 .array_to_slice => {
5696 if (isel.live_values.fetchRemove(air.inst_index)) |slice_vi| {
5697 defer slice_vi.value.deref(isel);
5698 const ty_op = air.data(air.inst_index).ty_op;
5699 var ptr_part_it = slice_vi.value.field(ty_op.ty.toType(), 0, 8);
5700 const ptr_part_vi = try ptr_part_it.only(isel);
5701 try ptr_part_vi.?.move(isel, ty_op.operand);
5702 var len_part_it = slice_vi.value.field(ty_op.ty.toType(), 8, 8);
5703 const len_part_vi = try len_part_it.only(isel);
5704 if (try len_part_vi.?.defReg(isel)) |len_ra| try isel.movImmediate(
5705 len_ra.x(),
5706 isel.air.typeOf(ty_op.operand, ip).childType(zcu).arrayLen(zcu),
5707 );
5708 }
5709 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5710 },
5711 .int_from_float, .int_from_float_optimized => |air_tag| {
5712 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
5713 defer dst_vi.value.deref(isel);
5714
5715 const ty_op = air.data(air.inst_index).ty_op;
5716 const dst_ty = ty_op.ty.toType();
5717 const src_ty = isel.air.typeOf(ty_op.operand, ip);
5718 if (!dst_ty.isAbiInt(zcu)) return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
5719 const dst_int_info = dst_ty.intInfo(zcu);
5720 const src_bits = src_ty.floatBits(isel.target);
5721 switch (@max(dst_int_info.bits, src_bits)) {
5722 0 => unreachable,
5723 1...64 => {
5724 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
5725 const need_fcvt = switch (src_bits) {
5726 else => unreachable,
5727 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
5728 32, 64 => false,
5729 };
5730 const src_vi = try isel.use(ty_op.operand);
5731 const src_mat = try src_vi.matReg(isel);
5732 const src_ra = if (need_fcvt) try isel.allocVecReg() else src_mat.ra;
5733 defer if (need_fcvt) isel.freeReg(src_ra);
5734 const dst_reg = switch (dst_int_info.bits) {
5735 else => unreachable,
5736 1...32 => dst_ra.w(),
5737 33...64 => dst_ra.x(),
5738 };
5739 const src_reg = switch (src_bits) {
5740 else => unreachable,
5741 16 => if (need_fcvt) src_ra.s() else src_ra.h(),
5742 32 => src_ra.s(),
5743 64 => src_ra.d(),
5744 };
5745 try isel.emit(switch (dst_int_info.signedness) {
5746 .signed => .fcvtzs(dst_reg, src_reg),
5747 .unsigned => .fcvtzu(dst_reg, src_reg),
5748 });
5749 if (need_fcvt) try isel.emit(.fcvt(src_reg, src_mat.ra.h()));
5750 try src_mat.finish(isel);
5751 },
5752 65...128 => {
5753 try call.prepareReturn(isel);
5754 switch (dst_int_info.bits) {
5755 else => unreachable,
5756 1...64 => try call.returnLiveIn(isel, dst_vi.value, .r0),
5757 65...128 => {
5758 var dst_hi64_it = dst_vi.value.field(dst_ty, 8, 8);
5759 const dst_hi64_vi = try dst_hi64_it.only(isel);
5760 try call.returnLiveIn(isel, dst_hi64_vi.?, .r1);
5761 var dst_lo64_it = dst_vi.value.field(dst_ty, 0, 8);
5762 const dst_lo64_vi = try dst_lo64_it.only(isel);
5763 try call.returnLiveIn(isel, dst_lo64_vi.?, .r0);
5764 },
5765 }
5766 try call.finishReturn(isel);
5767
5768 try call.prepareCallee(isel);
5769 try isel.global_relocs.append(gpa, .{
5770 .global = switch (dst_int_info.bits) {
5771 else => unreachable,
5772 1...32 => switch (dst_int_info.signedness) {
5773 .signed => switch (src_bits) {
5774 else => unreachable,
5775 16 => "__fixhfsi",
5776 32 => "__fixsfsi",
5777 64 => "__fixdfsi",
5778 80 => "__fixxfsi",
5779 128 => "__fixtfsi",
5780 },
5781 .unsigned => switch (src_bits) {
5782 else => unreachable,
5783 16 => "__fixunshfsi",
5784 32 => "__fixunssfsi",
5785 64 => "__fixunsdfsi",
5786 80 => "__fixunsxfsi",
5787 128 => "__fixunstfsi",
5788 },
5789 },
5790 33...64 => switch (dst_int_info.signedness) {
5791 .signed => switch (src_bits) {
5792 else => unreachable,
5793 16 => "__fixhfdi",
5794 32 => "__fixsfdi",
5795 64 => "__fixdfdi",
5796 80 => "__fixxfdi",
5797 128 => "__fixtfdi",
5798 },
5799 .unsigned => switch (src_bits) {
5800 else => unreachable,
5801 16 => "__fixunshfdi",
5802 32 => "__fixunssfdi",
5803 64 => "__fixunsdfdi",
5804 80 => "__fixunsxfdi",
5805 128 => "__fixunstfdi",
5806 },
5807 },
5808 65...128 => switch (dst_int_info.signedness) {
5809 .signed => switch (src_bits) {
5810 else => unreachable,
5811 16 => "__fixhfti",
5812 32 => "__fixsfti",
5813 64 => "__fixdfti",
5814 80 => "__fixxfti",
5815 128 => "__fixtfti",
5816 },
5817 .unsigned => switch (src_bits) {
5818 else => unreachable,
5819 16 => "__fixunshfti",
5820 32 => "__fixunssfti",
5821 64 => "__fixunsdfti",
5822 80 => "__fixunsxfti",
5823 128 => "__fixunstfti",
5824 },
5825 },
5826 },
5827 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
5828 });
5829 try isel.emit(.bl(0));
5830 try call.finishCallee(isel);
5831
5832 try call.prepareParams(isel);
5833 const src_vi = try isel.use(ty_op.operand);
5834 switch (src_bits) {
5835 else => unreachable,
5836 16, 32, 64, 128 => try call.paramLiveOut(isel, src_vi, .v0),
5837 80 => {
5838 var src_hi16_it = src_vi.field(src_ty, 8, 8);
5839 const src_hi16_vi = try src_hi16_it.only(isel);
5840 try call.paramLiveOut(isel, src_hi16_vi.?, .r1);
5841 var src_lo64_it = src_vi.field(src_ty, 0, 8);
5842 const src_lo64_vi = try src_lo64_it.only(isel);
5843 try call.paramLiveOut(isel, src_lo64_vi.?, .r0);
5844 },
5845 }
5846 try call.finishParams(isel);
5847 },
5848 else => return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }),
5849 }
5850 }
5851 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5852 },
5853 .float_from_int => |air_tag| {
5854 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
5855 defer dst_vi.value.deref(isel);
5856
5857 const ty_op = air.data(air.inst_index).ty_op;
5858 const dst_ty = ty_op.ty.toType();
5859 const src_ty = isel.air.typeOf(ty_op.operand, ip);
5860 const dst_bits = dst_ty.floatBits(isel.target);
5861 if (!src_ty.isAbiInt(zcu)) return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
5862 const src_int_info = src_ty.intInfo(zcu);
5863 switch (@max(dst_bits, src_int_info.bits)) {
5864 0 => unreachable,
5865 1...64 => {
5866 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
5867 const need_fcvt = switch (dst_bits) {
5868 else => unreachable,
5869 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
5870 32, 64 => false,
5871 };
5872 if (need_fcvt) try isel.emit(.fcvt(dst_ra.h(), dst_ra.s()));
5873 const src_vi = try isel.use(ty_op.operand);
5874 const src_mat = try src_vi.matReg(isel);
5875 const dst_reg = switch (dst_bits) {
5876 else => unreachable,
5877 16 => if (need_fcvt) dst_ra.s() else dst_ra.h(),
5878 32 => dst_ra.s(),
5879 64 => dst_ra.d(),
5880 };
5881 const src_reg = switch (src_int_info.bits) {
5882 else => unreachable,
5883 1...32 => src_mat.ra.w(),
5884 33...64 => src_mat.ra.x(),
5885 };
5886 try isel.emit(switch (src_int_info.signedness) {
5887 .signed => .scvtf(dst_reg, src_reg),
5888 .unsigned => .ucvtf(dst_reg, src_reg),
5889 });
5890 try src_mat.finish(isel);
5891 },
5892 65...128 => {
5893 try call.prepareReturn(isel);
5894 switch (dst_bits) {
5895 else => unreachable,
5896 16, 32, 64, 128 => try call.returnLiveIn(isel, dst_vi.value, .v0),
5897 80 => {
5898 var dst_hi16_it = dst_vi.value.field(dst_ty, 8, 8);
5899 const dst_hi16_vi = try dst_hi16_it.only(isel);
5900 try call.returnLiveIn(isel, dst_hi16_vi.?, .r1);
5901 var dst_lo64_it = dst_vi.value.field(dst_ty, 0, 8);
5902 const dst_lo64_vi = try dst_lo64_it.only(isel);
5903 try call.returnLiveIn(isel, dst_lo64_vi.?, .r0);
5904 },
5905 }
5906 try call.finishReturn(isel);
5907
5908 try call.prepareCallee(isel);
5909 try isel.global_relocs.append(gpa, .{
5910 .global = switch (src_int_info.bits) {
5911 else => unreachable,
5912 1...32 => switch (src_int_info.signedness) {
5913 .signed => switch (dst_bits) {
5914 else => unreachable,
5915 16 => "__floatsihf",
5916 32 => "__floatsisf",
5917 64 => "__floatsidf",
5918 80 => "__floatsixf",
5919 128 => "__floatsitf",
5920 },
5921 .unsigned => switch (dst_bits) {
5922 else => unreachable,
5923 16 => "__floatunsihf",
5924 32 => "__floatunsisf",
5925 64 => "__floatunsidf",
5926 80 => "__floatunsixf",
5927 128 => "__floatunsitf",
5928 },
5929 },
5930 33...64 => switch (src_int_info.signedness) {
5931 .signed => switch (dst_bits) {
5932 else => unreachable,
5933 16 => "__floatdihf",
5934 32 => "__floatdisf",
5935 64 => "__floatdidf",
5936 80 => "__floatdixf",
5937 128 => "__floatditf",
5938 },
5939 .unsigned => switch (dst_bits) {
5940 else => unreachable,
5941 16 => "__floatundihf",
5942 32 => "__floatundisf",
5943 64 => "__floatundidf",
5944 80 => "__floatundixf",
5945 128 => "__floatunditf",
5946 },
5947 },
5948 65...128 => switch (src_int_info.signedness) {
5949 .signed => switch (dst_bits) {
5950 else => unreachable,
5951 16 => "__floattihf",
5952 32 => "__floattisf",
5953 64 => "__floattidf",
5954 80 => "__floattixf",
5955 128 => "__floattitf",
5956 },
5957 .unsigned => switch (dst_bits) {
5958 else => unreachable,
5959 16 => "__floatuntihf",
5960 32 => "__floatuntisf",
5961 64 => "__floatuntidf",
5962 80 => "__floatuntixf",
5963 128 => "__floatuntitf",
5964 },
5965 },
5966 },
5967 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
5968 });
5969 try isel.emit(.bl(0));
5970 try call.finishCallee(isel);
5971
5972 try call.prepareParams(isel);
5973 const src_vi = try isel.use(ty_op.operand);
5974 switch (src_int_info.bits) {
5975 else => unreachable,
5976 1...64 => try call.paramLiveOut(isel, src_vi, .r0),
5977 65...128 => {
5978 var src_hi64_it = src_vi.field(src_ty, 8, 8);
5979 const src_hi64_vi = try src_hi64_it.only(isel);
5980 try call.paramLiveOut(isel, src_hi64_vi.?, .r1);
5981 var src_lo64_it = src_vi.field(src_ty, 0, 8);
5982 const src_lo64_vi = try src_lo64_it.only(isel);
5983 try call.paramLiveOut(isel, src_lo64_vi.?, .r0);
5984 },
5985 }
5986 try call.finishParams(isel);
5987 },
5988 else => return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }),
5989 }
5990 }
5991 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5992 },
5993 .memset => |air_tag| {
5994 const bin_op = air.data(air.inst_index).bin_op;
5995 const dst_ty = isel.air.typeOf(bin_op.lhs, ip);
5996 const dst_info = dst_ty.ptrInfo(zcu);
5997 const fill_byte: union(enum) { constant: u8, value: Air.Inst.Ref } = fill_byte: {
5998 if (bin_op.rhs.toInterned()) |fill_val|
5999 if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte|
6000 break :fill_byte .{ .constant = fill_byte };
6001 switch (dst_ty.elemType2(zcu).abiSize(zcu)) {
6002 0 => unreachable,
6003 1 => break :fill_byte .{ .value = bin_op.rhs },
6004 2, 4, 8 => |size| {
6005 const dst_vi = try isel.use(bin_op.lhs);
6006 const ptr_ra = try isel.allocIntReg();
6007 const fill_vi = try isel.use(bin_op.rhs);
6008 const fill_mat = try fill_vi.matReg(isel);
6009 const len_mat: Value.Materialize = len_mat: switch (dst_info.flags.size) {
6010 .one => .{ .vi = undefined, .ra = try isel.allocIntReg() },
6011 .many => unreachable,
6012 .slice => {
6013 var dst_len_it = dst_vi.field(dst_ty, 8, 8);
6014 const dst_len_vi = try dst_len_it.only(isel);
6015 break :len_mat try dst_len_vi.?.matReg(isel);
6016 },
6017 .c => unreachable,
6018 };
6019
6020 const skip_label = isel.instructions.items.len;
6021 _ = try isel.instructions.addOne(gpa);
6022 try isel.emit(.sub(len_mat.ra.x(), len_mat.ra.x(), .{ .immediate = 1 }));
6023 try isel.emit(switch (size) {
6024 else => unreachable,
6025 2 => .strh(fill_mat.ra.w(), .{ .post_index = .{ .base = ptr_ra.x(), .index = 2 } }),
6026 4 => .str(fill_mat.ra.w(), .{ .post_index = .{ .base = ptr_ra.x(), .index = 4 } }),
6027 8 => .str(fill_mat.ra.x(), .{ .post_index = .{ .base = ptr_ra.x(), .index = 8 } }),
6028 });
6029 isel.instructions.items[skip_label] = .cbnz(
6030 len_mat.ra.x(),
6031 -@as(i21, @intCast((isel.instructions.items.len - 1 - skip_label) << 2)),
6032 );
6033 switch (dst_info.flags.size) {
6034 .one => {
6035 const len_imm = ZigType.fromInterned(dst_info.child).arrayLen(zcu);
6036 assert(len_imm > 0);
6037 try isel.movImmediate(len_mat.ra.x(), len_imm);
6038 isel.freeReg(len_mat.ra);
6039 try fill_mat.finish(isel);
6040 isel.freeReg(ptr_ra);
6041 try dst_vi.liveOut(isel, ptr_ra);
6042 },
6043 .many => unreachable,
6044 .slice => {
6045 try isel.emit(.cbz(
6046 len_mat.ra.x(),
6047 @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
6048 ));
6049 try len_mat.finish(isel);
6050 try fill_mat.finish(isel);
6051 isel.freeReg(ptr_ra);
6052 var dst_ptr_it = dst_vi.field(dst_ty, 0, 8);
6053 const dst_ptr_vi = try dst_ptr_it.only(isel);
6054 try dst_ptr_vi.?.liveOut(isel, ptr_ra);
6055 },
6056 .c => unreachable,
6057 }
6058
6059 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6060 break :air_tag;
6061 },
6062 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty) }),
6063 }
6064 };
6065
6066 try call.prepareReturn(isel);
6067 try call.finishReturn(isel);
6068
6069 try call.prepareCallee(isel);
6070 try isel.global_relocs.append(gpa, .{
6071 .global = "memset",
6072 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6073 });
6074 try isel.emit(.bl(0));
6075 try call.finishCallee(isel);
6076
6077 try call.prepareParams(isel);
6078 const dst_vi = try isel.use(bin_op.lhs);
6079 switch (dst_info.flags.size) {
6080 .one => {
6081 try isel.movImmediate(.x2, ZigType.fromInterned(dst_info.child).abiSize(zcu));
6082 switch (fill_byte) {
6083 .constant => |byte| try isel.movImmediate(.w1, byte),
6084 .value => |byte| try call.paramLiveOut(isel, try isel.use(byte), .r1),
6085 }
6086 try call.paramLiveOut(isel, dst_vi, .r0);
6087 },
6088 .many => unreachable,
6089 .slice => {
6090 var dst_ptr_it = dst_vi.field(dst_ty, 0, 8);
6091 const dst_ptr_vi = try dst_ptr_it.only(isel);
6092 var dst_len_it = dst_vi.field(dst_ty, 8, 8);
6093 const dst_len_vi = try dst_len_it.only(isel);
6094 try isel.elemPtr(.r2, .zr, .add, ZigType.fromInterned(dst_info.child).abiSize(zcu), dst_len_vi.?);
6095 switch (fill_byte) {
6096 .constant => |byte| try isel.movImmediate(.w1, byte),
6097 .value => |byte| try call.paramLiveOut(isel, try isel.use(byte), .r1),
6098 }
6099 try call.paramLiveOut(isel, dst_ptr_vi.?, .r0);
6100 },
6101 .c => unreachable,
6102 }
6103 try call.finishParams(isel);
6104
6105 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6106 },
6107 .memcpy, .memmove => |air_tag| {
6108 const bin_op = air.data(air.inst_index).bin_op;
6109 const dst_ty = isel.air.typeOf(bin_op.lhs, ip);
6110 const dst_info = dst_ty.ptrInfo(zcu);
6111
6112 try call.prepareReturn(isel);
6113 try call.finishReturn(isel);
6114
6115 try call.prepareCallee(isel);
6116 try isel.global_relocs.append(gpa, .{
6117 .global = @tagName(air_tag),
6118 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6119 });
6120 try isel.emit(.bl(0));
6121 try call.finishCallee(isel);
6122
6123 try call.prepareParams(isel);
6124 switch (dst_info.flags.size) {
6125 .one => {
6126 const dst_vi = try isel.use(bin_op.lhs);
6127 const src_vi = try isel.use(bin_op.rhs);
6128 try isel.movImmediate(.x2, ZigType.fromInterned(dst_info.child).abiSize(zcu));
6129 try call.paramLiveOut(isel, src_vi, .r1);
6130 try call.paramLiveOut(isel, dst_vi, .r0);
6131 },
6132 .many => unreachable,
6133 .slice => {
6134 const dst_vi = try isel.use(bin_op.lhs);
6135 var dst_ptr_it = dst_vi.field(dst_ty, 0, 8);
6136 const dst_ptr_vi = try dst_ptr_it.only(isel);
6137 var dst_len_it = dst_vi.field(dst_ty, 8, 8);
6138 const dst_len_vi = try dst_len_it.only(isel);
6139 const src_vi = try isel.use(bin_op.rhs);
6140 try isel.elemPtr(.r2, .zr, .add, ZigType.fromInterned(dst_info.child).abiSize(zcu), dst_len_vi.?);
6141 try call.paramLiveOut(isel, src_vi, .r1);
6142 try call.paramLiveOut(isel, dst_ptr_vi.?, .r0);
6143 },
6144 .c => unreachable,
6145 }
6146 try call.finishParams(isel);
6147
6148 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6149 },
6150 .atomic_load => {
6151 const atomic_load = air.data(air.inst_index).atomic_load;
6152 const ptr_ty = isel.air.typeOf(atomic_load.ptr, ip);
6153 const ptr_info = ptr_ty.ptrInfo(zcu);
6154 if (atomic_load.order != .unordered) return isel.fail("ordered atomic load", .{});
6155 if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed atomic load", .{});
6156
6157 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| {
6158 defer dst_vi.value.deref(isel);
6159 var ptr_mat: ?Value.Materialize = null;
6160 var dst_part_it = dst_vi.value.parts(isel);
6161 while (dst_part_it.next()) |dst_part_vi| {
6162 const dst_ra = try dst_part_vi.defReg(isel) orelse continue;
6163 if (ptr_mat == null) {
6164 const ptr_vi = try isel.use(atomic_load.ptr);
6165 ptr_mat = try ptr_vi.matReg(isel);
6166 }
6167 try isel.emit(switch (dst_part_vi.size(isel)) {
6168 else => |size| return isel.fail("bad atomic load size of {d} from {f}", .{
6169 size, isel.fmtType(ptr_ty),
6170 }),
6171 1 => switch (dst_part_vi.signedness(isel)) {
6172 .signed => .ldrsb(dst_ra.w(), .{ .unsigned_offset = .{
6173 .base = ptr_mat.?.ra.x(),
6174 .offset = @intCast(dst_part_vi.get(isel).offset_from_parent),
6175 } }),
6176 .unsigned => .ldrb(dst_ra.w(), .{ .unsigned_offset = .{
6177 .base = ptr_mat.?.ra.x(),
6178 .offset = @intCast(dst_part_vi.get(isel).offset_from_parent),
6179 } }),
6180 },
6181 2 => switch (dst_part_vi.signedness(isel)) {
6182 .signed => .ldrsh(dst_ra.w(), .{ .unsigned_offset = .{
6183 .base = ptr_mat.?.ra.x(),
6184 .offset = @intCast(dst_part_vi.get(isel).offset_from_parent),
6185 } }),
6186 .unsigned => .ldrh(dst_ra.w(), .{ .unsigned_offset = .{
6187 .base = ptr_mat.?.ra.x(),
6188 .offset = @intCast(dst_part_vi.get(isel).offset_from_parent),
6189 } }),
6190 },
6191 4 => .ldr(dst_ra.w(), .{ .unsigned_offset = .{
6192 .base = ptr_mat.?.ra.x(),
6193 .offset = @intCast(dst_part_vi.get(isel).offset_from_parent),
6194 } }),
6195 8 => .ldr(dst_ra.x(), .{ .unsigned_offset = .{
6196 .base = ptr_mat.?.ra.x(),
6197 .offset = @intCast(dst_part_vi.get(isel).offset_from_parent),
6198 } }),
6199 });
6200 }
6201 if (ptr_mat) |mat| try mat.finish(isel);
6202 } else if (ptr_info.flags.is_volatile) return isel.fail("volatile atomic load", .{});
6203
6204 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6205 },
6206 .aggregate_init => {
6207 if (isel.live_values.fetchRemove(air.inst_index)) |agg_vi| {
6208 defer agg_vi.value.deref(isel);
6209
6210 const ty_pl = air.data(air.inst_index).ty_pl;
6211 const agg_ty = ty_pl.ty.toType();
6212 switch (ip.indexToKey(agg_ty.toIntern())) {
6213 .array_type => |array_type| {
6214 const elems: []const Air.Inst.Ref =
6215 @ptrCast(isel.air.extra.items[ty_pl.payload..][0..@intCast(array_type.len)]);
6216 var elem_offset: u64 = 0;
6217 const elem_size = ZigType.fromInterned(array_type.child).abiSize(zcu);
6218 for (elems) |elem| {
6219 var agg_part_it = agg_vi.value.field(agg_ty, elem_offset, elem_size);
6220 const agg_part_vi = try agg_part_it.only(isel);
6221 try agg_part_vi.?.move(isel, elem);
6222 elem_offset += elem_size;
6223 }
6224 switch (array_type.sentinel) {
6225 .none => {},
6226 else => |sentinel| {
6227 var agg_part_it = agg_vi.value.field(agg_ty, elem_offset, elem_size);
6228 const agg_part_vi = try agg_part_it.only(isel);
6229 try agg_part_vi.?.move(isel, .fromIntern(sentinel));
6230 },
6231 }
6232 },
6233 .struct_type => {
6234 const loaded_struct = ip.loadStructType(agg_ty.toIntern());
6235 const elems: []const Air.Inst.Ref =
6236 @ptrCast(isel.air.extra.items[ty_pl.payload..][0..loaded_struct.field_types.len]);
6237 var field_offset: u64 = 0;
6238 var field_it = loaded_struct.iterateRuntimeOrder(ip);
6239 while (field_it.next()) |field_index| {
6240 const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
6241 field_offset = field_ty.structFieldAlignment(
6242 loaded_struct.fieldAlign(ip, field_index),
6243 loaded_struct.layout,
6244 zcu,
6245 ).forward(field_offset);
6246 const field_size = field_ty.abiSize(zcu);
6247 if (field_size == 0) continue;
6248 var agg_part_it = agg_vi.value.field(agg_ty, field_offset, field_size);
6249 const agg_part_vi = try agg_part_it.only(isel);
6250 try agg_part_vi.?.move(isel, elems[field_index]);
6251 field_offset += field_size;
6252 }
6253 assert(field_offset == agg_vi.value.size(isel));
6254 },
6255 .tuple_type => |tuple_type| {
6256 const elems: []const Air.Inst.Ref =
6257 @ptrCast(isel.air.extra.items[ty_pl.payload..][0..tuple_type.types.len]);
6258 var field_offset: u64 = 0;
6259 for (
6260 tuple_type.types.get(ip),
6261 tuple_type.values.get(ip),
6262 elems,
6263 ) |field_ty_index, field_val, elem| {
6264 if (field_val != .none) continue;
6265 const field_ty: ZigType = .fromInterned(field_ty_index);
6266 field_offset = field_ty.abiAlignment(zcu).forward(field_offset);
6267 const field_size = field_ty.abiSize(zcu);
6268 if (field_size == 0) continue;
6269 var agg_part_it = agg_vi.value.field(agg_ty, field_offset, field_size);
6270 const agg_part_vi = try agg_part_it.only(isel);
6271 try agg_part_vi.?.move(isel, elem);
6272 field_offset += field_size;
6273 }
6274 assert(field_offset == agg_vi.value.size(isel));
6275 },
6276 else => return isel.fail("aggregate init {f}", .{isel.fmtType(agg_ty)}),
6277 }
6278 }
6279 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6280 },
6281 .union_init => {
6282 if (isel.live_values.fetchRemove(air.inst_index)) |un_vi| unused: {
6283 defer un_vi.value.deref(isel);
6284
6285 const ty_pl = air.data(air.inst_index).ty_pl;
6286 const extra = isel.air.extraData(Air.UnionInit, ty_pl.payload).data;
6287 const un_ty = ty_pl.ty.toType();
6288 if (un_ty.containerLayout(zcu) != .@"extern") return isel.fail("bad union init {f}", .{isel.fmtType(un_ty)});
6289
6290 try un_vi.value.defAddr(isel, un_ty, null, comptime &.initFill(.free)) orelse break :unused;
6291
6292 try call.prepareReturn(isel);
6293 try call.finishReturn(isel);
6294
6295 try call.prepareCallee(isel);
6296 try isel.global_relocs.append(gpa, .{
6297 .global = "memcpy",
6298 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6299 });
6300 try isel.emit(.bl(0));
6301 try call.finishCallee(isel);
6302
6303 try call.prepareParams(isel);
6304 const init_vi = try isel.use(extra.init);
6305 try isel.movImmediate(.x2, init_vi.size(isel));
6306 try call.paramAddress(isel, init_vi, .r1);
6307 try call.paramAddress(isel, un_vi.value, .r0);
6308 try call.finishParams(isel);
6309 }
6310 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6311 },
6312 .prefetch => {
6313 const prefetch = air.data(air.inst_index).prefetch;
6314 if (!(prefetch.rw == .write and prefetch.cache == .instruction)) {
6315 const maybe_slice_ty = isel.air.typeOf(prefetch.ptr, ip);
6316 const maybe_slice_vi = try isel.use(prefetch.ptr);
6317 const ptr_vi = if (maybe_slice_ty.isSlice(zcu)) ptr_vi: {
6318 var ptr_part_it = maybe_slice_vi.field(maybe_slice_ty, 0, 8);
6319 const ptr_part_vi = try ptr_part_it.only(isel);
6320 break :ptr_vi ptr_part_vi.?;
6321 } else maybe_slice_vi;
6322 const ptr_mat = try ptr_vi.matReg(isel);
6323 try isel.emit(.prfm(.{
6324 .policy = switch (prefetch.locality) {
6325 1, 2, 3 => .keep,
6326 0 => .strm,
6327 },
6328 .target = switch (prefetch.locality) {
6329 0, 3 => .l1,
6330 2 => .l2,
6331 1 => .l3,
6332 },
6333 .type = switch (prefetch.rw) {
6334 .read => switch (prefetch.cache) {
6335 .data => .pld,
6336 .instruction => .pli,
6337 },
6338 .write => switch (prefetch.cache) {
6339 .data => .pst,
6340 .instruction => unreachable,
6341 },
6342 },
6343 }, .{ .base = ptr_mat.ra.x() }));
6344 try ptr_mat.finish(isel);
6345 }
6346 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6347 },
6348 .mul_add => {
6349 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
6350 defer res_vi.value.deref(isel);
6351
6352 const pl_op = air.data(air.inst_index).pl_op;
6353 const bin_op = isel.air.extraData(Air.Bin, pl_op.payload).data;
6354 const ty = isel.air.typeOf(pl_op.operand, ip);
6355 switch (ty.floatBits(isel.target)) {
6356 else => unreachable,
6357 16, 32, 64 => |bits| {
6358 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
6359 const need_fcvt = switch (bits) {
6360 else => unreachable,
6361 16 => !isel.target.cpu.has(.aarch64, .fullfp16),
6362 32, 64 => false,
6363 };
6364 if (need_fcvt) try isel.emit(.fcvt(res_ra.h(), res_ra.s()));
6365 const lhs_vi = try isel.use(bin_op.lhs);
6366 const rhs_vi = try isel.use(bin_op.rhs);
6367 const addend_vi = try isel.use(pl_op.operand);
6368 const lhs_mat = try lhs_vi.matReg(isel);
6369 const rhs_mat = try rhs_vi.matReg(isel);
6370 const addend_mat = try addend_vi.matReg(isel);
6371 const lhs_ra = if (need_fcvt) try isel.allocVecReg() else lhs_mat.ra;
6372 defer if (need_fcvt) isel.freeReg(lhs_ra);
6373 const rhs_ra = if (need_fcvt) try isel.allocVecReg() else rhs_mat.ra;
6374 defer if (need_fcvt) isel.freeReg(rhs_ra);
6375 const addend_ra = if (need_fcvt) try isel.allocVecReg() else addend_mat.ra;
6376 defer if (need_fcvt) isel.freeReg(addend_ra);
6377 try isel.emit(bits: switch (bits) {
6378 else => unreachable,
6379 16 => if (need_fcvt)
6380 continue :bits 32
6381 else
6382 .fmadd(res_ra.h(), lhs_ra.h(), rhs_ra.h(), addend_ra.h()),
6383 32 => .fmadd(res_ra.s(), lhs_ra.s(), rhs_ra.s(), addend_ra.s()),
6384 64 => .fmadd(res_ra.d(), lhs_ra.d(), rhs_ra.d(), addend_ra.d()),
6385 });
6386 if (need_fcvt) {
6387 try isel.emit(.fcvt(addend_ra.s(), addend_mat.ra.h()));
6388 try isel.emit(.fcvt(rhs_ra.s(), rhs_mat.ra.h()));
6389 try isel.emit(.fcvt(lhs_ra.s(), lhs_mat.ra.h()));
6390 }
6391 try addend_mat.finish(isel);
6392 try rhs_mat.finish(isel);
6393 try lhs_mat.finish(isel);
6394 },
6395 80, 128 => |bits| {
6396 try call.prepareReturn(isel);
6397 switch (bits) {
6398 else => unreachable,
6399 16, 32, 64, 128 => try call.returnLiveIn(isel, res_vi.value, .v0),
6400 80 => {
6401 var res_hi16_it = res_vi.value.field(ty, 8, 8);
6402 const res_hi16_vi = try res_hi16_it.only(isel);
6403 try call.returnLiveIn(isel, res_hi16_vi.?, .r1);
6404 var res_lo64_it = res_vi.value.field(ty, 0, 8);
6405 const res_lo64_vi = try res_lo64_it.only(isel);
6406 try call.returnLiveIn(isel, res_lo64_vi.?, .r0);
6407 },
6408 }
6409 try call.finishReturn(isel);
6410
6411 try call.prepareCallee(isel);
6412 try isel.global_relocs.append(gpa, .{
6413 .global = switch (bits) {
6414 else => unreachable,
6415 16 => "__fmah",
6416 32 => "fmaf",
6417 64 => "fma",
6418 80 => "__fmax",
6419 128 => "fmaq",
6420 },
6421 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6422 });
6423 try isel.emit(.bl(0));
6424 try call.finishCallee(isel);
6425
6426 try call.prepareParams(isel);
6427 const lhs_vi = try isel.use(bin_op.lhs);
6428 const rhs_vi = try isel.use(bin_op.rhs);
6429 const addend_vi = try isel.use(pl_op.operand);
6430 switch (bits) {
6431 else => unreachable,
6432 16, 32, 64, 128 => {
6433 try call.paramLiveOut(isel, addend_vi, .v2);
6434 try call.paramLiveOut(isel, rhs_vi, .v1);
6435 try call.paramLiveOut(isel, lhs_vi, .v0);
6436 },
6437 80 => {
6438 var addend_hi16_it = addend_vi.field(ty, 8, 8);
6439 const addend_hi16_vi = try addend_hi16_it.only(isel);
6440 try call.paramLiveOut(isel, addend_hi16_vi.?, .r5);
6441 var addend_lo64_it = addend_vi.field(ty, 0, 8);
6442 const addend_lo64_vi = try addend_lo64_it.only(isel);
6443 try call.paramLiveOut(isel, addend_lo64_vi.?, .r4);
6444 var rhs_hi16_it = rhs_vi.field(ty, 8, 8);
6445 const rhs_hi16_vi = try rhs_hi16_it.only(isel);
6446 try call.paramLiveOut(isel, rhs_hi16_vi.?, .r3);
6447 var rhs_lo64_it = rhs_vi.field(ty, 0, 8);
6448 const rhs_lo64_vi = try rhs_lo64_it.only(isel);
6449 try call.paramLiveOut(isel, rhs_lo64_vi.?, .r2);
6450 var lhs_hi16_it = lhs_vi.field(ty, 8, 8);
6451 const lhs_hi16_vi = try lhs_hi16_it.only(isel);
6452 try call.paramLiveOut(isel, lhs_hi16_vi.?, .r1);
6453 var lhs_lo64_it = lhs_vi.field(ty, 0, 8);
6454 const lhs_lo64_vi = try lhs_lo64_it.only(isel);
6455 try call.paramLiveOut(isel, lhs_lo64_vi.?, .r0);
6456 },
6457 }
6458 try call.finishParams(isel);
6459 },
6460 }
6461 }
6462 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6463 },
6464 .field_parent_ptr => {
6465 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
6466 defer dst_vi.value.deref(isel);
6467 const ty_pl = air.data(air.inst_index).ty_pl;
6468 const extra = isel.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
6469 switch (codegen.fieldOffset(
6470 ty_pl.ty.toType(),
6471 isel.air.typeOf(extra.field_ptr, ip),
6472 extra.field_index,
6473 zcu,
6474 )) {
6475 0 => try dst_vi.value.move(isel, extra.field_ptr),
6476 else => |field_offset| {
6477 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
6478 const src_vi = try isel.use(extra.field_ptr);
6479 const src_mat = try src_vi.matReg(isel);
6480 const lo12: u12 = @truncate(field_offset >> 0);
6481 const hi12: u12 = @intCast(field_offset >> 12);
6482 if (hi12 > 0) try isel.emit(.sub(
6483 dst_ra.x(),
6484 if (lo12 > 0) dst_ra.x() else src_mat.ra.x(),
6485 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
6486 ));
6487 if (lo12 > 0) try isel.emit(.sub(dst_ra.x(), src_mat.ra.x(), .{ .immediate = lo12 }));
6488 try src_mat.finish(isel);
6489 },
6490 }
6491 }
6492 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6493 },
6494 .runtime_nav_ptr => {
6495 if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: {
6496 defer ptr_vi.value.deref(isel);
6497 const ptr_ra = try ptr_vi.value.defReg(isel) orelse break :unused;
6498
6499 const ty_nav = air.data(air.inst_index).ty_nav;
6500 if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) {
6501 false => {
6502 try isel.nav_relocs.append(zcu.gpa, .{
6503 .nav = ty_nav.nav,
6504 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6505 });
6506 try isel.emit(.adr(ptr_ra.x(), 0));
6507 },
6508 true => {
6509 try isel.nav_relocs.append(zcu.gpa, .{
6510 .nav = ty_nav.nav,
6511 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6512 });
6513 try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 }));
6514 try isel.nav_relocs.append(zcu.gpa, .{
6515 .nav = ty_nav.nav,
6516 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6517 });
6518 try isel.emit(.adrp(ptr_ra.x(), 0));
6519 },
6520 } else try isel.movImmediate(ptr_ra.x(), isel.pt.navAlignment(ty_nav.nav).forward(0xaaaaaaaaaaaaaaaa));
6521 }
6522 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6523 },
6524 .add_safe,
6525 .sub_safe,
6526 .mul_safe,
6527 .inferred_alloc,
6528 .inferred_alloc_comptime,
6529 .int_from_float_safe,
6530 .int_from_float_optimized_safe,
6531 .wasm_memory_size,
6532 .wasm_memory_grow,
6533 .work_item_id,
6534 .work_group_size,
6535 .work_group_id,
6536 => unreachable,
6537 }
6538 assert(air.body_index == 0);
6539}
6540
6541pub fn verify(isel: *Select, check_values: bool) void {
6542 if (!std.debug.runtime_safety) return;
6543 assert(isel.blocks.count() == 1 and isel.blocks.keys()[0] == Select.Block.main);
6544 assert(isel.active_loops.items.len == 0);
6545 assert(isel.dom_start == 0 and isel.dom_len == 0);
6546 var live_reg_it = isel.live_registers.iterator();
6547 while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) {
6548 _ => {
6549 isel.dumpValues(.all);
6550 unreachable;
6551 },
6552 .allocating, .free => {},
6553 };
6554 if (check_values) for (isel.values.items) |value| if (value.refs != 0) {
6555 isel.dumpValues(.only_referenced);
6556 unreachable;
6557 };
6558}
6559
6560/// Stack Frame Layout
6561/// +-+-----------------------------------+
6562/// |R| allocated stack |
6563/// +-+-----------------------------------+
6564/// |S| caller frame record | +---------------+
6565/// +-+-----------------------------------+ <-| entry/exit FP |
6566/// |R| caller frame | +---------------+
6567/// +-+-----------------------------------+
6568/// |R| variable incoming stack arguments | +---------------+
6569/// +-+-----------------------------------+ <-| __stack |
6570/// |S| named incoming stack arguments | +---------------+
6571/// +-+-----------------------------------+ <-| entry/exit SP |
6572/// |S| incoming gr arguments | | __gr_top |
6573/// +-+-----------------------------------+ +---------------+
6574/// |S| alignment gap |
6575/// +-+-----------------------------------+
6576/// |S| frame record | +----------+
6577/// +-+-----------------------------------+ <-| FP |
6578/// |S| incoming vr arguments | | __vr_top |
6579/// +-+-----------------------------------+ +----------+
6580/// |L| alignment gap |
6581/// +-+-----------------------------------+
6582/// |L| callee saved vr area |
6583/// +-+-----------------------------------+
6584/// |L| callee saved gr area | +----------------------+
6585/// +-+-----------------------------------+ <-| prologue/epilogue SP |
6586/// |R| realignment gap | +----------------------+
6587/// +-+-----------------------------------+
6588/// |L| locals |
6589/// +-+-----------------------------------+
6590/// |S| outgoing stack arguments | +----+
6591/// +-+-----------------------------------+ <-| SP |
6592/// |R| unallocated stack | +----+
6593/// +-+-----------------------------------+
6594/// [S] Size computed by `analyze`, can be used by the body.
6595/// [L] Size computed by `layout`, can be used by the prologue/epilogue.
6596/// [R] Size unknown until runtime, can vary from one call to the next.
6597///
6598/// Constraints that led to this layout:
6599/// * FP to __stack/__gr_top/__vr_top must only pass through [S]
6600/// * SP to outgoing stack arguments/locals must only pass through [S]
6601/// * entry/exit SP to prologue/epilogue SP must only pass through [S/L]
6602/// * all save areas must be at a positive offset from prologue/epilogue SP
6603/// * the entry/exit SP to prologue/epilogue SP distance must
6604/// - be a multiple of 16 due to hardware restrictions on the value of SP
6605/// - conform to the limit from the first matching condition in the
6606/// following list due to instruction encoding limitations
6607/// 1. callee saved gr count >= 2: multiple of 8 of at most 504 bytes
6608/// 2. callee saved vr count >= 2: multiple of 8 of at most 504 bytes
6609/// 3. callee saved gr count >= 1: at most 255 bytes
6610/// 4. callee saved vr count >= 1: at most 255 bytes
6611/// 5. variable incoming vr argument count >= 2: multiple of 16 of at most 1008 bytes
6612/// 6. variable incoming vr argument count >= 1: at most 255 bytes
6613/// 7. have frame record: multiple of 8 of at most 504 bytes
6614pub fn layout(
6615 isel: *Select,
6616 incoming: CallAbiIterator,
6617 have_va: bool,
6618 saved_gra_len: u7,
6619 saved_vra_len: u7,
6620 mod: *const Package.Module,
6621) !usize {
6622 const zcu = isel.pt.zcu;
6623 const ip = &zcu.intern_pool;
6624 const nav = ip.getNav(isel.nav_index);
6625 wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)});
6626
6627 const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));
6628 const stack_size_low: u12 = @truncate(stack_size >> 0);
6629 const stack_size_high: u12 = @truncate(stack_size >> 12);
6630
6631 var saves_buf: [10 + 8 + 8 + 2 + 8]struct {
6632 class: enum { integer, vector },
6633 needs_restore: bool,
6634 register: Register,
6635 offset: u10,
6636 size: u5,
6637 } = undefined;
6638 const saves, const saves_size, const frame_record_offset = saves: {
6639 var saves_len: usize = 0;
6640 var saves_size: u10 = 0;
6641 var save_ra: Register.Alias = undefined;
6642
6643 // callee saved gr area
6644 save_ra = .r19;
6645 while (save_ra != .r29) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
6646 if (!isel.saved_registers.contains(save_ra)) continue;
6647 saves_size = std.mem.alignForward(u10, saves_size, 8);
6648 saves_buf[saves_len] = .{
6649 .class = .integer,
6650 .needs_restore = true,
6651 .register = save_ra.x(),
6652 .offset = saves_size,
6653 .size = 8,
6654 };
6655 saves_len += 1;
6656 saves_size += 8;
6657 }
6658 var deferred_gr = if (saves_size == 8 or (saves_size % 16 != 0 and saved_gra_len % 2 != 0)) gr: {
6659 saves_len -= 1;
6660 saves_size -= 8;
6661 break :gr saves_buf[saves_len].register;
6662 } else null;
6663 defer assert(deferred_gr == null);
6664
6665 // callee saved vr area
6666 save_ra = .v8;
6667 while (save_ra != .v16) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
6668 if (!isel.saved_registers.contains(save_ra)) continue;
6669 saves_size = std.mem.alignForward(u10, saves_size, 8);
6670 saves_buf[saves_len] = .{
6671 .class = .vector,
6672 .needs_restore = true,
6673 .register = save_ra.d(),
6674 .offset = saves_size,
6675 .size = 8,
6676 };
6677 saves_len += 1;
6678 saves_size += 8;
6679 }
6680 if (deferred_gr != null and saved_gra_len % 2 == 0) {
6681 saves_size = std.mem.alignForward(u10, saves_size, 8);
6682 saves_buf[saves_len] = .{
6683 .class = .integer,
6684 .needs_restore = true,
6685 .register = deferred_gr.?,
6686 .offset = saves_size,
6687 .size = 8,
6688 };
6689 saves_len += 1;
6690 saves_size += 8;
6691 deferred_gr = null;
6692 }
6693 if (saves_size % 16 != 0 and saved_vra_len % 2 != 0) {
6694 const prev_save = &saves_buf[saves_len - 1];
6695 switch (prev_save.class) {
6696 .integer => {},
6697 .vector => {
6698 prev_save.register = prev_save.register.alias.q();
6699 prev_save.size = 16;
6700 saves_size += 8;
6701 },
6702 }
6703 }
6704
6705 // incoming vr arguments
6706 save_ra = if (mod.strip) incoming.nsrn else CallAbiIterator.nsrn_start;
6707 while (save_ra != if (have_va) CallAbiIterator.nsrn_end else incoming.nsrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
6708 saves_size = std.mem.alignForward(u10, saves_size, 16);
6709 saves_buf[saves_len] = .{
6710 .class = .vector,
6711 .needs_restore = false,
6712 .register = save_ra.q(),
6713 .offset = saves_size,
6714 .size = 16,
6715 };
6716 saves_len += 1;
6717 saves_size += 16;
6718 }
6719
6720 // frame record
6721 saves_size = std.mem.alignForward(u10, saves_size, 16);
6722 const frame_record_offset = saves_size;
6723 saves_buf[saves_len] = .{
6724 .class = .integer,
6725 .needs_restore = true,
6726 .register = .fp,
6727 .offset = saves_size,
6728 .size = 8,
6729 };
6730 saves_len += 1;
6731 saves_size += 8;
6732
6733 saves_size = std.mem.alignForward(u10, saves_size, 8);
6734 saves_buf[saves_len] = .{
6735 .class = .integer,
6736 .needs_restore = true,
6737 .register = .lr,
6738 .offset = saves_size,
6739 .size = 8,
6740 };
6741 saves_len += 1;
6742 saves_size += 8;
6743
6744 // incoming gr arguments
6745 if (deferred_gr) |gr| {
6746 saves_size = std.mem.alignForward(u10, saves_size, 8);
6747 saves_buf[saves_len] = .{
6748 .class = .integer,
6749 .needs_restore = true,
6750 .register = gr,
6751 .offset = saves_size,
6752 .size = 8,
6753 };
6754 saves_len += 1;
6755 saves_size += 8;
6756 deferred_gr = null;
6757 }
6758 save_ra = if (mod.strip) incoming.ngrn else CallAbiIterator.ngrn_start;
6759 while (save_ra != if (have_va) CallAbiIterator.ngrn_end else incoming.ngrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
6760 saves_size = std.mem.alignForward(u10, saves_size, 8);
6761 saves_buf[saves_len] = .{
6762 .class = .integer,
6763 .needs_restore = false,
6764 .register = save_ra.x(),
6765 .offset = saves_size,
6766 .size = 8,
6767 };
6768 saves_len += 1;
6769 saves_size += 8;
6770 }
6771
6772 assert(InternPool.Alignment.@"16".check(saves_size));
6773 break :saves .{ saves_buf[0..saves_len], saves_size, frame_record_offset };
6774 };
6775
6776 {
6777 wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)});
6778 var save_index: usize = 0;
6779 while (save_index < saves.len) {
6780 if (save_index + 2 <= saves.len and saves[save_index + 0].class == saves[save_index + 1].class and
6781 saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset)
6782 {
6783 try isel.emit(.stp(
6784 saves[save_index + 0].register,
6785 saves[save_index + 1].register,
6786 switch (saves[save_index + 0].offset) {
6787 0 => .{ .pre_index = .{
6788 .base = .sp,
6789 .index = @intCast(-@as(i11, saves_size)),
6790 } },
6791 else => |offset| .{ .signed_offset = .{
6792 .base = .sp,
6793 .offset = @intCast(offset),
6794 } },
6795 },
6796 ));
6797 save_index += 2;
6798 } else {
6799 try isel.emit(.str(
6800 saves[save_index].register,
6801 switch (saves[save_index].offset) {
6802 0 => .{ .pre_index = .{
6803 .base = .sp,
6804 .index = @intCast(-@as(i11, saves_size)),
6805 } },
6806 else => |offset| .{ .unsigned_offset = .{
6807 .base = .sp,
6808 .offset = @intCast(offset),
6809 } },
6810 },
6811 ));
6812 save_index += 1;
6813 }
6814 }
6815
6816 const scratch_reg: Register = if (isel.stack_align == .@"16")
6817 .sp
6818 else if (stack_size == 0)
6819 .fp
6820 else
6821 .x9;
6822 try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
6823 if (stack_size_high > 0) try isel.emit(.sub(scratch_reg, .sp, .{
6824 .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
6825 }));
6826 if (stack_size_low > 0) try isel.emit(.sub(
6827 scratch_reg,
6828 if (stack_size_high > 0) scratch_reg else .sp,
6829 .{ .immediate = stack_size_low },
6830 ));
6831 if (isel.stack_align != .@"16") {
6832 try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{
6833 .N = .doubleword,
6834 .immr = -%isel.stack_align.toLog2Units(),
6835 .imms = ~isel.stack_align.toLog2Units(),
6836 } }));
6837 }
6838 wip_mir_log.debug("", .{});
6839 }
6840
6841 const epilogue = isel.instructions.items.len;
6842 if (isel.returns) {
6843 try isel.emit(.ret(.lr));
6844 var save_index: usize = 0;
6845 while (save_index < saves.len) {
6846 if (save_index + 2 <= saves.len and saves[save_index + 1].needs_restore and
6847 saves[save_index + 0].class == saves[save_index + 1].class and
6848 saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset)
6849 {
6850 try isel.emit(.ldp(
6851 saves[save_index + 0].register,
6852 saves[save_index + 1].register,
6853 switch (saves[save_index + 0].offset) {
6854 0 => .{ .post_index = .{
6855 .base = .sp,
6856 .index = @intCast(saves_size),
6857 } },
6858 else => |offset| .{ .signed_offset = .{
6859 .base = .sp,
6860 .offset = @intCast(offset),
6861 } },
6862 },
6863 ));
6864 save_index += 2;
6865 } else if (saves[save_index].needs_restore) {
6866 try isel.emit(.ldr(
6867 saves[save_index].register,
6868 switch (saves[save_index].offset) {
6869 0 => .{ .post_index = .{
6870 .base = .sp,
6871 .index = @intCast(saves_size),
6872 } },
6873 else => |offset| .{ .unsigned_offset = .{
6874 .base = .sp,
6875 .offset = @intCast(offset),
6876 } },
6877 },
6878 ));
6879 save_index += 1;
6880 } else save_index += 1;
6881 }
6882 if (isel.stack_align != .@"16" or (stack_size_low > 0 and stack_size_high > 0)) {
6883 try isel.emit(switch (frame_record_offset) {
6884 0 => .add(.sp, .fp, .{ .immediate = 0 }),
6885 else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),
6886 });
6887 } else {
6888 if (stack_size_high > 0) try isel.emit(.add(.sp, .sp, .{
6889 .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
6890 }));
6891 if (stack_size_low > 0) try isel.emit(.add(.sp, .sp, .{
6892 .immediate = stack_size_low,
6893 }));
6894 }
6895 wip_mir_log.debug("{f}<epilogue>:\n", .{nav.fqn.fmt(ip)});
6896 }
6897 return epilogue;
6898}
6899
6900fn fmtDom(isel: *Select, inst: Air.Inst.Index, start: u32, len: u32) struct {
6901 isel: *Select,
6902 inst: Air.Inst.Index,
6903 start: u32,
6904 len: u32,
6905 pub fn format(data: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
6906 try writer.print("%{d} -> {{", .{@intFromEnum(data.inst)});
6907 var first = true;
6908 for (data.isel.blocks.keys()[0..data.len], 0..) |block_inst_index, dom_index| {
6909 if (@as(u1, @truncate(data.isel.dom.items[
6910 data.start + dom_index / @bitSizeOf(DomInt)
6911 ] >> @truncate(dom_index))) == 0) continue;
6912 if (first) {
6913 first = false;
6914 } else {
6915 try writer.writeByte(',');
6916 }
6917 switch (block_inst_index) {
6918 Block.main => try writer.writeAll(" %main"),
6919 else => try writer.print(" %{d}", .{@intFromEnum(block_inst_index)}),
6920 }
6921 }
6922 if (!first) try writer.writeByte(' ');
6923 try writer.writeByte('}');
6924 }
6925} {
6926 return .{ .isel = isel, .inst = inst, .start = start, .len = len };
6927}
6928
6929fn fmtLoopLive(isel: *Select, loop_inst: Air.Inst.Index) struct {
6930 isel: *Select,
6931 inst: Air.Inst.Index,
6932 pub fn format(data: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
6933 const loops = data.isel.loops.values();
6934 const loop_index = data.isel.loops.getIndex(data.inst).?;
6935 const live_insts =
6936 data.isel.loop_live.list.items[loops[loop_index].live..loops[loop_index + 1].live];
6937
6938 try writer.print("%{d} <- {{", .{@intFromEnum(data.inst)});
6939 var first = true;
6940 for (live_insts) |live_inst| {
6941 if (first) {
6942 first = false;
6943 } else {
6944 try writer.writeByte(',');
6945 }
6946 try writer.print(" %{d}", .{@intFromEnum(live_inst)});
6947 }
6948 if (!first) try writer.writeByte(' ');
6949 try writer.writeByte('}');
6950 }
6951} {
6952 return .{ .isel = isel, .inst = loop_inst };
6953}
6954
6955fn fmtType(isel: *Select, ty: ZigType) ZigType.Formatter {
6956 return ty.fmt(isel.pt);
6957}
6958
6959fn fmtConstant(isel: *Select, constant: Constant) @typeInfo(@TypeOf(Constant.fmtValue)).@"fn".return_type.? {
6960 return constant.fmtValue(isel.pt);
6961}
6962
6963fn emit(isel: *Select, instruction: codegen.aarch64.encoding.Instruction) !void {
6964 wip_mir_log.debug(" | {f}", .{instruction});
6965 try isel.instructions.append(isel.pt.zcu.gpa, instruction);
6966}
6967
6968fn emitLiteral(isel: *Select, bytes: []const u8) !void {
6969 const words: []align(1) const u32 = @ptrCast(bytes);
6970 const literals = try isel.literals.addManyAsSlice(isel.pt.zcu.gpa, words.len);
6971 switch (isel.target.cpu.arch.endian()) {
6972 .little => @memcpy(literals, words),
6973 .big => for (words, 0..) |word, word_index| {
6974 literals[literals.len - 1 - word_index] = @byteSwap(word);
6975 },
6976 }
6977}
6978
6979fn fail(isel: *Select, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
6980 @branchHint(.cold);
6981 return isel.pt.zcu.codegenFail(isel.nav_index, format, args);
6982}
6983
6984/// dst = src
6985fn movImmediate(isel: *Select, dst_reg: Register, src_imm: u64) !void {
6986 const sf = dst_reg.format.integer;
6987 if (src_imm == 0) {
6988 const zr: Register = switch (sf) {
6989 .word => .wzr,
6990 .doubleword => .xzr,
6991 };
6992 return isel.emit(.orr(dst_reg, zr, .{ .register = zr }));
6993 }
6994
6995 const Part = u16;
6996 const min_part: Part = std.math.minInt(Part);
6997 const max_part: Part = std.math.maxInt(Part);
6998
6999 const parts: [4]Part = @bitCast(switch (sf) {
7000 .word => @as(u32, @intCast(src_imm)),
7001 .doubleword => @as(u64, @intCast(src_imm)),
7002 });
7003 const width: u7 = switch (sf) {
7004 .word => 32,
7005 .doubleword => 64,
7006 };
7007 const parts_len: u3 = @intCast(@divExact(width, @bitSizeOf(Part)));
7008 var equal_min_count: u3 = 0;
7009 var equal_max_count: u3 = 0;
7010 for (parts[0..parts_len]) |part| {
7011 equal_min_count += @intFromBool(part == min_part);
7012 equal_max_count += @intFromBool(part == max_part);
7013 }
7014
7015 const equal_fill_count, const fill_part: Part = if (equal_min_count >= equal_max_count)
7016 .{ equal_min_count, min_part }
7017 else
7018 .{ equal_max_count, max_part };
7019 var remaining_parts = @max(parts_len - equal_fill_count, 1);
7020
7021 if (remaining_parts > 1) {
7022 var elem_width: u8 = 2;
7023 while (elem_width <= width) : (elem_width <<= 1) {
7024 const emask = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - elem_width);
7025 const rmask = @divExact(@as(u64, switch (sf) {
7026 .word => std.math.maxInt(u32),
7027 .doubleword => std.math.maxInt(u64),
7028 }), emask);
7029 const elem = src_imm & emask;
7030 if (src_imm != elem * rmask) continue;
7031 const imask: u64 = @bitCast(@as(i64, @bitCast(elem << 63)) >> 63);
7032 const lsb0 = elem ^ (imask & emask);
7033 const lsb1 = (lsb0 - 1) | lsb0;
7034 if ((lsb1 +% 1) & lsb1 == 0) {
7035 const lo: u6 = @intCast(@ctz(lsb0));
7036 const hi: u6 = @intCast(@clz(lsb0) - (64 - elem_width));
7037 const mid: u6 = @intCast(elem_width - lo - hi);
7038 const smask: u6 = @truncate(imask);
7039 const mid_masked = mid & ~smask;
7040 return isel.emit(.orr(
7041 dst_reg,
7042 switch (sf) {
7043 .word => .wzr,
7044 .doubleword => .xzr,
7045 },
7046 .{ .immediate = .{
7047 .N = @enumFromInt(elem_width >> 6),
7048 .immr = hi + mid_masked,
7049 .imms = ((((lo + hi) & smask) | mid_masked) - 1) | -%@as(u6, @truncate(elem_width)) << 1,
7050 } },
7051 ));
7052 }
7053 }
7054 }
7055
7056 var part_index = parts_len;
7057 while (part_index > 0) {
7058 part_index -= 1;
7059 if (part_index >= remaining_parts and parts[part_index] == fill_part) continue;
7060 remaining_parts -= 1;
7061 try isel.emit(if (remaining_parts > 0) .movk(
7062 dst_reg,
7063 parts[part_index],
7064 .{ .lsl = @enumFromInt(part_index) },
7065 ) else switch (fill_part) {
7066 else => unreachable,
7067 min_part => .movz(
7068 dst_reg,
7069 parts[part_index],
7070 .{ .lsl = @enumFromInt(part_index) },
7071 ),
7072 max_part => .movn(
7073 dst_reg,
7074 ~parts[part_index],
7075 .{ .lsl = @enumFromInt(part_index) },
7076 ),
7077 });
7078 }
7079 assert(remaining_parts == 0);
7080}
7081
7082/// elem_ptr = base +- elem_size * index
7083/// elem_ptr, base, and index may alias
7084fn elemPtr(
7085 isel: *Select,
7086 elem_ptr_ra: Register.Alias,
7087 base_ra: Register.Alias,
7088 op: codegen.aarch64.encoding.Instruction.AddSubtractOp,
7089 elem_size: u64,
7090 index_vi: Value.Index,
7091) !void {
7092 const index_mat = try index_vi.matReg(isel);
7093 switch (@popCount(elem_size)) {
7094 0 => unreachable,
7095 1 => try isel.emit(switch (op) {
7096 .add => switch (base_ra) {
7097 else => .add(elem_ptr_ra.x(), base_ra.x(), .{ .shifted_register = .{
7098 .register = index_mat.ra.x(),
7099 .shift = .{ .lsl = @intCast(@ctz(elem_size)) },
7100 } }),
7101 .zr => switch (@ctz(elem_size)) {
7102 0 => .orr(elem_ptr_ra.x(), .xzr, .{ .register = index_mat.ra.x() }),
7103 else => |shift| .ubfm(elem_ptr_ra.x(), index_mat.ra.x(), .{
7104 .N = .doubleword,
7105 .immr = @intCast(64 - shift),
7106 .imms = @intCast(63 - shift),
7107 }),
7108 },
7109 },
7110 .sub => .sub(elem_ptr_ra.x(), base_ra.x(), .{ .shifted_register = .{
7111 .register = index_mat.ra.x(),
7112 .shift = .{ .lsl = @intCast(@ctz(elem_size)) },
7113 } }),
7114 }),
7115 2 => {
7116 const shift: u6 = @intCast(@ctz(elem_size));
7117 const temp_ra = temp_ra: switch (op) {
7118 .add => switch (base_ra) {
7119 else => {
7120 const temp_ra = try isel.allocIntReg();
7121 errdefer isel.freeReg(temp_ra);
7122 try isel.emit(.add(elem_ptr_ra.x(), base_ra.x(), .{ .shifted_register = .{
7123 .register = temp_ra.x(),
7124 .shift = .{ .lsl = shift },
7125 } }));
7126 break :temp_ra temp_ra;
7127 },
7128 .zr => {
7129 if (shift > 0) try isel.emit(.ubfm(elem_ptr_ra.x(), elem_ptr_ra.x(), .{
7130 .N = .doubleword,
7131 .immr = -%shift,
7132 .imms = ~shift,
7133 }));
7134 break :temp_ra elem_ptr_ra;
7135 },
7136 },
7137 .sub => {
7138 const temp_ra = try isel.allocIntReg();
7139 errdefer isel.freeReg(temp_ra);
7140 try isel.emit(.sub(elem_ptr_ra.x(), base_ra.x(), .{ .shifted_register = .{
7141 .register = temp_ra.x(),
7142 .shift = .{ .lsl = shift },
7143 } }));
7144 break :temp_ra temp_ra;
7145 },
7146 };
7147 defer if (temp_ra != elem_ptr_ra) isel.freeReg(temp_ra);
7148 try isel.emit(.add(temp_ra.x(), index_mat.ra.x(), .{ .shifted_register = .{
7149 .register = index_mat.ra.x(),
7150 .shift = .{ .lsl = @intCast(63 - @clz(elem_size) - shift) },
7151 } }));
7152 },
7153 else => {
7154 const elem_size_lsb1 = (elem_size - 1) | elem_size;
7155 if ((elem_size_lsb1 +% 1) & elem_size_lsb1 == 0) {
7156 const shift: u6 = @intCast(@ctz(elem_size));
7157 const temp_ra = temp_ra: switch (op) {
7158 .add => {
7159 const temp_ra = try isel.allocIntReg();
7160 errdefer isel.freeReg(temp_ra);
7161 try isel.emit(.sub(elem_ptr_ra.x(), base_ra.x(), .{ .shifted_register = .{
7162 .register = temp_ra.x(),
7163 .shift = .{ .lsl = shift },
7164 } }));
7165 break :temp_ra temp_ra;
7166 },
7167 .sub => switch (base_ra) {
7168 else => {
7169 const temp_ra = try isel.allocIntReg();
7170 errdefer isel.freeReg(temp_ra);
7171 try isel.emit(.add(elem_ptr_ra.x(), base_ra.x(), .{ .shifted_register = .{
7172 .register = temp_ra.x(),
7173 .shift = .{ .lsl = shift },
7174 } }));
7175 break :temp_ra temp_ra;
7176 },
7177 .zr => {
7178 if (shift > 0) try isel.emit(.ubfm(elem_ptr_ra.x(), elem_ptr_ra.x(), .{
7179 .N = .doubleword,
7180 .immr = -%shift,
7181 .imms = ~shift,
7182 }));
7183 break :temp_ra elem_ptr_ra;
7184 },
7185 },
7186 };
7187 defer if (temp_ra != elem_ptr_ra) isel.freeReg(temp_ra);
7188 try isel.emit(.sub(temp_ra.x(), index_mat.ra.x(), .{ .shifted_register = .{
7189 .register = index_mat.ra.x(),
7190 .shift = .{ .lsl = @intCast(64 - @clz(elem_size) - shift) },
7191 } }));
7192 } else {
7193 try isel.emit(switch (op) {
7194 .add => .madd(elem_ptr_ra.x(), index_mat.ra.x(), elem_ptr_ra.x(), base_ra.x()),
7195 .sub => .msub(elem_ptr_ra.x(), index_mat.ra.x(), elem_ptr_ra.x(), base_ra.x()),
7196 });
7197 try isel.movImmediate(elem_ptr_ra.x(), elem_size);
7198 }
7199 },
7200 }
7201 try index_mat.finish(isel);
7202}
7203
7204fn clzLimb(
7205 isel: *Select,
7206 res_ra: Register.Alias,
7207 src_int_info: std.builtin.Type.Int,
7208 src_ra: Register.Alias,
7209) !void {
7210 switch (src_int_info.bits) {
7211 else => unreachable,
7212 1...31 => |bits| {
7213 try isel.emit(.sub(res_ra.w(), res_ra.w(), .{
7214 .immediate = @intCast(32 - bits),
7215 }));
7216 switch (src_int_info.signedness) {
7217 .signed => {
7218 try isel.emit(.clz(res_ra.w(), res_ra.w()));
7219 try isel.emit(.ubfm(res_ra.w(), src_ra.w(), .{
7220 .N = .word,
7221 .immr = 0,
7222 .imms = @intCast(bits - 1),
7223 }));
7224 },
7225 .unsigned => try isel.emit(.clz(res_ra.w(), src_ra.w())),
7226 }
7227 },
7228 32 => try isel.emit(.clz(res_ra.w(), src_ra.w())),
7229 33...63 => |bits| {
7230 try isel.emit(.sub(res_ra.w(), res_ra.w(), .{
7231 .immediate = @intCast(64 - bits),
7232 }));
7233 switch (src_int_info.signedness) {
7234 .signed => {
7235 try isel.emit(.clz(res_ra.x(), res_ra.x()));
7236 try isel.emit(.ubfm(res_ra.x(), src_ra.x(), .{
7237 .N = .doubleword,
7238 .immr = 0,
7239 .imms = @intCast(bits - 1),
7240 }));
7241 },
7242 .unsigned => try isel.emit(.clz(res_ra.x(), src_ra.x())),
7243 }
7244 },
7245 64 => try isel.emit(.clz(res_ra.x(), src_ra.x())),
7246 }
7247}
7248
7249fn ctzLimb(
7250 isel: *Select,
7251 res_ra: Register.Alias,
7252 src_int_info: std.builtin.Type.Int,
7253 src_ra: Register.Alias,
7254) !void {
7255 switch (src_int_info.bits) {
7256 else => unreachable,
7257 1...31 => |bits| {
7258 try isel.emit(.clz(res_ra.w(), res_ra.w()));
7259 try isel.emit(.rbit(res_ra.w(), res_ra.w()));
7260 try isel.emit(.orr(res_ra.w(), src_ra.w(), .{ .immediate = .{
7261 .N = .word,
7262 .immr = @intCast(32 - bits),
7263 .imms = @intCast(32 - bits - 1),
7264 } }));
7265 },
7266 32 => {
7267 try isel.emit(.clz(res_ra.w(), res_ra.w()));
7268 try isel.emit(.rbit(res_ra.w(), src_ra.w()));
7269 },
7270 33...63 => |bits| {
7271 try isel.emit(.clz(res_ra.x(), res_ra.x()));
7272 try isel.emit(.rbit(res_ra.x(), res_ra.x()));
7273 try isel.emit(.orr(res_ra.x(), src_ra.x(), .{ .immediate = .{
7274 .N = .doubleword,
7275 .immr = @intCast(64 - bits),
7276 .imms = @intCast(64 - bits - 1),
7277 } }));
7278 },
7279 64 => {
7280 try isel.emit(.clz(res_ra.x(), res_ra.x()));
7281 try isel.emit(.rbit(res_ra.x(), src_ra.x()));
7282 },
7283 }
7284}
7285
7286fn storeReg(
7287 isel: *Select,
7288 ra: Register.Alias,
7289 size: u64,
7290 base_ra: Register.Alias,
7291 offset: i65,
7292) !void {
7293 switch (size) {
7294 0 => unreachable,
7295 1 => {
7296 if (std.math.cast(u12, offset)) |unsigned_offset| return isel.emit(if (ra.isVector()) .str(
7297 ra.b(),
7298 .{ .unsigned_offset = .{
7299 .base = base_ra.x(),
7300 .offset = unsigned_offset,
7301 } },
7302 ) else .strb(
7303 ra.w(),
7304 .{ .unsigned_offset = .{
7305 .base = base_ra.x(),
7306 .offset = unsigned_offset,
7307 } },
7308 ));
7309 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(if (ra.isVector())
7310 .stur(ra.b(), base_ra.x(), signed_offset)
7311 else
7312 .sturb(ra.w(), base_ra.x(), signed_offset));
7313 },
7314 2 => {
7315 if (std.math.cast(u13, offset)) |unsigned_offset| if (unsigned_offset % 2 == 0)
7316 return isel.emit(if (ra.isVector()) .str(
7317 ra.h(),
7318 .{ .unsigned_offset = .{
7319 .base = base_ra.x(),
7320 .offset = unsigned_offset,
7321 } },
7322 ) else .strh(
7323 ra.w(),
7324 .{ .unsigned_offset = .{
7325 .base = base_ra.x(),
7326 .offset = unsigned_offset,
7327 } },
7328 ));
7329 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(if (ra.isVector())
7330 .stur(ra.h(), base_ra.x(), signed_offset)
7331 else
7332 .sturh(ra.w(), base_ra.x(), signed_offset));
7333 },
7334 3 => {
7335 const hi8_ra = try isel.allocIntReg();
7336 defer isel.freeReg(hi8_ra);
7337 try isel.storeReg(hi8_ra, 1, base_ra, offset + 2);
7338 try isel.storeReg(ra, 2, base_ra, offset);
7339 return isel.emit(.ubfm(hi8_ra.w(), ra.w(), .{
7340 .N = .word,
7341 .immr = 16,
7342 .imms = 16 + 8 - 1,
7343 }));
7344 },
7345 4 => {
7346 if (std.math.cast(u14, offset)) |unsigned_offset| if (unsigned_offset % 4 == 0) return isel.emit(.str(
7347 if (ra.isVector()) ra.s() else ra.w(),
7348 .{ .unsigned_offset = .{
7349 .base = base_ra.x(),
7350 .offset = unsigned_offset,
7351 } },
7352 ));
7353 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(.stur(
7354 if (ra.isVector()) ra.s() else ra.w(),
7355 base_ra.x(),
7356 signed_offset,
7357 ));
7358 },
7359 5 => {
7360 const hi8_ra = try isel.allocIntReg();
7361 defer isel.freeReg(hi8_ra);
7362 try isel.storeReg(hi8_ra, 1, base_ra, offset + 4);
7363 try isel.storeReg(ra, 4, base_ra, offset);
7364 return isel.emit(.ubfm(hi8_ra.x(), ra.x(), .{
7365 .N = .doubleword,
7366 .immr = 32,
7367 .imms = 32 + 8 - 1,
7368 }));
7369 },
7370 6 => {
7371 const hi16_ra = try isel.allocIntReg();
7372 defer isel.freeReg(hi16_ra);
7373 try isel.storeReg(hi16_ra, 2, base_ra, offset + 4);
7374 try isel.storeReg(ra, 4, base_ra, offset);
7375 return isel.emit(.ubfm(hi16_ra.x(), ra.x(), .{
7376 .N = .doubleword,
7377 .immr = 32,
7378 .imms = 32 + 16 - 1,
7379 }));
7380 },
7381 7 => {
7382 const hi16_ra = try isel.allocIntReg();
7383 defer isel.freeReg(hi16_ra);
7384 const hi8_ra = try isel.allocIntReg();
7385 defer isel.freeReg(hi8_ra);
7386 try isel.storeReg(hi8_ra, 1, base_ra, offset + 6);
7387 try isel.storeReg(hi16_ra, 2, base_ra, offset + 4);
7388 try isel.storeReg(ra, 4, base_ra, offset);
7389 try isel.emit(.ubfm(hi8_ra.x(), ra.x(), .{
7390 .N = .doubleword,
7391 .immr = 32 + 16,
7392 .imms = 32 + 16 + 8 - 1,
7393 }));
7394 return isel.emit(.ubfm(hi16_ra.x(), ra.x(), .{
7395 .N = .doubleword,
7396 .immr = 32,
7397 .imms = 32 + 16 - 1,
7398 }));
7399 },
7400 8 => {
7401 if (std.math.cast(u15, offset)) |unsigned_offset| if (unsigned_offset % 8 == 0) return isel.emit(.str(
7402 if (ra.isVector()) ra.d() else ra.x(),
7403 .{ .unsigned_offset = .{
7404 .base = base_ra.x(),
7405 .offset = unsigned_offset,
7406 } },
7407 ));
7408 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(.stur(
7409 if (ra.isVector()) ra.d() else ra.x(),
7410 base_ra.x(),
7411 signed_offset,
7412 ));
7413 },
7414 16 => {
7415 if (std.math.cast(u16, offset)) |unsigned_offset| if (unsigned_offset % 16 == 0) return isel.emit(.str(
7416 ra.q(),
7417 .{ .unsigned_offset = .{
7418 .base = base_ra.x(),
7419 .offset = unsigned_offset,
7420 } },
7421 ));
7422 if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(.stur(ra.q(), base_ra.x(), signed_offset));
7423 },
7424 else => return isel.fail("bad store size: {d}", .{size}),
7425 }
7426 const ptr_ra = try isel.allocIntReg();
7427 defer isel.freeReg(ptr_ra);
7428 try isel.storeReg(ra, size, ptr_ra, 0);
7429 if (std.math.cast(u24, offset)) |pos_offset| {
7430 const lo12: u12 = @truncate(pos_offset >> 0);
7431 const hi12: u12 = @intCast(pos_offset >> 12);
7432 if (hi12 > 0) try isel.emit(.add(
7433 ptr_ra.x(),
7434 if (lo12 > 0) ptr_ra.x() else base_ra.x(),
7435 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
7436 ));
7437 if (lo12 > 0 or hi12 == 0) try isel.emit(.add(ptr_ra.x(), base_ra.x(), .{ .immediate = lo12 }));
7438 } else if (std.math.cast(u24, -offset)) |neg_offset| {
7439 const lo12: u12 = @truncate(neg_offset >> 0);
7440 const hi12: u12 = @intCast(neg_offset >> 12);
7441 if (hi12 > 0) try isel.emit(.sub(
7442 ptr_ra.x(),
7443 if (lo12 > 0) ptr_ra.x() else base_ra.x(),
7444 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
7445 ));
7446 if (lo12 > 0 or hi12 == 0) try isel.emit(.sub(ptr_ra.x(), base_ra.x(), .{ .immediate = lo12 }));
7447 } else {
7448 try isel.emit(.add(ptr_ra.x(), base_ra.x(), .{ .register = ptr_ra.x() }));
7449 try isel.movImmediate(ptr_ra.x(), @truncate(@as(u65, @bitCast(offset))));
7450 }
7451}
7452
7453const DomInt = u8;
7454
7455pub const Value = struct {
7456 refs: u32,
7457 flags: Flags,
7458 offset_from_parent: u64,
7459 parent_payload: Parent.Payload,
7460 location_payload: Location.Payload,
7461 parts: Value.Index,
7462
7463 /// Must be at least 16 to compute call abi.
7464 /// Must be at least 16, the largest hardware alignment.
7465 pub const max_parts = 16;
7466 pub const PartsLen = std.math.IntFittingRange(0, Value.max_parts);
7467
7468 comptime {
7469 if (!std.debug.runtime_safety) assert(@sizeOf(Value) == 32);
7470 }
7471
7472 pub const Flags = packed struct(u32) {
7473 alignment: InternPool.Alignment,
7474 parent_tag: Parent.Tag,
7475 location_tag: Location.Tag,
7476 parts_len_minus_one: std.math.IntFittingRange(0, Value.max_parts - 1),
7477 unused: u18 = 0,
7478 };
7479
7480 pub const Parent = union(enum(u3)) {
7481 unallocated: void,
7482 stack_slot: Indirect,
7483 address: Value.Index,
7484 value: Value.Index,
7485 constant: Constant,
7486
7487 pub const Tag = @typeInfo(Parent).@"union".tag_type.?;
7488 pub const Payload = @Type(.{ .@"union" = .{
7489 .layout = .auto,
7490 .tag_type = null,
7491 .fields = @typeInfo(Parent).@"union".fields,
7492 .decls = &.{},
7493 } });
7494 };
7495
7496 pub const Location = union(enum(u1)) {
7497 large: struct {
7498 size: u64,
7499 },
7500 small: struct {
7501 size: u5,
7502 signedness: std.builtin.Signedness,
7503 is_vector: bool,
7504 hint: Register.Alias,
7505 register: Register.Alias,
7506 },
7507
7508 pub const Tag = @typeInfo(Location).@"union".tag_type.?;
7509 pub const Payload = @Type(.{ .@"union" = .{
7510 .layout = .auto,
7511 .tag_type = null,
7512 .fields = @typeInfo(Location).@"union".fields,
7513 .decls = &.{},
7514 } });
7515 };
7516
7517 pub const Indirect = packed struct(u32) {
7518 base: Register.Alias,
7519 offset: i25,
7520
7521 pub fn withOffset(ind: Indirect, offset: i25) Indirect {
7522 return .{
7523 .base = ind.base,
7524 .offset = ind.offset + offset,
7525 };
7526 }
7527 };
7528
7529 pub const Index = enum(u32) {
7530 allocating = std.math.maxInt(u32) - 1,
7531 free = std.math.maxInt(u32) - 0,
7532 _,
7533
7534 fn get(vi: Value.Index, isel: *Select) *Value {
7535 return &isel.values.items[@intFromEnum(vi)];
7536 }
7537
7538 fn setAlignment(vi: Value.Index, isel: *Select, new_alignment: InternPool.Alignment) void {
7539 vi.get(isel).flags.alignment = new_alignment;
7540 }
7541
7542 pub fn alignment(vi: Value.Index, isel: *Select) InternPool.Alignment {
7543 return vi.get(isel).flags.alignment;
7544 }
7545
7546 pub fn setParent(vi: Value.Index, isel: *Select, new_parent: Parent) void {
7547 const value = vi.get(isel);
7548 assert(value.flags.parent_tag == .unallocated);
7549 value.flags.parent_tag = new_parent;
7550 value.parent_payload = switch (new_parent) {
7551 .unallocated => unreachable,
7552 inline else => |payload, tag| @unionInit(Parent.Payload, @tagName(tag), payload),
7553 };
7554 if (value.refs > 0) switch (new_parent) {
7555 .unallocated => unreachable,
7556 .stack_slot, .constant => {},
7557 .address, .value => |parent_vi| _ = parent_vi.ref(isel),
7558 };
7559 }
7560
7561 pub fn parent(vi: Value.Index, isel: *Select) Parent {
7562 const value = vi.get(isel);
7563 return switch (value.flags.parent_tag) {
7564 inline else => |tag| @unionInit(
7565 Parent,
7566 @tagName(tag),
7567 @field(value.parent_payload, @tagName(tag)),
7568 ),
7569 };
7570 }
7571
7572 pub fn valueParent(initial_vi: Value.Index, isel: *Select) struct { u64, Value.Index } {
7573 var offset: u64 = 0;
7574 var vi = initial_vi;
7575 parent: switch (vi.parent(isel)) {
7576 else => return .{ offset, vi },
7577 .value => |parent_vi| {
7578 offset += vi.position(isel)[0];
7579 vi = parent_vi;
7580 continue :parent parent_vi.parent(isel);
7581 },
7582 }
7583 }
7584
7585 pub fn location(vi: Value.Index, isel: *Select) Location {
7586 const value = vi.get(isel);
7587 return switch (value.flags.location_tag) {
7588 inline else => |tag| @unionInit(
7589 Location,
7590 @tagName(tag),
7591 @field(value.location_payload, @tagName(tag)),
7592 ),
7593 };
7594 }
7595
7596 pub fn position(vi: Value.Index, isel: *Select) struct { u64, u64 } {
7597 return .{ vi.get(isel).offset_from_parent, vi.size(isel) };
7598 }
7599
7600 pub fn size(vi: Value.Index, isel: *Select) u64 {
7601 return switch (vi.location(isel)) {
7602 inline else => |loc| loc.size,
7603 };
7604 }
7605
7606 fn setHint(vi: Value.Index, isel: *Select, new_hint: Register.Alias) void {
7607 vi.get(isel).location_payload.small.hint = new_hint;
7608 }
7609
7610 pub fn hint(vi: Value.Index, isel: *Select) ?Register.Alias {
7611 return switch (vi.location(isel)) {
7612 .large => null,
7613 .small => |loc| switch (loc.hint) {
7614 .zr => null,
7615 else => |hint_reg| hint_reg,
7616 },
7617 };
7618 }
7619
7620 fn setSignedness(vi: Value.Index, isel: *Select, new_signedness: std.builtin.Signedness) void {
7621 const value = vi.get(isel);
7622 assert(value.location_payload.small.size <= 2);
7623 value.location_payload.small.signedness = new_signedness;
7624 }
7625
7626 pub fn signedness(vi: Value.Index, isel: *Select) std.builtin.Signedness {
7627 const value = vi.get(isel);
7628 return switch (value.flags.location_tag) {
7629 .large => .unsigned,
7630 .small => value.location_payload.small.signedness,
7631 };
7632 }
7633
7634 fn setIsVector(vi: Value.Index, isel: *Select) void {
7635 const is_vector = &vi.get(isel).location_payload.small.is_vector;
7636 assert(!is_vector.*);
7637 is_vector.* = true;
7638 }
7639
7640 pub fn isVector(vi: Value.Index, isel: *Select) bool {
7641 const value = vi.get(isel);
7642 return switch (value.flags.location_tag) {
7643 .large => false,
7644 .small => value.location_payload.small.is_vector,
7645 };
7646 }
7647
7648 pub fn register(vi: Value.Index, isel: *Select) ?Register.Alias {
7649 return switch (vi.location(isel)) {
7650 .large => null,
7651 .small => |loc| switch (loc.register) {
7652 .zr => null,
7653 else => |reg| reg,
7654 },
7655 };
7656 }
7657
7658 pub fn isUsed(vi: Value.Index, isel: *Select) bool {
7659 return vi.valueParent(isel)[1].parent(isel) != .unallocated or vi.hasRegisterRecursive(isel);
7660 }
7661
7662 fn hasRegisterRecursive(vi: Value.Index, isel: *Select) bool {
7663 if (vi.register(isel)) |_| return true;
7664 var part_it = vi.parts(isel);
7665 if (part_it.only() == null) while (part_it.next()) |part_vi| if (part_vi.hasRegisterRecursive(isel)) return true;
7666 return false;
7667 }
7668
7669 fn setParts(vi: Value.Index, isel: *Select, parts_len: Value.PartsLen) void {
7670 assert(parts_len > 1);
7671 const value = vi.get(isel);
7672 assert(value.flags.parts_len_minus_one == 0);
7673 value.parts = @enumFromInt(isel.values.items.len);
7674 value.flags.parts_len_minus_one = @intCast(parts_len - 1);
7675 }
7676
7677 fn addPart(vi: Value.Index, isel: *Select, part_offset: u64, part_size: u64) Value.Index {
7678 const part_vi = isel.initValueAdvanced(vi.alignment(isel), part_offset, part_size);
7679 tracking_log.debug("${d} <- ${d}[{d}]", .{
7680 @intFromEnum(part_vi),
7681 @intFromEnum(vi),
7682 part_offset,
7683 });
7684 part_vi.setParent(isel, .{ .value = vi });
7685 return part_vi;
7686 }
7687
7688 pub fn parts(vi: Value.Index, isel: *Select) Value.PartIterator {
7689 const value = vi.get(isel);
7690 return switch (value.flags.parts_len_minus_one) {
7691 0 => .initOne(vi),
7692 else => |parts_len_minus_one| .{
7693 .vi = value.parts,
7694 .remaining = @as(Value.PartsLen, parts_len_minus_one) + 1,
7695 },
7696 };
7697 }
7698
7699 fn containingParts(vi: Value.Index, isel: *Select, part_offset: u64, part_size: u64) Value.PartIterator {
7700 const start_vi = vi.partAtOffset(isel, part_offset);
7701 const start_offset, const start_size = start_vi.position(isel);
7702 if (part_offset >= start_offset and part_size <= start_size) return .initOne(start_vi);
7703 const end_vi = vi.partAtOffset(isel, part_size - 1 + part_offset);
7704 return .{
7705 .vi = start_vi,
7706 .remaining = @intCast(@intFromEnum(end_vi) - @intFromEnum(start_vi) + 1),
7707 };
7708 }
7709 comptime {
7710 _ = containingParts;
7711 }
7712
7713 fn partAtOffset(vi: Value.Index, isel: *Select, offset: u64) Value.Index {
7714 const SearchPartIndex = std.math.IntFittingRange(0, Value.max_parts * 2 - 1);
7715 const value = vi.get(isel);
7716 var last: SearchPartIndex = value.flags.parts_len_minus_one;
7717 if (last == 0) return vi;
7718 var first: SearchPartIndex = 0;
7719 last += 1;
7720 while (true) {
7721 const mid = (first + last) / 2;
7722 const mid_vi: Value.Index = @enumFromInt(@intFromEnum(value.parts) + mid);
7723 if (mid == first) return mid_vi;
7724 if (offset < mid_vi.get(isel).offset_from_parent) last = mid else first = mid;
7725 }
7726 }
7727
7728 fn field(
7729 vi: Value.Index,
7730 ty: ZigType,
7731 field_offset: u64,
7732 field_size: u64,
7733 ) Value.FieldPartIterator {
7734 assert(field_size > 0);
7735 return .{
7736 .vi = vi,
7737 .ty = ty,
7738 .field_offset = field_offset,
7739 .field_size = field_size,
7740 .next_offset = 0,
7741 };
7742 }
7743
7744 fn ref(initial_vi: Value.Index, isel: *Select) Value.Index {
7745 var vi = initial_vi;
7746 while (true) {
7747 const refs = &vi.get(isel).refs;
7748 refs.* += 1;
7749 if (refs.* > 1) return initial_vi;
7750 switch (vi.parent(isel)) {
7751 .unallocated, .stack_slot, .constant => {},
7752 .address, .value => |parent_vi| {
7753 vi = parent_vi;
7754 continue;
7755 },
7756 }
7757 return initial_vi;
7758 }
7759 }
7760
7761 pub fn deref(initial_vi: Value.Index, isel: *Select) void {
7762 var vi = initial_vi;
7763 while (true) {
7764 const refs = &vi.get(isel).refs;
7765 refs.* -= 1;
7766 if (refs.* > 0) return;
7767 switch (vi.parent(isel)) {
7768 .unallocated, .constant => {},
7769 .stack_slot => {
7770 // reuse stack slot
7771 },
7772 .address, .value => |parent_vi| {
7773 vi = parent_vi;
7774 continue;
7775 },
7776 }
7777 return;
7778 }
7779 }
7780
7781 fn move(dst_vi: Value.Index, isel: *Select, src_ref: Air.Inst.Ref) !void {
7782 try dst_vi.copy(
7783 isel,
7784 isel.air.typeOf(src_ref, &isel.pt.zcu.intern_pool),
7785 try isel.use(src_ref),
7786 );
7787 }
7788
7789 fn copy(dst_vi: Value.Index, isel: *Select, ty: ZigType, src_vi: Value.Index) !void {
7790 try dst_vi.copyAdvanced(isel, src_vi, .{
7791 .ty = ty,
7792 .dst_vi = dst_vi,
7793 .dst_offset = 0,
7794 .src_vi = src_vi,
7795 .src_offset = 0,
7796 });
7797 }
7798
7799 fn copyAdvanced(dst_vi: Value.Index, isel: *Select, src_vi: Value.Index, root: struct {
7800 ty: ZigType,
7801 dst_vi: Value.Index,
7802 dst_offset: u64,
7803 src_vi: Value.Index,
7804 src_offset: u64,
7805 }) !void {
7806 if (dst_vi == src_vi) return;
7807 var dst_part_it = dst_vi.parts(isel);
7808 if (dst_part_it.only()) |dst_part_vi| {
7809 var src_part_it = src_vi.parts(isel);
7810 if (src_part_it.only()) |src_part_vi| {
7811 try src_part_vi.liveOut(isel, try dst_part_vi.defReg(isel) orelse return);
7812 } else while (src_part_it.next()) |src_part_vi| {
7813 const src_part_offset, const src_part_size = src_part_vi.position(isel);
7814 var dst_field_it = root.dst_vi.field(root.ty, root.dst_offset + src_part_offset, src_part_size);
7815 const dst_field_vi = try dst_field_it.only(isel);
7816 try dst_field_vi.?.copyAdvanced(isel, src_part_vi, .{
7817 .ty = root.ty,
7818 .dst_vi = root.dst_vi,
7819 .dst_offset = root.dst_offset + src_part_offset,
7820 .src_vi = root.src_vi,
7821 .src_offset = root.src_offset + src_part_offset,
7822 });
7823 }
7824 } else while (dst_part_it.next()) |dst_part_vi| {
7825 const dst_part_offset, const dst_part_size = dst_part_vi.position(isel);
7826 var src_field_it = root.src_vi.field(root.ty, root.src_offset + dst_part_offset, dst_part_size);
7827 const src_part_vi = try src_field_it.only(isel);
7828 try dst_part_vi.copyAdvanced(isel, src_part_vi.?, .{
7829 .ty = root.ty,
7830 .dst_vi = root.dst_vi,
7831 .dst_offset = root.dst_offset + dst_part_offset,
7832 .src_vi = root.src_vi,
7833 .src_offset = root.src_offset + dst_part_offset,
7834 });
7835 }
7836 }
7837
7838 fn addOrSubtract(
7839 res_vi: Value.Index,
7840 isel: *Select,
7841 ty: ZigType,
7842 lhs_vi: Value.Index,
7843 op: codegen.aarch64.encoding.Instruction.AddSubtractOp,
7844 rhs_vi: Value.Index,
7845 opts: struct {
7846 wrap: bool,
7847 overflow_ra: Register.Alias = .zr,
7848 },
7849 ) !void {
7850 assert(opts.wrap or opts.overflow_ra == .zr);
7851 const zcu = isel.pt.zcu;
7852 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(op), isel.fmtType(ty) });
7853 const int_info = ty.intInfo(zcu);
7854 if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(op), isel.fmtType(ty) });
7855 var part_offset = res_vi.size(isel);
7856 var need_wrap = opts.wrap;
7857 var need_carry = opts.overflow_ra != .zr;
7858 while (part_offset > 0) : (need_wrap = false) {
7859 const part_size = @min(part_offset, 8);
7860 part_offset -= part_size;
7861 var wrapped_res_part_it = res_vi.field(ty, part_offset, part_size);
7862 const wrapped_res_part_vi = try wrapped_res_part_it.only(isel);
7863 const wrapped_res_part_ra = try wrapped_res_part_vi.?.defReg(isel) orelse if (need_carry) .zr else continue;
7864 const unwrapped_res_part_ra = unwrapped_res_part_ra: {
7865 if (!need_wrap) break :unwrapped_res_part_ra wrapped_res_part_ra;
7866 if (int_info.bits % 32 == 0) {
7867 if (opts.overflow_ra != .zr) try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(switch (int_info.signedness) {
7868 .signed => .vs,
7869 .unsigned => switch (op) {
7870 .add => .cs,
7871 .sub => .cc,
7872 },
7873 })));
7874 break :unwrapped_res_part_ra wrapped_res_part_ra;
7875 }
7876 const wrapped_part_ra, const unwrapped_part_ra = if (opts.overflow_ra != .zr) part_ra: {
7877 switch (op) {
7878 .add => {},
7879 .sub => switch (int_info.signedness) {
7880 .signed => {},
7881 .unsigned => {
7882 try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.cc)));
7883 break :part_ra .{ wrapped_res_part_ra, wrapped_res_part_ra };
7884 },
7885 },
7886 }
7887 try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.ne)));
7888 const wrapped_part_ra = switch (wrapped_res_part_ra) {
7889 else => |res_part_ra| res_part_ra,
7890 .zr => try isel.allocIntReg(),
7891 };
7892 errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);
7893 const unwrapped_part_ra = unwrapped_part_ra: {
7894 const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) {
7895 else => |res_part_ra| isel.lockReg(res_part_ra),
7896 .zr => .empty,
7897 };
7898 defer wrapped_res_part_lock.unlock(isel);
7899 break :unwrapped_part_ra try isel.allocIntReg();
7900 };
7901 errdefer isel.freeReg(unwrapped_part_ra);
7902 switch (part_size) {
7903 else => unreachable,
7904 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })),
7905 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })),
7906 }
7907 break :part_ra .{ wrapped_part_ra, unwrapped_part_ra };
7908 } else .{ wrapped_res_part_ra, wrapped_res_part_ra };
7909 defer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);
7910 errdefer if (unwrapped_part_ra != wrapped_res_part_ra) isel.freeReg(unwrapped_part_ra);
7911 if (wrapped_part_ra != .zr) try isel.emit(switch (part_size) {
7912 else => unreachable,
7913 1...4 => switch (int_info.signedness) {
7914 .signed => .sbfm(wrapped_part_ra.w(), unwrapped_part_ra.w(), .{
7915 .N = .word,
7916 .immr = 0,
7917 .imms = @truncate(int_info.bits - 1),
7918 }),
7919 .unsigned => .ubfm(wrapped_part_ra.w(), unwrapped_part_ra.w(), .{
7920 .N = .word,
7921 .immr = 0,
7922 .imms = @truncate(int_info.bits - 1),
7923 }),
7924 },
7925 5...8 => switch (int_info.signedness) {
7926 .signed => .sbfm(wrapped_part_ra.x(), unwrapped_part_ra.x(), .{
7927 .N = .doubleword,
7928 .immr = 0,
7929 .imms = @truncate(int_info.bits - 1),
7930 }),
7931 .unsigned => .ubfm(wrapped_part_ra.x(), unwrapped_part_ra.x(), .{
7932 .N = .doubleword,
7933 .immr = 0,
7934 .imms = @truncate(int_info.bits - 1),
7935 }),
7936 },
7937 });
7938 break :unwrapped_res_part_ra unwrapped_part_ra;
7939 };
7940 defer if (unwrapped_res_part_ra != wrapped_res_part_ra) isel.freeReg(unwrapped_res_part_ra);
7941 var lhs_part_it = lhs_vi.field(ty, part_offset, part_size);
7942 const lhs_part_vi = try lhs_part_it.only(isel);
7943 const lhs_part_mat = try lhs_part_vi.?.matReg(isel);
7944 var rhs_part_it = rhs_vi.field(ty, part_offset, part_size);
7945 const rhs_part_vi = try rhs_part_it.only(isel);
7946 const rhs_part_mat = try rhs_part_vi.?.matReg(isel);
7947 try isel.emit(switch (part_size) {
7948 else => unreachable,
7949 1...4 => switch (op) {
7950 .add => switch (part_offset) {
7951 0 => switch (need_carry) {
7952 false => .add(unwrapped_res_part_ra.w(), lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }),
7953 true => .adds(unwrapped_res_part_ra.w(), lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }),
7954 },
7955 else => switch (need_carry) {
7956 false => .adc(unwrapped_res_part_ra.w(), lhs_part_mat.ra.w(), rhs_part_mat.ra.w()),
7957 true => .adcs(unwrapped_res_part_ra.w(), lhs_part_mat.ra.w(), rhs_part_mat.ra.w()),
7958 },
7959 },
7960 .sub => switch (part_offset) {
7961 0 => switch (need_carry) {
7962 false => .sub(unwrapped_res_part_ra.w(), lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }),
7963 true => .subs(unwrapped_res_part_ra.w(), lhs_part_mat.ra.w(), .{ .register = rhs_part_mat.ra.w() }),
7964 },
7965 else => switch (need_carry) {
7966 false => .sbc(unwrapped_res_part_ra.w(), lhs_part_mat.ra.w(), rhs_part_mat.ra.w()),
7967 true => .sbcs(unwrapped_res_part_ra.w(), lhs_part_mat.ra.w(), rhs_part_mat.ra.w()),
7968 },
7969 },
7970 },
7971 5...8 => switch (op) {
7972 .add => switch (part_offset) {
7973 0 => switch (need_carry) {
7974 false => .add(unwrapped_res_part_ra.x(), lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }),
7975 true => .adds(unwrapped_res_part_ra.x(), lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }),
7976 },
7977 else => switch (need_carry) {
7978 false => .adc(unwrapped_res_part_ra.x(), lhs_part_mat.ra.x(), rhs_part_mat.ra.x()),
7979 true => .adcs(unwrapped_res_part_ra.x(), lhs_part_mat.ra.x(), rhs_part_mat.ra.x()),
7980 },
7981 },
7982 .sub => switch (part_offset) {
7983 0 => switch (need_carry) {
7984 false => .sub(unwrapped_res_part_ra.x(), lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }),
7985 true => .subs(unwrapped_res_part_ra.x(), lhs_part_mat.ra.x(), .{ .register = rhs_part_mat.ra.x() }),
7986 },
7987 else => switch (need_carry) {
7988 false => .sbc(unwrapped_res_part_ra.x(), lhs_part_mat.ra.x(), rhs_part_mat.ra.x()),
7989 true => .sbcs(unwrapped_res_part_ra.x(), lhs_part_mat.ra.x(), rhs_part_mat.ra.x()),
7990 },
7991 },
7992 },
7993 });
7994 try rhs_part_mat.finish(isel);
7995 try lhs_part_mat.finish(isel);
7996 need_carry = true;
7997 }
7998 }
7999
8000 const MemoryAccessOptions = struct {
8001 root_vi: Value.Index = .free,
8002 offset: u64 = 0,
8003 @"volatile": bool = false,
8004 split: bool = true,
8005 wrap: ?std.builtin.Type.Int = null,
8006 expected_live_registers: *const LiveRegisters = &.initFill(.free),
8007 };
8008
8009 fn load(
8010 vi: Value.Index,
8011 isel: *Select,
8012 root_ty: ZigType,
8013 base_ra: Register.Alias,
8014 opts: MemoryAccessOptions,
8015 ) !bool {
8016 const root_vi = switch (opts.root_vi) {
8017 _ => |root_vi| root_vi,
8018 .allocating => unreachable,
8019 .free => vi,
8020 };
8021 var part_it = vi.parts(isel);
8022 if (part_it.only()) |part_vi| only: {
8023 const part_size = part_vi.size(isel);
8024 const part_is_vector = part_vi.isVector(isel);
8025 if (part_size > @as(@TypeOf(part_size), if (part_is_vector) 16 else 8)) {
8026 if (!opts.split) return false;
8027 var subpart_it = root_vi.field(root_ty, opts.offset, part_size - 1);
8028 _ = try subpart_it.next(isel);
8029 part_it = vi.parts(isel);
8030 assert(part_it.only() == null);
8031 break :only;
8032 }
8033 const part_ra = if (try part_vi.defReg(isel)) |part_ra|
8034 part_ra
8035 else if (opts.@"volatile")
8036 .zr
8037 else
8038 return false;
8039 if (part_ra != .zr) {
8040 const live_vi = isel.live_registers.getPtr(part_ra);
8041 assert(live_vi.* == .free);
8042 live_vi.* = .allocating;
8043 }
8044 if (opts.wrap) |int_info| switch (int_info.bits) {
8045 else => unreachable,
8046 1...7, 9...15, 17...31 => |bits| try isel.emit(switch (int_info.signedness) {
8047 .signed => .sbfm(part_ra.w(), part_ra.w(), .{
8048 .N = .word,
8049 .immr = 0,
8050 .imms = @intCast(bits - 1),
8051 }),
8052 .unsigned => .ubfm(part_ra.w(), part_ra.w(), .{
8053 .N = .word,
8054 .immr = 0,
8055 .imms = @intCast(bits - 1),
8056 }),
8057 }),
8058 8, 16, 32 => {},
8059 33...63 => |bits| try isel.emit(switch (int_info.signedness) {
8060 .signed => .sbfm(part_ra.x(), part_ra.x(), .{
8061 .N = .doubleword,
8062 .immr = 0,
8063 .imms = @intCast(bits - 1),
8064 }),
8065 .unsigned => .ubfm(part_ra.x(), part_ra.x(), .{
8066 .N = .doubleword,
8067 .immr = 0,
8068 .imms = @intCast(bits - 1),
8069 }),
8070 }),
8071 64 => {},
8072 };
8073 try isel.emit(emit: switch (part_size) {
8074 else => return isel.fail("bad load size of {d}", .{part_size}),
8075 1 => if (part_is_vector) .ldr(part_ra.b(), .{ .unsigned_offset = .{
8076 .base = base_ra.x(),
8077 .offset = @intCast(opts.offset),
8078 } }) else switch (part_vi.signedness(isel)) {
8079 .signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
8080 .base = base_ra.x(),
8081 .offset = @intCast(opts.offset),
8082 } }),
8083 .unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
8084 .base = base_ra.x(),
8085 .offset = @intCast(opts.offset),
8086 } }),
8087 },
8088 2 => if (part_is_vector) .ldr(part_ra.h(), .{ .unsigned_offset = .{
8089 .base = base_ra.x(),
8090 .offset = @intCast(opts.offset),
8091 } }) else switch (part_vi.signedness(isel)) {
8092 .signed => .ldrsh(part_ra.w(), .{ .unsigned_offset = .{
8093 .base = base_ra.x(),
8094 .offset = @intCast(opts.offset),
8095 } }),
8096 .unsigned => .ldrh(part_ra.w(), .{ .unsigned_offset = .{
8097 .base = base_ra.x(),
8098 .offset = @intCast(opts.offset),
8099 } }),
8100 },
8101 3 => {
8102 const lo16_ra = try isel.allocIntReg();
8103 defer isel.freeReg(lo16_ra);
8104 try isel.emit(.orr(part_ra.w(), lo16_ra.w(), .{ .shifted_register = .{
8105 .register = part_ra.w(),
8106 .shift = .{ .lsl = 16 },
8107 } }));
8108 try isel.emit(switch (part_vi.signedness(isel)) {
8109 .signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
8110 .base = base_ra.x(),
8111 .offset = @intCast(opts.offset + 2),
8112 } }),
8113 .unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
8114 .base = base_ra.x(),
8115 .offset = @intCast(opts.offset + 2),
8116 } }),
8117 });
8118 break :emit .ldrh(lo16_ra.w(), .{ .unsigned_offset = .{
8119 .base = base_ra.x(),
8120 .offset = @intCast(opts.offset),
8121 } });
8122 },
8123 4 => .ldr(if (part_is_vector) part_ra.s() else part_ra.w(), .{ .unsigned_offset = .{
8124 .base = base_ra.x(),
8125 .offset = @intCast(opts.offset),
8126 } }),
8127 5 => {
8128 const lo32_ra = try isel.allocIntReg();
8129 defer isel.freeReg(lo32_ra);
8130 try isel.emit(.orr(part_ra.x(), lo32_ra.x(), .{ .shifted_register = .{
8131 .register = part_ra.x(),
8132 .shift = .{ .lsl = 32 },
8133 } }));
8134 try isel.emit(switch (part_vi.signedness(isel)) {
8135 .signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
8136 .base = base_ra.x(),
8137 .offset = @intCast(opts.offset + 4),
8138 } }),
8139 .unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
8140 .base = base_ra.x(),
8141 .offset = @intCast(opts.offset + 4),
8142 } }),
8143 });
8144 break :emit .ldr(lo32_ra.w(), .{ .unsigned_offset = .{
8145 .base = base_ra.x(),
8146 .offset = @intCast(opts.offset),
8147 } });
8148 },
8149 7 => {
8150 const lo32_ra = try isel.allocIntReg();
8151 defer isel.freeReg(lo32_ra);
8152 const lo48_ra = try isel.allocIntReg();
8153 defer isel.freeReg(lo48_ra);
8154 try isel.emit(.orr(part_ra.x(), lo48_ra.x(), .{ .shifted_register = .{
8155 .register = part_ra.x(),
8156 .shift = .{ .lsl = 32 + 16 },
8157 } }));
8158 try isel.emit(switch (part_vi.signedness(isel)) {
8159 .signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
8160 .base = base_ra.x(),
8161 .offset = @intCast(opts.offset + 4 + 2),
8162 } }),
8163 .unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
8164 .base = base_ra.x(),
8165 .offset = @intCast(opts.offset + 4 + 2),
8166 } }),
8167 });
8168 try isel.emit(.orr(lo48_ra.x(), lo32_ra.x(), .{ .shifted_register = .{
8169 .register = lo48_ra.x(),
8170 .shift = .{ .lsl = 32 },
8171 } }));
8172 try isel.emit(.ldrh(lo48_ra.w(), .{ .unsigned_offset = .{
8173 .base = base_ra.x(),
8174 .offset = @intCast(opts.offset + 4),
8175 } }));
8176 break :emit .ldr(lo32_ra.w(), .{ .unsigned_offset = .{
8177 .base = base_ra.x(),
8178 .offset = @intCast(opts.offset),
8179 } });
8180 },
8181 8 => .ldr(if (part_is_vector) part_ra.d() else part_ra.x(), .{ .unsigned_offset = .{
8182 .base = base_ra.x(),
8183 .offset = @intCast(opts.offset),
8184 } }),
8185 16 => .ldr(part_ra.q(), .{ .unsigned_offset = .{
8186 .base = base_ra.x(),
8187 .offset = @intCast(opts.offset),
8188 } }),
8189 });
8190 if (part_ra != .zr) {
8191 const live_vi = isel.live_registers.getPtr(part_ra);
8192 assert(live_vi.* == .allocating);
8193 switch (opts.expected_live_registers.get(part_ra)) {
8194 _ => {},
8195 .allocating => unreachable,
8196 .free => live_vi.* = .free,
8197 }
8198 }
8199 return true;
8200 }
8201 var used = false;
8202 while (part_it.next()) |part_vi| used |= try part_vi.load(isel, root_ty, base_ra, .{
8203 .root_vi = root_vi,
8204 .offset = opts.offset + part_vi.get(isel).offset_from_parent,
8205 .@"volatile" = opts.@"volatile",
8206 .split = opts.split,
8207 .wrap = switch (part_it.remaining) {
8208 else => null,
8209 0 => if (opts.wrap) |wrap| .{
8210 .signedness = wrap.signedness,
8211 .bits = @intCast(wrap.bits - 8 * part_vi.position(isel)[0]),
8212 } else null,
8213 },
8214 .expected_live_registers = opts.expected_live_registers,
8215 });
8216 return used;
8217 }
8218
8219 fn store(
8220 vi: Value.Index,
8221 isel: *Select,
8222 root_ty: ZigType,
8223 base_ra: Register.Alias,
8224 opts: MemoryAccessOptions,
8225 ) !void {
8226 const root_vi = switch (opts.root_vi) {
8227 _ => |root_vi| root_vi,
8228 .allocating => unreachable,
8229 .free => vi,
8230 };
8231 var part_it = vi.parts(isel);
8232 if (part_it.only()) |part_vi| only: {
8233 const part_size = part_vi.size(isel);
8234 const part_is_vector = part_vi.isVector(isel);
8235 if (part_size > @as(@TypeOf(part_size), if (part_is_vector) 16 else 8)) {
8236 if (!opts.split) return;
8237 var subpart_it = root_vi.field(root_ty, opts.offset, part_size - 1);
8238 _ = try subpart_it.next(isel);
8239 part_it = vi.parts(isel);
8240 assert(part_it.only() == null);
8241 break :only;
8242 }
8243 const part_mat = try part_vi.matReg(isel);
8244 try isel.storeReg(part_mat.ra, part_size, base_ra, opts.offset);
8245 return part_mat.finish(isel);
8246 }
8247 while (part_it.next()) |part_vi| try part_vi.store(isel, root_ty, base_ra, .{
8248 .root_vi = root_vi,
8249 .offset = opts.offset + part_vi.get(isel).offset_from_parent,
8250 .@"volatile" = opts.@"volatile",
8251 .split = opts.split,
8252 .wrap = switch (part_it.remaining) {
8253 else => null,
8254 0 => if (opts.wrap) |wrap| .{
8255 .signedness = wrap.signedness,
8256 .bits = @intCast(wrap.bits - 8 * part_vi.position(isel)[0]),
8257 } else null,
8258 },
8259 .expected_live_registers = opts.expected_live_registers,
8260 });
8261 }
8262
8263 fn mat(vi: Value.Index, isel: *Select) !void {
8264 if (false) {
8265 var part_it: Value.PartIterator = if (vi.size(isel) > 8) vi.parts(isel) else .initOne(vi);
8266 if (part_it.only()) |part_vi| only: {
8267 const mat_ra = mat_ra: {
8268 if (part_vi.register(isel)) |mat_ra| {
8269 part_vi.get(isel).location_payload.small.register = .zr;
8270 const live_vi = isel.live_registers.getPtr(mat_ra);
8271 assert(live_vi.* == part_vi);
8272 live_vi.* = .allocating;
8273 break :mat_ra mat_ra;
8274 }
8275 if (part_vi.hint(isel)) |hint_ra| {
8276 const live_vi = isel.live_registers.getPtr(hint_ra);
8277 if (live_vi.* == .free) {
8278 live_vi.* = .allocating;
8279 isel.saved_registers.insert(hint_ra);
8280 break :mat_ra hint_ra;
8281 }
8282 }
8283 const part_size = part_vi.size(isel);
8284 const part_is_vector = part_vi.isVector(isel);
8285 if (part_size <= @as(@TypeOf(part_size), if (part_is_vector) 16 else 8))
8286 switch (if (part_is_vector) isel.tryAllocVecReg() else isel.tryAllocIntReg()) {
8287 .allocated => |ra| break :mat_ra ra,
8288 .fill_candidate, .out_of_registers => {},
8289 };
8290 _, const parent_vi = vi.valueParent(isel);
8291 switch (parent_vi.parent(isel)) {
8292 .unallocated => parent_vi.setParent(isel, .{ .stack_slot = parent_vi.allocStackSlot(isel) }),
8293 else => {},
8294 }
8295 break :only;
8296 };
8297 assert(isel.live_registers.get(mat_ra) == .allocating);
8298 try Value.Materialize.finish(.{ .vi = part_vi, .ra = mat_ra }, isel);
8299 } else while (part_it.next()) |part_vi| try part_vi.mat(isel);
8300 } else {
8301 _, const parent_vi = vi.valueParent(isel);
8302 switch (parent_vi.parent(isel)) {
8303 .unallocated => parent_vi.setParent(isel, .{ .stack_slot = parent_vi.allocStackSlot(isel) }),
8304 else => {},
8305 }
8306 }
8307 }
8308
8309 fn matReg(vi: Value.Index, isel: *Select) !Value.Materialize {
8310 const mat_ra = mat_ra: {
8311 if (vi.register(isel)) |mat_ra| {
8312 vi.get(isel).location_payload.small.register = .zr;
8313 const live_vi = isel.live_registers.getPtr(mat_ra);
8314 assert(live_vi.* == vi);
8315 live_vi.* = .allocating;
8316 break :mat_ra mat_ra;
8317 }
8318 if (vi.hint(isel)) |hint_ra| {
8319 const live_vi = isel.live_registers.getPtr(hint_ra);
8320 if (live_vi.* == .free) {
8321 live_vi.* = .allocating;
8322 isel.saved_registers.insert(hint_ra);
8323 break :mat_ra hint_ra;
8324 }
8325 }
8326 break :mat_ra if (vi.isVector(isel)) try isel.allocVecReg() else try isel.allocIntReg();
8327 };
8328 assert(isel.live_registers.get(mat_ra) == .allocating);
8329 return .{ .vi = vi, .ra = mat_ra };
8330 }
8331
8332 fn defAddr(
8333 def_vi: Value.Index,
8334 isel: *Select,
8335 def_ty: ZigType,
8336 wrap: ?std.builtin.Type.Int,
8337 expected_live_registers: *const LiveRegisters,
8338 ) !?void {
8339 if (!def_vi.isUsed(isel)) return null;
8340 const offset_from_parent: i65, const parent_vi = def_vi.valueParent(isel);
8341 const stack_slot, const allocated = switch (parent_vi.parent(isel)) {
8342 .unallocated => .{ parent_vi.allocStackSlot(isel), true },
8343 .stack_slot => |stack_slot| .{ stack_slot, false },
8344 else => unreachable,
8345 };
8346 _ = try def_vi.load(isel, def_ty, stack_slot.base, .{
8347 .offset = @intCast(stack_slot.offset + offset_from_parent),
8348 .split = false,
8349 .wrap = wrap,
8350 .expected_live_registers = expected_live_registers,
8351 });
8352 if (allocated) parent_vi.setParent(isel, .{ .stack_slot = stack_slot });
8353 }
8354
8355 fn defReg(def_vi: Value.Index, isel: *Select) !?Register.Alias {
8356 var vi = def_vi;
8357 var offset: i65 = 0;
8358 var def_ra: ?Register.Alias = null;
8359 while (true) {
8360 if (vi.register(isel)) |ra| {
8361 vi.get(isel).location_payload.small.register = .zr;
8362 const live_vi = isel.live_registers.getPtr(ra);
8363 assert(live_vi.* == vi);
8364 if (def_ra == null and vi != def_vi) {
8365 var part_it = vi.parts(isel);
8366 assert(part_it.only() == null);
8367
8368 const first_part_vi = part_it.next().?;
8369 const first_part_value = first_part_vi.get(isel);
8370 assert(first_part_value.offset_from_parent == 0);
8371 first_part_value.location_payload.small.register = ra;
8372 live_vi.* = first_part_vi;
8373
8374 const vi_size = vi.size(isel);
8375 while (part_it.next()) |part_vi| {
8376 const part_offset, const part_size = part_vi.position(isel);
8377 const part_mat = try part_vi.matReg(isel);
8378 try isel.emit(if (part_vi.isVector(isel)) emit: {
8379 assert(part_offset == 0 and part_size == vi_size);
8380 break :emit size: switch (vi_size) {
8381 else => unreachable,
8382 2 => if (isel.target.cpu.has(.aarch64, .fullfp16))
8383 .fmov(ra.h(), .{ .register = part_mat.ra.h() })
8384 else
8385 continue :size 4,
8386 4 => .fmov(ra.s(), .{ .register = part_mat.ra.s() }),
8387 8 => .fmov(ra.d(), .{ .register = part_mat.ra.d() }),
8388 16 => .orr(ra.@"16b"(), part_mat.ra.@"16b"(), .{ .register = part_mat.ra.@"16b"() }),
8389 };
8390 } else switch (vi_size) {
8391 else => unreachable,
8392 1...4 => .bfm(ra.w(), part_mat.ra.w(), .{
8393 .N = .word,
8394 .immr = @as(u5, @truncate(32 - 8 * part_offset)),
8395 .imms = @intCast(8 * part_size - 1),
8396 }),
8397 5...8 => .bfm(ra.x(), part_mat.ra.x(), .{
8398 .N = .doubleword,
8399 .immr = @as(u6, @truncate(64 - 8 * part_offset)),
8400 .imms = @intCast(8 * part_size - 1),
8401 }),
8402 });
8403 try part_mat.finish(isel);
8404 }
8405 vi = def_vi;
8406 offset = 0;
8407 continue;
8408 }
8409 live_vi.* = .free;
8410 def_ra = ra;
8411 }
8412 offset += vi.get(isel).offset_from_parent;
8413 switch (vi.parent(isel)) {
8414 else => unreachable,
8415 .unallocated => return def_ra,
8416 .stack_slot => |stack_slot| {
8417 offset += stack_slot.offset;
8418 const def_is_vector = def_vi.isVector(isel);
8419 const ra = def_ra orelse if (def_is_vector) try isel.allocVecReg() else try isel.allocIntReg();
8420 defer if (def_ra == null) isel.freeReg(ra);
8421 try isel.storeReg(ra, def_vi.size(isel), stack_slot.base, offset);
8422 return ra;
8423 },
8424 .value => |parent_vi| vi = parent_vi,
8425 }
8426 }
8427 }
8428
8429 pub fn liveIn(
8430 vi: Value.Index,
8431 isel: *Select,
8432 src_ra: Register.Alias,
8433 expected_live_registers: *const LiveRegisters,
8434 ) !void {
8435 const src_live_vi = isel.live_registers.getPtr(src_ra);
8436 if (vi.register(isel)) |dst_ra| {
8437 const dst_live_vi = isel.live_registers.getPtr(dst_ra);
8438 assert(dst_live_vi.* == vi);
8439 if (dst_ra == src_ra) {
8440 src_live_vi.* = .allocating;
8441 return;
8442 }
8443 dst_live_vi.* = .allocating;
8444 if (try isel.fill(src_ra)) {
8445 assert(src_live_vi.* == .free);
8446 src_live_vi.* = .allocating;
8447 }
8448 assert(src_live_vi.* == .allocating);
8449 try isel.emit(switch (dst_ra.isVector()) {
8450 false => switch (src_ra.isVector()) {
8451 false => switch (vi.size(isel)) {
8452 else => unreachable,
8453 1...4 => .orr(dst_ra.w(), .wzr, .{ .register = src_ra.w() }),
8454 5...8 => .orr(dst_ra.x(), .xzr, .{ .register = src_ra.x() }),
8455 },
8456 true => switch (vi.size(isel)) {
8457 else => unreachable,
8458 2 => .fmov(dst_ra.w(), .{ .register = src_ra.h() }),
8459 4 => .fmov(dst_ra.w(), .{ .register = src_ra.s() }),
8460 8 => .fmov(dst_ra.x(), .{ .register = src_ra.d() }),
8461 },
8462 },
8463 true => switch (src_ra.isVector()) {
8464 false => switch (vi.size(isel)) {
8465 else => unreachable,
8466 2 => .fmov(dst_ra.h(), .{ .register = src_ra.w() }),
8467 4 => .fmov(dst_ra.s(), .{ .register = src_ra.w() }),
8468 8 => .fmov(dst_ra.d(), .{ .register = src_ra.x() }),
8469 },
8470 true => switch (vi.size(isel)) {
8471 else => unreachable,
8472 2 => .fmov(dst_ra.h(), .{ .register = src_ra.h() }),
8473 4 => .fmov(dst_ra.s(), .{ .register = src_ra.s() }),
8474 8 => .fmov(dst_ra.d(), .{ .register = src_ra.d() }),
8475 16 => .orr(dst_ra.@"16b"(), src_ra.@"16b"(), .{ .register = src_ra.@"16b"() }),
8476 },
8477 },
8478 });
8479 assert(dst_live_vi.* == .allocating);
8480 dst_live_vi.* = switch (expected_live_registers.get(dst_ra)) {
8481 _ => .allocating,
8482 .allocating => .allocating,
8483 .free => .free,
8484 };
8485 } else if (try isel.fill(src_ra)) {
8486 assert(src_live_vi.* == .free);
8487 src_live_vi.* = .allocating;
8488 }
8489 assert(src_live_vi.* == .allocating);
8490 vi.get(isel).location_payload.small.register = src_ra;
8491 }
8492
8493 pub fn defLiveIn(
8494 vi: Value.Index,
8495 isel: *Select,
8496 src_ra: Register.Alias,
8497 expected_live_registers: *const LiveRegisters,
8498 ) !void {
8499 try vi.liveIn(isel, src_ra, expected_live_registers);
8500 const offset_from_parent: i65, const parent_vi = vi.valueParent(isel);
8501 switch (parent_vi.parent(isel)) {
8502 .unallocated => {},
8503 .stack_slot => |stack_slot| {
8504 const offset = stack_slot.offset + offset_from_parent;
8505 try isel.emit(switch (vi.size(isel)) {
8506 else => unreachable,
8507 1 => if (src_ra.isVector()) .str(src_ra.b(), .{ .unsigned_offset = .{
8508 .base = stack_slot.base.x(),
8509 .offset = @intCast(offset),
8510 } }) else .strb(src_ra.w(), .{ .unsigned_offset = .{
8511 .base = stack_slot.base.x(),
8512 .offset = @intCast(offset),
8513 } }),
8514 2 => if (src_ra.isVector()) .str(src_ra.h(), .{ .unsigned_offset = .{
8515 .base = stack_slot.base.x(),
8516 .offset = @intCast(offset),
8517 } }) else .strh(src_ra.w(), .{ .unsigned_offset = .{
8518 .base = stack_slot.base.x(),
8519 .offset = @intCast(offset),
8520 } }),
8521 4 => .str(if (src_ra.isVector()) src_ra.s() else src_ra.w(), .{ .unsigned_offset = .{
8522 .base = stack_slot.base.x(),
8523 .offset = @intCast(offset),
8524 } }),
8525 8 => .str(if (src_ra.isVector()) src_ra.d() else src_ra.x(), .{ .unsigned_offset = .{
8526 .base = stack_slot.base.x(),
8527 .offset = @intCast(offset),
8528 } }),
8529 16 => .str(src_ra.q(), .{ .unsigned_offset = .{
8530 .base = stack_slot.base.x(),
8531 .offset = @intCast(offset),
8532 } }),
8533 });
8534 },
8535 else => unreachable,
8536 }
8537 try vi.spillReg(isel, src_ra, 0, expected_live_registers);
8538 }
8539
8540 fn spillReg(
8541 vi: Value.Index,
8542 isel: *Select,
8543 src_ra: Register.Alias,
8544 start_offset: u64,
8545 expected_live_registers: *const LiveRegisters,
8546 ) !void {
8547 assert(isel.live_registers.get(src_ra) == .allocating);
8548 var part_it = vi.parts(isel);
8549 if (part_it.only()) |part_vi| {
8550 const dst_ra = part_vi.register(isel) orelse return;
8551 if (dst_ra == src_ra) return;
8552 const part_size = part_vi.size(isel);
8553 const part_ra = if (part_vi.isVector(isel)) try isel.allocIntReg() else dst_ra;
8554 defer if (part_ra != dst_ra) isel.freeReg(part_ra);
8555 if (part_ra != dst_ra) try isel.emit(switch (part_size) {
8556 else => unreachable,
8557 2 => .fmov(dst_ra.h(), .{ .register = part_ra.w() }),
8558 4 => .fmov(dst_ra.s(), .{ .register = part_ra.w() }),
8559 8 => .fmov(dst_ra.d(), .{ .register = part_ra.x() }),
8560 });
8561 try isel.emit(switch (start_offset + part_size) {
8562 else => unreachable,
8563 1...4 => |end_offset| switch (part_vi.signedness(isel)) {
8564 .signed => .sbfm(part_ra.w(), src_ra.w(), .{
8565 .N = .word,
8566 .immr = @intCast(8 * start_offset),
8567 .imms = @intCast(8 * end_offset - 1),
8568 }),
8569 .unsigned => .ubfm(part_ra.w(), src_ra.w(), .{
8570 .N = .word,
8571 .immr = @intCast(8 * start_offset),
8572 .imms = @intCast(8 * end_offset - 1),
8573 }),
8574 },
8575 5...8 => |end_offset| switch (part_vi.signedness(isel)) {
8576 .signed => .sbfm(part_ra.x(), src_ra.x(), .{
8577 .N = .doubleword,
8578 .immr = @intCast(8 * start_offset),
8579 .imms = @intCast(8 * end_offset - 1),
8580 }),
8581 .unsigned => .ubfm(part_ra.x(), src_ra.x(), .{
8582 .N = .doubleword,
8583 .immr = @intCast(8 * start_offset),
8584 .imms = @intCast(8 * end_offset - 1),
8585 }),
8586 },
8587 });
8588 const value_ra = &part_vi.get(isel).location_payload.small.register;
8589 assert(value_ra.* == dst_ra);
8590 value_ra.* = .zr;
8591 const dst_live_vi = isel.live_registers.getPtr(dst_ra);
8592 assert(dst_live_vi.* == part_vi);
8593 dst_live_vi.* = switch (expected_live_registers.get(dst_ra)) {
8594 _ => .allocating,
8595 .allocating => unreachable,
8596 .free => .free,
8597 };
8598 } else while (part_it.next()) |part_vi| try part_vi.spillReg(
8599 isel,
8600 src_ra,
8601 start_offset + part_vi.get(isel).offset_from_parent,
8602 expected_live_registers,
8603 );
8604 }
8605
8606 fn liveOut(vi: Value.Index, isel: *Select, ra: Register.Alias) !void {
8607 assert(try isel.fill(ra));
8608 const live_vi = isel.live_registers.getPtr(ra);
8609 assert(live_vi.* == .free);
8610 live_vi.* = .allocating;
8611 try Value.Materialize.finish(.{ .vi = vi, .ra = ra }, isel);
8612 }
8613
8614 fn allocStackSlot(vi: Value.Index, isel: *Select) Value.Indirect {
8615 const offset = vi.alignment(isel).forward(isel.stack_size);
8616 isel.stack_size = @intCast(offset + vi.size(isel));
8617 tracking_log.debug("${d} -> [sp, #0x{x}]", .{ @intFromEnum(vi), @abs(offset) });
8618 return .{
8619 .base = .sp,
8620 .offset = @intCast(offset),
8621 };
8622 }
8623
8624 fn address(initial_vi: Value.Index, isel: *Select, initial_offset: u64, ptr_ra: Register.Alias) !void {
8625 var vi = initial_vi;
8626 var offset: i65 = vi.get(isel).offset_from_parent + initial_offset;
8627 parent: switch (vi.parent(isel)) {
8628 .unallocated => {
8629 const stack_slot = vi.allocStackSlot(isel);
8630 vi.setParent(isel, .{ .stack_slot = stack_slot });
8631 continue :parent .{ .stack_slot = stack_slot };
8632 },
8633 .stack_slot => |stack_slot| {
8634 offset += stack_slot.offset;
8635 const lo12: u12 = @truncate(@abs(offset) >> 0);
8636 const hi12: u12 = @intCast(@abs(offset) >> 12);
8637 if (hi12 > 0) try isel.emit(if (offset >= 0) .add(
8638 ptr_ra.x(),
8639 if (lo12 > 0) ptr_ra.x() else stack_slot.base.x(),
8640 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
8641 ) else .sub(
8642 ptr_ra.x(),
8643 if (lo12 > 0) ptr_ra.x() else stack_slot.base.x(),
8644 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
8645 ));
8646 if (lo12 > 0 or hi12 == 0) try isel.emit(if (offset >= 0) .add(
8647 ptr_ra.x(),
8648 stack_slot.base.x(),
8649 .{ .immediate = lo12 },
8650 ) else .sub(
8651 ptr_ra.x(),
8652 stack_slot.base.x(),
8653 .{ .immediate = lo12 },
8654 ));
8655 },
8656 .address => |address_vi| try address_vi.liveOut(isel, ptr_ra),
8657 .value => |parent_vi| {
8658 vi = parent_vi;
8659 offset += vi.get(isel).offset_from_parent;
8660 continue :parent vi.parent(isel);
8661 },
8662 .constant => |constant| {
8663 const pt = isel.pt;
8664 const zcu = pt.zcu;
8665 switch (true) {
8666 false => {
8667 try isel.uav_relocs.append(zcu.gpa, .{
8668 .uav = .{
8669 .val = constant.toIntern(),
8670 .orig_ty = (try pt.singleConstPtrType(constant.typeOf(zcu))).toIntern(),
8671 },
8672 .reloc = .{
8673 .label = @intCast(isel.instructions.items.len),
8674 .addend = @intCast(offset),
8675 },
8676 });
8677 try isel.emit(.adr(ptr_ra.x(), 0));
8678 },
8679 true => {
8680 try isel.uav_relocs.append(zcu.gpa, .{
8681 .uav = .{
8682 .val = constant.toIntern(),
8683 .orig_ty = (try pt.singleConstPtrType(constant.typeOf(zcu))).toIntern(),
8684 },
8685 .reloc = .{
8686 .label = @intCast(isel.instructions.items.len),
8687 .addend = @intCast(offset),
8688 },
8689 });
8690 try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 }));
8691 try isel.uav_relocs.append(zcu.gpa, .{
8692 .uav = .{
8693 .val = constant.toIntern(),
8694 .orig_ty = (try pt.singleConstPtrType(constant.typeOf(zcu))).toIntern(),
8695 },
8696 .reloc = .{
8697 .label = @intCast(isel.instructions.items.len),
8698 .addend = @intCast(offset),
8699 },
8700 });
8701 try isel.emit(.adrp(ptr_ra.x(), 0));
8702 },
8703 }
8704 },
8705 }
8706 }
8707 };
8708
8709 pub const PartIterator = struct {
8710 vi: Value.Index,
8711 remaining: Value.PartsLen,
8712
8713 fn initOne(vi: Value.Index) PartIterator {
8714 return .{ .vi = vi, .remaining = 1 };
8715 }
8716
8717 pub fn next(it: *PartIterator) ?Value.Index {
8718 if (it.remaining == 0) return null;
8719 it.remaining -= 1;
8720 defer it.vi = @enumFromInt(@intFromEnum(it.vi) + 1);
8721 return it.vi;
8722 }
8723
8724 pub fn only(it: PartIterator) ?Value.Index {
8725 return if (it.remaining == 1) it.vi else null;
8726 }
8727 };
8728
8729 const FieldPartIterator = struct {
8730 vi: Value.Index,
8731 ty: ZigType,
8732 field_offset: u64,
8733 field_size: u64,
8734 next_offset: u64,
8735
8736 fn next(it: *FieldPartIterator, isel: *Select) !?struct { offset: u64, vi: Value.Index } {
8737 const next_offset = it.next_offset;
8738 const next_part_size = it.field_size - next_offset;
8739 if (next_part_size == 0) return null;
8740 var next_part_offset = it.field_offset + next_offset;
8741
8742 const zcu = isel.pt.zcu;
8743 const ip = &zcu.intern_pool;
8744 var vi = it.vi;
8745 var ty = it.ty;
8746 var ty_size = vi.size(isel);
8747 assert(ty_size == ty.abiSize(zcu));
8748 var offset: u64 = 0;
8749 var size = ty_size;
8750 assert(next_part_offset + next_part_size <= size);
8751 while (next_part_offset > 0 or next_part_size < size) {
8752 const part_vi = vi.partAtOffset(isel, next_part_offset);
8753 if (part_vi != vi) {
8754 vi = part_vi;
8755 const part_offset, size = part_vi.position(isel);
8756 assert(part_offset <= next_part_offset and part_offset + size > next_part_offset);
8757 offset += part_offset;
8758 next_part_offset -= part_offset;
8759 continue;
8760 }
8761 try isel.values.ensureUnusedCapacity(zcu.gpa, Value.max_parts);
8762 type_key: switch (ip.indexToKey(ty.toIntern())) {
8763 else => return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)}),
8764 .int_type => |int_type| switch (int_type.bits) {
8765 0 => unreachable,
8766 1...64 => unreachable,
8767 65...256 => |bits| if (offset == 0 and size == ty_size) {
8768 const parts_len = std.math.divCeil(u16, bits, 64) catch unreachable;
8769 vi.setParts(isel, @intCast(parts_len));
8770 for (0..parts_len) |part_index| _ = vi.addPart(isel, 8 * part_index, 8);
8771 },
8772 else => return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)}),
8773 },
8774 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
8775 .one, .many, .c => unreachable,
8776 .slice => if (offset == 0 and size == ty_size) {
8777 vi.setParts(isel, 2);
8778 _ = vi.addPart(isel, 0, 8);
8779 _ = vi.addPart(isel, 8, 8);
8780 } else unreachable,
8781 },
8782 .opt_type => |child_type| if (ty.optionalReprIsPayload(zcu))
8783 continue :type_key ip.indexToKey(child_type)
8784 else switch (ZigType.fromInterned(child_type).abiSize(zcu)) {
8785 0...8, 16 => |child_size| if (offset == 0 and size == ty_size) {
8786 vi.setParts(isel, 2);
8787 _ = vi.addPart(isel, 0, child_size);
8788 _ = vi.addPart(isel, child_size, 1);
8789 } else unreachable,
8790 9...15 => |child_size| if (offset == 0 and size == ty_size) {
8791 vi.setParts(isel, 2);
8792 _ = vi.addPart(isel, 0, 8);
8793 _ = vi.addPart(isel, 8, ty_size - 8);
8794 } else if (offset == 8 and size == ty_size - 8) {
8795 vi.setParts(isel, 2);
8796 _ = vi.addPart(isel, 0, child_size - 8);
8797 _ = vi.addPart(isel, child_size - 8, 1);
8798 } else unreachable,
8799 else => return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)}),
8800 },
8801 .array_type => |array_type| {
8802 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
8803 const array_len = array_type.lenIncludingSentinel();
8804 if (array_len > Value.max_parts and
8805 (std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
8806 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
8807 const alignment = vi.alignment(isel);
8808 const Part = struct { offset: u64, size: u64 };
8809 var parts: [Value.max_parts]Part = undefined;
8810 var parts_len: Value.PartsLen = 0;
8811 const elem_ty: ZigType = .fromInterned(array_type.child);
8812 const elem_size = elem_ty.abiSize(zcu);
8813 const elem_signedness = if (ty.isAbiInt(zcu)) elem_signedness: {
8814 const elem_int_info = elem_ty.intInfo(zcu);
8815 break :elem_signedness if (elem_int_info.bits <= 16) elem_int_info.signedness else null;
8816 } else null;
8817 const elem_is_vector = elem_size <= 16 and
8818 CallAbiIterator.homogeneousAggregateBaseType(zcu, elem_ty.toIntern()) != null;
8819 var elem_end: u64 = 0;
8820 for (0..@intCast(array_len)) |_| {
8821 const elem_begin = elem_end;
8822 if (elem_begin >= offset + size) break;
8823 elem_end = elem_begin + elem_size;
8824 if (elem_end <= offset) continue;
8825 if (offset >= elem_begin and offset + size <= elem_begin + elem_size) {
8826 ty = elem_ty;
8827 ty_size = elem_size;
8828 offset -= elem_begin;
8829 continue :type_key ip.indexToKey(elem_ty.toIntern());
8830 }
8831 if (parts_len > 0) combine: {
8832 const prev_part = &parts[parts_len - 1];
8833 const combined_size = elem_end - prev_part.offset;
8834 if (combined_size > @as(u64, 1) << @min(
8835 min_part_log2_stride,
8836 alignment.toLog2Units(),
8837 @ctz(prev_part.offset),
8838 )) break :combine;
8839 prev_part.size = combined_size;
8840 continue;
8841 }
8842 parts[parts_len] = .{ .offset = elem_begin, .size = elem_size };
8843 parts_len += 1;
8844 }
8845 vi.setParts(isel, parts_len);
8846 for (parts[0..parts_len]) |part| {
8847 const subpart_vi = vi.addPart(isel, part.offset - offset, part.size);
8848 if (elem_signedness) |signedness| subpart_vi.setSignedness(isel, signedness);
8849 if (elem_is_vector) subpart_vi.setIsVector(isel);
8850 }
8851 },
8852 .anyframe_type => unreachable,
8853 .error_union_type => |error_union_type| {
8854 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
8855 if ((std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
8856 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
8857 const alignment = vi.alignment(isel);
8858 const payload_ty: ZigType = .fromInterned(error_union_type.payload_type);
8859 const error_set_offset = codegen.errUnionErrorOffset(payload_ty, zcu);
8860 const payload_offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
8861 const Part = struct { offset: u64, size: u64, signedness: ?std.builtin.Signedness, is_vector: bool };
8862 var parts: [2]Part = undefined;
8863 var parts_len: Value.PartsLen = 0;
8864 var field_end: u64 = 0;
8865 for (0..2) |field_index| {
8866 const field_ty: ZigType, const field_begin = switch (@as(enum { error_set, payload }, switch (field_index) {
8867 0 => if (error_set_offset < payload_offset) .error_set else .payload,
8868 1 => if (error_set_offset < payload_offset) .payload else .error_set,
8869 else => unreachable,
8870 })) {
8871 .error_set => .{ .fromInterned(error_union_type.error_set_type), error_set_offset },
8872 .payload => .{ payload_ty, payload_offset },
8873 };
8874 if (field_begin >= offset + size) break;
8875 const field_size = field_ty.abiSize(zcu);
8876 if (field_size == 0) continue;
8877 field_end = field_begin + field_size;
8878 if (field_end <= offset) continue;
8879 if (offset >= field_begin and offset + size <= field_begin + field_size) {
8880 ty = field_ty;
8881 ty_size = field_size;
8882 offset -= field_begin;
8883 continue :type_key ip.indexToKey(field_ty.toIntern());
8884 }
8885 const field_signedness = if (field_ty.isAbiInt(zcu)) field_signedness: {
8886 const field_int_info = field_ty.intInfo(zcu);
8887 break :field_signedness if (field_int_info.bits <= 16) field_int_info.signedness else null;
8888 } else null;
8889 const field_is_vector = field_size <= 16 and
8890 CallAbiIterator.homogeneousAggregateBaseType(zcu, field_ty.toIntern()) != null;
8891 if (parts_len > 0) combine: {
8892 const prev_part = &parts[parts_len - 1];
8893 const combined_size = field_end - prev_part.offset;
8894 if (combined_size > @as(u64, 1) << @min(
8895 min_part_log2_stride,
8896 alignment.toLog2Units(),
8897 @ctz(prev_part.offset),
8898 )) break :combine;
8899 prev_part.size = combined_size;
8900 prev_part.signedness = null;
8901 prev_part.is_vector &= field_is_vector;
8902 continue;
8903 }
8904 parts[parts_len] = .{
8905 .offset = field_begin,
8906 .size = field_size,
8907 .signedness = field_signedness,
8908 .is_vector = field_is_vector,
8909 };
8910 parts_len += 1;
8911 }
8912 vi.setParts(isel, parts_len);
8913 for (parts[0..parts_len]) |part| {
8914 const subpart_vi = vi.addPart(isel, part.offset - offset, part.size);
8915 if (part.signedness) |signedness| subpart_vi.setSignedness(isel, signedness);
8916 if (part.is_vector) subpart_vi.setIsVector(isel);
8917 }
8918 },
8919 .simple_type => |simple_type| switch (simple_type) {
8920 .f16, .f32, .f64, .f128, .c_longdouble => return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)}),
8921 .f80 => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 80 } },
8922 .usize,
8923 .isize,
8924 .c_char,
8925 .c_short,
8926 .c_ushort,
8927 .c_int,
8928 .c_uint,
8929 .c_long,
8930 .c_ulong,
8931 .c_longlong,
8932 .c_ulonglong,
8933 => continue :type_key .{ .int_type = ty.intInfo(zcu) },
8934 .anyopaque,
8935 .void,
8936 .type,
8937 .comptime_int,
8938 .comptime_float,
8939 .noreturn,
8940 .null,
8941 .undefined,
8942 .enum_literal,
8943 .adhoc_inferred_error_set,
8944 .generic_poison,
8945 => unreachable,
8946 .bool => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 1 } },
8947 .anyerror => continue :type_key .{ .int_type = .{
8948 .signedness = .unsigned,
8949 .bits = zcu.errorSetBits(),
8950 } },
8951 },
8952 .struct_type => {
8953 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
8954 const loaded_struct = ip.loadStructType(ty.toIntern());
8955 if (loaded_struct.field_types.len > Value.max_parts and
8956 (std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
8957 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
8958 const alignment = vi.alignment(isel);
8959 const Part = struct { offset: u64, size: u64, signedness: ?std.builtin.Signedness, is_vector: bool };
8960 var parts: [Value.max_parts]Part = undefined;
8961 var parts_len: Value.PartsLen = 0;
8962 var field_end: u64 = 0;
8963 var field_it = loaded_struct.iterateRuntimeOrder(ip);
8964 while (field_it.next()) |field_index| {
8965 const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
8966 const field_begin = switch (loaded_struct.fieldAlign(ip, field_index)) {
8967 .none => field_ty.abiAlignment(zcu),
8968 else => |field_align| field_align,
8969 }.forward(field_end);
8970 if (field_begin >= offset + size) break;
8971 const field_size = field_ty.abiSize(zcu);
8972 field_end = field_begin + field_size;
8973 if (field_end <= offset) continue;
8974 if (offset >= field_begin and offset + size <= field_begin + field_size) {
8975 ty = field_ty;
8976 ty_size = field_size;
8977 offset -= field_begin;
8978 continue :type_key ip.indexToKey(field_ty.toIntern());
8979 }
8980 const field_signedness = if (field_ty.isAbiInt(zcu)) field_signedness: {
8981 const field_int_info = field_ty.intInfo(zcu);
8982 break :field_signedness if (field_int_info.bits <= 16) field_int_info.signedness else null;
8983 } else null;
8984 const field_is_vector = field_size <= 16 and
8985 CallAbiIterator.homogeneousAggregateBaseType(zcu, field_ty.toIntern()) != null;
8986 if (parts_len > 0) combine: {
8987 const prev_part = &parts[parts_len - 1];
8988 const combined_size = field_end - prev_part.offset;
8989 if (combined_size > @as(u64, 1) << @min(
8990 min_part_log2_stride,
8991 alignment.toLog2Units(),
8992 @ctz(prev_part.offset),
8993 )) break :combine;
8994 prev_part.size = combined_size;
8995 prev_part.signedness = null;
8996 prev_part.is_vector &= field_is_vector;
8997 continue;
8998 }
8999 parts[parts_len] = .{
9000 .offset = field_begin,
9001 .size = field_size,
9002 .signedness = field_signedness,
9003 .is_vector = field_is_vector,
9004 };
9005 parts_len += 1;
9006 }
9007 vi.setParts(isel, parts_len);
9008 for (parts[0..parts_len]) |part| {
9009 const subpart_vi = vi.addPart(isel, part.offset - offset, part.size);
9010 if (part.signedness) |signedness| subpart_vi.setSignedness(isel, signedness);
9011 if (part.is_vector) subpart_vi.setIsVector(isel);
9012 }
9013 },
9014 .tuple_type => |tuple_type| {
9015 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
9016 if (tuple_type.types.len > Value.max_parts and
9017 (std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
9018 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
9019 const alignment = vi.alignment(isel);
9020 const Part = struct { offset: u64, size: u64, is_vector: bool };
9021 var parts: [Value.max_parts]Part = undefined;
9022 var parts_len: Value.PartsLen = 0;
9023 var field_end: u64 = 0;
9024 for (tuple_type.types.get(ip), tuple_type.values.get(ip)) |field_type, field_value| {
9025 if (field_value != .none) continue;
9026 const field_ty: ZigType = .fromInterned(field_type);
9027 const field_begin = field_ty.abiAlignment(zcu).forward(field_end);
9028 if (field_begin >= offset + size) break;
9029 const field_size = field_ty.abiSize(zcu);
9030 if (field_size == 0) continue;
9031 field_end = field_begin + field_size;
9032 if (field_end <= offset) continue;
9033 if (offset >= field_begin and offset + size <= field_begin + field_size) {
9034 ty = field_ty;
9035 ty_size = field_size;
9036 offset -= field_begin;
9037 continue :type_key ip.indexToKey(field_ty.toIntern());
9038 }
9039 const field_is_vector = field_size <= 16 and
9040 CallAbiIterator.homogeneousAggregateBaseType(zcu, field_ty.toIntern()) != null;
9041 if (parts_len > 0) combine: {
9042 const prev_part = &parts[parts_len - 1];
9043 const combined_size = field_end - prev_part.offset;
9044 if (combined_size > @as(u64, 1) << @min(
9045 min_part_log2_stride,
9046 alignment.toLog2Units(),
9047 @ctz(prev_part.offset),
9048 )) break :combine;
9049 prev_part.size = combined_size;
9050 prev_part.is_vector &= field_is_vector;
9051 continue;
9052 }
9053 parts[parts_len] = .{ .offset = field_begin, .size = field_size, .is_vector = field_is_vector };
9054 parts_len += 1;
9055 }
9056 vi.setParts(isel, parts_len);
9057 for (parts[0..parts_len]) |part| {
9058 const subpart_vi = vi.addPart(isel, part.offset - offset, part.size);
9059 if (part.is_vector) subpart_vi.setIsVector(isel);
9060 }
9061 },
9062 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
9063 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
9064 .error_set_type,
9065 .inferred_error_set_type,
9066 => continue :type_key .{ .simple_type = .anyerror },
9067 .undef,
9068 .simple_value,
9069 .variable,
9070 .@"extern",
9071 .func,
9072 .int,
9073 .err,
9074 .error_union,
9075 .enum_literal,
9076 .enum_tag,
9077 .empty_enum_value,
9078 .float,
9079 .ptr,
9080 .slice,
9081 .opt,
9082 .aggregate,
9083 .un,
9084 .memoized_call,
9085 => unreachable, // values, not types
9086 }
9087 }
9088 it.next_offset = next_offset + size;
9089 return .{ .offset = next_part_offset - next_offset, .vi = vi };
9090 }
9091
9092 fn only(it: *FieldPartIterator, isel: *Select) !?Value.Index {
9093 const part = try it.next(isel);
9094 assert(part.?.offset == 0);
9095 return if (try it.next(isel)) |_| null else part.?.vi;
9096 }
9097 };
9098
9099 const Materialize = struct {
9100 vi: Value.Index,
9101 ra: Register.Alias,
9102
9103 fn finish(mat: Value.Materialize, isel: *Select) error{ OutOfMemory, CodegenFail }!void {
9104 const live_vi = isel.live_registers.getPtr(mat.ra);
9105 assert(live_vi.* == .allocating);
9106 var vi = mat.vi;
9107 var offset: i65 = 0;
9108 const size = mat.vi.size(isel);
9109 free: while (true) {
9110 if (vi.register(isel)) |ra| {
9111 if (ra != mat.ra) break :free try isel.emit(if (vi == mat.vi) if (mat.ra.isVector()) switch (size) {
9112 else => unreachable,
9113 2 => .fmov(mat.ra.h(), .{ .register = ra.h() }),
9114 4 => .fmov(mat.ra.s(), .{ .register = ra.s() }),
9115 8 => .fmov(mat.ra.d(), .{ .register = ra.d() }),
9116 16 => .orr(mat.ra.@"16b"(), ra.@"16b"(), .{ .register = ra.@"16b"() }),
9117 } else switch (size) {
9118 else => unreachable,
9119 1...4 => .orr(mat.ra.w(), .wzr, .{ .register = ra.w() }),
9120 5...8 => .orr(mat.ra.x(), .xzr, .{ .register = ra.x() }),
9121 } else switch (offset + size) {
9122 else => unreachable,
9123 1...4 => |end_offset| switch (mat.vi.signedness(isel)) {
9124 .signed => .sbfm(mat.ra.w(), ra.w(), .{
9125 .N = .word,
9126 .immr = @intCast(8 * offset),
9127 .imms = @intCast(8 * end_offset - 1),
9128 }),
9129 .unsigned => .ubfm(mat.ra.w(), ra.w(), .{
9130 .N = .word,
9131 .immr = @intCast(8 * offset),
9132 .imms = @intCast(8 * end_offset - 1),
9133 }),
9134 },
9135 5...8 => |end_offset| switch (mat.vi.signedness(isel)) {
9136 .signed => .sbfm(mat.ra.x(), ra.x(), .{
9137 .N = .doubleword,
9138 .immr = @intCast(8 * offset),
9139 .imms = @intCast(8 * end_offset - 1),
9140 }),
9141 .unsigned => .ubfm(mat.ra.x(), ra.x(), .{
9142 .N = .doubleword,
9143 .immr = @intCast(8 * offset),
9144 .imms = @intCast(8 * end_offset - 1),
9145 }),
9146 },
9147 });
9148 mat.vi.get(isel).location_payload.small.register = mat.ra;
9149 live_vi.* = mat.vi;
9150 return;
9151 }
9152 offset += vi.get(isel).offset_from_parent;
9153 switch (vi.parent(isel)) {
9154 .unallocated => {
9155 mat.vi.get(isel).location_payload.small.register = mat.ra;
9156 live_vi.* = mat.vi;
9157 return;
9158 },
9159 .stack_slot => |stack_slot| {
9160 offset += stack_slot.offset;
9161 break :free try isel.emit(switch (size) {
9162 else => unreachable,
9163 1 => if (mat.ra.isVector()) .ldr(mat.ra.b(), .{ .unsigned_offset = .{
9164 .base = stack_slot.base.x(),
9165 .offset = @intCast(offset),
9166 } }) else switch (mat.vi.signedness(isel)) {
9167 .signed => .ldrsb(mat.ra.w(), .{ .unsigned_offset = .{
9168 .base = stack_slot.base.x(),
9169 .offset = @intCast(offset),
9170 } }),
9171 .unsigned => .ldrb(mat.ra.w(), .{ .unsigned_offset = .{
9172 .base = stack_slot.base.x(),
9173 .offset = @intCast(offset),
9174 } }),
9175 },
9176 2 => if (mat.ra.isVector()) .ldr(mat.ra.h(), .{ .unsigned_offset = .{
9177 .base = stack_slot.base.x(),
9178 .offset = @intCast(offset),
9179 } }) else switch (mat.vi.signedness(isel)) {
9180 .signed => .ldrsh(mat.ra.w(), .{ .unsigned_offset = .{
9181 .base = stack_slot.base.x(),
9182 .offset = @intCast(offset),
9183 } }),
9184 .unsigned => .ldrh(mat.ra.w(), .{ .unsigned_offset = .{
9185 .base = stack_slot.base.x(),
9186 .offset = @intCast(offset),
9187 } }),
9188 },
9189 4 => .ldr(if (mat.ra.isVector()) mat.ra.s() else mat.ra.w(), .{ .unsigned_offset = .{
9190 .base = stack_slot.base.x(),
9191 .offset = @intCast(offset),
9192 } }),
9193 8 => .ldr(if (mat.ra.isVector()) mat.ra.d() else mat.ra.x(), .{ .unsigned_offset = .{
9194 .base = stack_slot.base.x(),
9195 .offset = @intCast(offset),
9196 } }),
9197 16 => .ldr(mat.ra.q(), .{ .unsigned_offset = .{
9198 .base = stack_slot.base.x(),
9199 .offset = @intCast(offset),
9200 } }),
9201 });
9202 },
9203 .address => |base_vi| {
9204 const base_mat = try base_vi.matReg(isel);
9205 try isel.emit(switch (size) {
9206 else => unreachable,
9207 1 => if (mat.ra.isVector()) .ldr(mat.ra.b(), .{ .unsigned_offset = .{
9208 .base = base_mat.ra.x(),
9209 .offset = @intCast(offset),
9210 } }) else switch (mat.vi.signedness(isel)) {
9211 .signed => .ldrsb(mat.ra.w(), .{ .unsigned_offset = .{
9212 .base = base_mat.ra.x(),
9213 .offset = @intCast(offset),
9214 } }),
9215 .unsigned => .ldrb(mat.ra.w(), .{ .unsigned_offset = .{
9216 .base = base_mat.ra.x(),
9217 .offset = @intCast(offset),
9218 } }),
9219 },
9220 2 => if (mat.ra.isVector()) .ldr(mat.ra.h(), .{ .unsigned_offset = .{
9221 .base = base_mat.ra.x(),
9222 .offset = @intCast(offset),
9223 } }) else switch (mat.vi.signedness(isel)) {
9224 .signed => .ldrsh(mat.ra.w(), .{ .unsigned_offset = .{
9225 .base = base_mat.ra.x(),
9226 .offset = @intCast(offset),
9227 } }),
9228 .unsigned => .ldrh(mat.ra.w(), .{ .unsigned_offset = .{
9229 .base = base_mat.ra.x(),
9230 .offset = @intCast(offset),
9231 } }),
9232 },
9233 4 => .ldr(if (mat.ra.isVector()) mat.ra.s() else mat.ra.w(), .{ .unsigned_offset = .{
9234 .base = base_mat.ra.x(),
9235 .offset = @intCast(offset),
9236 } }),
9237 8 => .ldr(if (mat.ra.isVector()) mat.ra.d() else mat.ra.x(), .{ .unsigned_offset = .{
9238 .base = base_mat.ra.x(),
9239 .offset = @intCast(offset),
9240 } }),
9241 16 => .ldr(mat.ra.q(), .{ .unsigned_offset = .{
9242 .base = base_mat.ra.x(),
9243 .offset = @intCast(offset),
9244 } }),
9245 });
9246 break :free try base_mat.finish(isel);
9247 },
9248 .value => |parent_vi| vi = parent_vi,
9249 .constant => |initial_constant| {
9250 const zcu = isel.pt.zcu;
9251 const ip = &zcu.intern_pool;
9252 var constant = initial_constant.toIntern();
9253 var constant_key = ip.indexToKey(constant);
9254 while (true) {
9255 constant_key: switch (constant_key) {
9256 .int_type,
9257 .ptr_type,
9258 .array_type,
9259 .vector_type,
9260 .opt_type,
9261 .anyframe_type,
9262 .error_union_type,
9263 .simple_type,
9264 .struct_type,
9265 .tuple_type,
9266 .union_type,
9267 .opaque_type,
9268 .enum_type,
9269 .func_type,
9270 .error_set_type,
9271 .inferred_error_set_type,
9272
9273 .enum_literal,
9274 .empty_enum_value,
9275 .memoized_call,
9276 => unreachable, // not a runtime value
9277 .undef => break :free try isel.emit(if (mat.ra.isVector()) .movi(switch (size) {
9278 else => unreachable,
9279 1...8 => mat.ra.@"8b"(),
9280 9...16 => mat.ra.@"16b"(),
9281 }, 0xaa, .{ .lsl = 0 }) else switch (size) {
9282 else => unreachable,
9283 1...4 => .orr(mat.ra.w(), .wzr, .{ .immediate = .{
9284 .N = .word,
9285 .immr = 0b000001,
9286 .imms = 0b111100,
9287 } }),
9288 5...8 => .orr(mat.ra.x(), .xzr, .{ .immediate = .{
9289 .N = .word,
9290 .immr = 0b000001,
9291 .imms = 0b111100,
9292 } }),
9293 }),
9294 .simple_value => |simple_value| switch (simple_value) {
9295 .undefined, .void, .null, .empty_tuple, .@"unreachable" => unreachable,
9296 .true => continue :constant_key .{ .int = .{
9297 .ty = .bool_type,
9298 .storage = .{ .u64 = 1 },
9299 } },
9300 .false => continue :constant_key .{ .int = .{
9301 .ty = .bool_type,
9302 .storage = .{ .u64 = 0 },
9303 } },
9304 },
9305 .int => |int| break :free storage: switch (int.storage) {
9306 .u64 => |imm| try isel.movImmediate(switch (size) {
9307 else => unreachable,
9308 1...4 => mat.ra.w(),
9309 5...8 => mat.ra.x(),
9310 }, @bitCast(std.math.shr(u64, imm, 8 * offset))),
9311 .i64 => |imm| switch (size) {
9312 else => unreachable,
9313 1...4 => try isel.movImmediate(mat.ra.w(), @as(u32, @bitCast(@as(i32, @truncate(std.math.shr(i64, imm, 8 * offset)))))),
9314 5...8 => try isel.movImmediate(mat.ra.x(), @bitCast(std.math.shr(i64, imm, 8 * offset))),
9315 },
9316 .big_int => |big_int| {
9317 assert(size == 8);
9318 var imm: u64 = 0;
9319 const limb_bits = @bitSizeOf(std.math.big.Limb);
9320 const limbs = @divExact(64, limb_bits);
9321 var limb_index: usize = @intCast(@divExact(offset, @divExact(limb_bits, 8)) + limbs);
9322 for (0..limbs) |_| {
9323 limb_index -= 1;
9324 if (limb_index >= big_int.limbs.len) continue;
9325 if (limb_bits < 64) imm <<= limb_bits;
9326 imm |= big_int.limbs[limb_index];
9327 }
9328 if (!big_int.positive) {
9329 limb_index = @min(limb_index, big_int.limbs.len);
9330 imm = while (limb_index > 0) {
9331 limb_index -= 1;
9332 if (big_int.limbs[limb_index] != 0) break ~imm;
9333 } else -%imm;
9334 }
9335 try isel.movImmediate(mat.ra.x(), imm);
9336 },
9337 .lazy_align => |ty| continue :storage .{
9338 .u64 = ZigType.fromInterned(ty).abiAlignment(zcu).toByteUnits().?,
9339 },
9340 .lazy_size => |ty| continue :storage .{
9341 .u64 = ZigType.fromInterned(ty).abiSize(zcu),
9342 },
9343 },
9344 .err => |err| continue :constant_key .{ .int = .{
9345 .ty = err.ty,
9346 .storage = .{ .u64 = ip.getErrorValueIfExists(err.name).? },
9347 } },
9348 .error_union => |error_union| {
9349 const error_union_type = ip.indexToKey(error_union.ty).error_union_type;
9350 const payload_ty: ZigType = .fromInterned(error_union_type.payload_type);
9351 if (!ip.isNoReturn(error_union_type.error_set_type) and
9352 offset == codegen.errUnionErrorOffset(payload_ty, zcu))
9353 {
9354 offset = 0;
9355 continue :constant_key switch (error_union.val) {
9356 .err_name => |err_name| .{ .err = .{
9357 .ty = error_union_type.error_set_type,
9358 .name = err_name,
9359 } },
9360 .payload => .{ .int = .{
9361 .ty = error_union_type.error_set_type,
9362 .storage = .{ .u64 = 0 },
9363 } },
9364 };
9365 }
9366 assert(payload_ty.hasRuntimeBitsIgnoreComptime(zcu));
9367 offset -= @intCast(codegen.errUnionPayloadOffset(payload_ty, zcu));
9368 switch (error_union.val) {
9369 .err_name => continue :constant_key .{ .undef = error_union_type.payload_type },
9370 .payload => |payload| {
9371 constant = payload;
9372 constant_key = ip.indexToKey(payload);
9373 continue :constant_key constant_key;
9374 },
9375 }
9376 },
9377 .enum_tag => |enum_tag| continue :constant_key .{ .int = ip.indexToKey(enum_tag.int).int },
9378 .float => |float| storage: switch (float.storage) {
9379 .f16 => |imm| {
9380 if (!mat.ra.isVector()) continue :constant_key .{ .int = .{
9381 .ty = .u16_type,
9382 .storage = .{ .u64 = @as(u16, @bitCast(imm)) },
9383 } };
9384 const feat_fp16 = isel.target.cpu.has(.aarch64, .fullfp16);
9385 if (feat_fp16) {
9386 const Repr = std.math.FloatRepr(f16);
9387 const repr: Repr = @bitCast(imm);
9388 if (repr.mantissa & std.math.maxInt(Repr.Mantissa) >> 5 == 0 and switch (repr.exponent) {
9389 .denormal, .infinite => false,
9390 else => std.math.cast(i3, repr.exponent.unbias() - 1) != null,
9391 }) break :free try isel.emit(.fmov(mat.ra.h(), .{ .immediate = imm }));
9392 }
9393 const bits: u16 = @bitCast(imm);
9394 if (bits == 0) break :free try isel.emit(.movi(mat.ra.d(), 0b00000000, .replicate));
9395 if (bits & std.math.maxInt(u8) == 0) break :free try isel.emit(.movi(
9396 mat.ra.@"4h"(),
9397 @intCast(@shrExact(bits, 8)),
9398 .{ .lsl = 8 },
9399 ));
9400 const temp_ra = try isel.allocIntReg();
9401 defer isel.freeReg(temp_ra);
9402 try isel.emit(.fmov(if (feat_fp16) mat.ra.h() else mat.ra.s(), .{ .register = temp_ra.w() }));
9403 break :free try isel.movImmediate(temp_ra.w(), bits);
9404 },
9405 .f32 => |imm| {
9406 if (!mat.ra.isVector()) continue :constant_key .{ .int = .{
9407 .ty = .u32_type,
9408 .storage = .{ .u64 = @as(u32, @bitCast(imm)) },
9409 } };
9410 const Repr = std.math.FloatRepr(f32);
9411 const repr: Repr = @bitCast(imm);
9412 if (repr.mantissa & std.math.maxInt(Repr.Mantissa) >> 5 == 0 and switch (repr.exponent) {
9413 .denormal, .infinite => false,
9414 else => std.math.cast(i3, repr.exponent.unbias() - 1) != null,
9415 }) break :free try isel.emit(.fmov(mat.ra.s(), .{ .immediate = @floatCast(imm) }));
9416 const bits: u32 = @bitCast(imm);
9417 if (bits == 0) break :free try isel.emit(.movi(mat.ra.d(), 0b00000000, .replicate));
9418 if (bits & std.math.maxInt(u24) == 0) break :free try isel.emit(.movi(
9419 mat.ra.@"2s"(),
9420 @intCast(@shrExact(bits, 24)),
9421 .{ .lsl = 24 },
9422 ));
9423 const temp_ra = try isel.allocIntReg();
9424 defer isel.freeReg(temp_ra);
9425 try isel.emit(.fmov(mat.ra.s(), .{ .register = temp_ra.w() }));
9426 break :free try isel.movImmediate(temp_ra.w(), bits);
9427 },
9428 .f64 => |imm| {
9429 if (!mat.ra.isVector()) continue :constant_key .{ .int = .{
9430 .ty = .u64_type,
9431 .storage = .{ .u64 = @as(u64, @bitCast(imm)) },
9432 } };
9433 const Repr = std.math.FloatRepr(f64);
9434 const repr: Repr = @bitCast(imm);
9435 if (repr.mantissa & std.math.maxInt(Repr.Mantissa) >> 5 == 0 and switch (repr.exponent) {
9436 .denormal, .infinite => false,
9437 else => std.math.cast(i3, repr.exponent.unbias() - 1) != null,
9438 }) break :free try isel.emit(.fmov(mat.ra.d(), .{ .immediate = @floatCast(imm) }));
9439 const bits: u64 = @bitCast(imm);
9440 if (bits == 0) break :free try isel.emit(.movi(mat.ra.d(), 0b00000000, .replicate));
9441 const temp_ra = try isel.allocIntReg();
9442 defer isel.freeReg(temp_ra);
9443 try isel.emit(.fmov(mat.ra.d(), .{ .register = temp_ra.x() }));
9444 break :free try isel.movImmediate(temp_ra.x(), bits);
9445 },
9446 .f80 => |imm| break :free try isel.movImmediate(
9447 mat.ra.x(),
9448 @truncate(std.math.shr(u80, @bitCast(imm), 8 * offset)),
9449 ),
9450 .f128 => |imm| switch (ZigType.fromInterned(float.ty).floatBits(isel.target)) {
9451 else => unreachable,
9452 16 => continue :storage .{ .f16 = @floatCast(imm) },
9453 32 => continue :storage .{ .f32 = @floatCast(imm) },
9454 64 => continue :storage .{ .f64 = @floatCast(imm) },
9455 128 => {
9456 const bits: u128 = @bitCast(imm);
9457 const hi64: u64 = @intCast(bits >> 64);
9458 const lo64: u64 = @truncate(bits >> 0);
9459 const temp_ra = try isel.allocIntReg();
9460 defer isel.freeReg(temp_ra);
9461 switch (hi64) {
9462 0 => {},
9463 else => {
9464 try isel.emit(.fmov(mat.ra.@"d[]"(1), .{ .register = temp_ra.x() }));
9465 try isel.movImmediate(temp_ra.x(), hi64);
9466 },
9467 }
9468 break :free switch (lo64) {
9469 0 => try isel.emit(.movi(switch (hi64) {
9470 else => mat.ra.d(),
9471 0 => mat.ra.@"2d"(),
9472 }, 0b00000000, .replicate)),
9473 else => {
9474 try isel.emit(.fmov(mat.ra.d(), .{ .register = temp_ra.x() }));
9475 try isel.movImmediate(temp_ra.x(), lo64);
9476 },
9477 };
9478 },
9479 },
9480 },
9481 .ptr => |ptr| {
9482 assert(offset == 0 and size == 8);
9483 break :free switch (ptr.base_addr) {
9484 .nav => |nav| if (ZigType.fromInterned(ip.getNav(nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) {
9485 false => {
9486 try isel.nav_relocs.append(zcu.gpa, .{
9487 .nav = nav,
9488 .reloc = .{
9489 .label = @intCast(isel.instructions.items.len),
9490 .addend = ptr.byte_offset,
9491 },
9492 });
9493 try isel.emit(.adr(mat.ra.x(), 0));
9494 },
9495 true => {
9496 try isel.nav_relocs.append(zcu.gpa, .{
9497 .nav = nav,
9498 .reloc = .{
9499 .label = @intCast(isel.instructions.items.len),
9500 .addend = ptr.byte_offset,
9501 },
9502 });
9503 try isel.emit(.add(mat.ra.x(), mat.ra.x(), .{ .immediate = 0 }));
9504 try isel.nav_relocs.append(zcu.gpa, .{
9505 .nav = nav,
9506 .reloc = .{
9507 .label = @intCast(isel.instructions.items.len),
9508 .addend = ptr.byte_offset,
9509 },
9510 });
9511 try isel.emit(.adrp(mat.ra.x(), 0));
9512 },
9513 } else continue :constant_key .{ .int = .{
9514 .ty = .usize_type,
9515 .storage = .{ .u64 = isel.pt.navAlignment(nav).forward(0xaaaaaaaaaaaaaaaa) },
9516 } },
9517 .uav => |uav| if (ZigType.fromInterned(ip.typeOf(uav.val)).isFnOrHasRuntimeBits(zcu)) switch (true) {
9518 false => {
9519 try isel.uav_relocs.append(zcu.gpa, .{
9520 .uav = uav,
9521 .reloc = .{
9522 .label = @intCast(isel.instructions.items.len),
9523 .addend = ptr.byte_offset,
9524 },
9525 });
9526 try isel.emit(.adr(mat.ra.x(), 0));
9527 },
9528 true => {
9529 try isel.uav_relocs.append(zcu.gpa, .{
9530 .uav = uav,
9531 .reloc = .{
9532 .label = @intCast(isel.instructions.items.len),
9533 .addend = ptr.byte_offset,
9534 },
9535 });
9536 try isel.emit(.add(mat.ra.x(), mat.ra.x(), .{ .immediate = 0 }));
9537 try isel.uav_relocs.append(zcu.gpa, .{
9538 .uav = uav,
9539 .reloc = .{
9540 .label = @intCast(isel.instructions.items.len),
9541 .addend = ptr.byte_offset,
9542 },
9543 });
9544 try isel.emit(.adrp(mat.ra.x(), 0));
9545 },
9546 } else continue :constant_key .{ .int = .{
9547 .ty = .usize_type,
9548 .storage = .{ .u64 = ZigType.fromInterned(uav.orig_ty).ptrAlignment(zcu).forward(0xaaaaaaaaaaaaaaaa) },
9549 } },
9550 .int => continue :constant_key .{ .int = .{
9551 .ty = .usize_type,
9552 .storage = .{ .u64 = ptr.byte_offset },
9553 } },
9554 .eu_payload => |base| {
9555 var base_ptr = ip.indexToKey(base).ptr;
9556 const eu_ty = ip.indexToKey(base_ptr.ty).ptr_type.child;
9557 const payload_ty = ip.indexToKey(eu_ty).error_union_type.payload_type;
9558 base_ptr.byte_offset += codegen.errUnionPayloadOffset(.fromInterned(payload_ty), zcu);
9559 continue :constant_key .{ .ptr = base_ptr };
9560 },
9561 .opt_payload => |base| continue :constant_key .{ .ptr = ip.indexToKey(base).ptr },
9562 .field => |field| {
9563 var base_ptr = ip.indexToKey(field.base).ptr;
9564 const agg_ty: ZigType = .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child);
9565 base_ptr.byte_offset += agg_ty.structFieldOffset(@intCast(field.index), zcu);
9566 continue :constant_key .{ .ptr = base_ptr };
9567 },
9568 .comptime_alloc, .comptime_field, .arr_elem => unreachable,
9569 };
9570 },
9571 .slice => |slice| switch (offset) {
9572 0 => continue :constant_key .{ .ptr = ip.indexToKey(slice.ptr).ptr },
9573 else => {
9574 assert(offset == @divExact(isel.target.ptrBitWidth(), 8));
9575 offset = 0;
9576 continue :constant_key .{ .int = ip.indexToKey(slice.len).int };
9577 },
9578 },
9579 .opt => |opt| {
9580 const child_ty = ip.indexToKey(opt.ty).opt_type;
9581 const child_size = ZigType.fromInterned(child_ty).abiSize(zcu);
9582 if (offset == child_size and size == 1) {
9583 offset = 0;
9584 continue :constant_key .{ .simple_value = switch (opt.val) {
9585 .none => .false,
9586 else => .true,
9587 } };
9588 }
9589 const opt_ty: ZigType = .fromInterned(opt.ty);
9590 if (offset + size <= child_size) continue :constant_key switch (opt.val) {
9591 .none => if (opt_ty.optionalReprIsPayload(zcu)) .{ .int = .{
9592 .ty = opt.ty,
9593 .storage = .{ .u64 = 0 },
9594 } } else .{ .undef = child_ty },
9595 else => |child| {
9596 constant = child;
9597 constant_key = ip.indexToKey(child);
9598 continue :constant_key constant_key;
9599 },
9600 };
9601 },
9602 .aggregate => |aggregate| switch (ip.indexToKey(aggregate.ty)) {
9603 else => unreachable,
9604 .array_type => |array_type| {
9605 const elem_size = ZigType.fromInterned(array_type.child).abiSize(zcu);
9606 const elem_offset = @mod(offset, elem_size);
9607 if (size <= elem_size - elem_offset) {
9608 defer offset = elem_offset;
9609 continue :constant_key switch (aggregate.storage) {
9610 .bytes => |bytes| .{ .int = .{ .ty = .u8_type, .storage = .{
9611 .u64 = bytes.toSlice(array_type.lenIncludingSentinel(), ip)[@intCast(@divFloor(offset, elem_size))],
9612 } } },
9613 .elems => |elems| {
9614 constant = elems[@intCast(@divFloor(offset, elem_size))];
9615 constant_key = ip.indexToKey(constant);
9616 continue :constant_key constant_key;
9617 },
9618 .repeated_elem => |repeated_elem| {
9619 constant = repeated_elem;
9620 constant_key = ip.indexToKey(repeated_elem);
9621 continue :constant_key constant_key;
9622 },
9623 };
9624 }
9625 },
9626 .vector_type => {},
9627 .struct_type => {
9628 const loaded_struct = ip.loadStructType(aggregate.ty);
9629 switch (loaded_struct.layout) {
9630 .auto => {
9631 var field_offset: u64 = 0;
9632 var field_it = loaded_struct.iterateRuntimeOrder(ip);
9633 while (field_it.next()) |field_index| {
9634 if (loaded_struct.fieldIsComptime(ip, field_index)) continue;
9635 const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
9636 field_offset = field_ty.structFieldAlignment(
9637 loaded_struct.fieldAlign(ip, field_index),
9638 loaded_struct.layout,
9639 zcu,
9640 ).forward(field_offset);
9641 const field_size = field_ty.abiSize(zcu);
9642 if (offset >= field_offset and offset + size <= field_offset + field_size) {
9643 offset -= field_offset;
9644 constant = switch (aggregate.storage) {
9645 .bytes => unreachable,
9646 .elems => |elems| elems[field_index],
9647 .repeated_elem => |repeated_elem| repeated_elem,
9648 };
9649 constant_key = ip.indexToKey(constant);
9650 continue :constant_key constant_key;
9651 }
9652 field_offset += field_size;
9653 }
9654 },
9655 .@"extern", .@"packed" => {},
9656 }
9657 },
9658 .tuple_type => |tuple_type| {
9659 var field_offset: u64 = 0;
9660 for (tuple_type.types.get(ip), tuple_type.values.get(ip), 0..) |field_type, field_value, field_index| {
9661 if (field_value != .none) continue;
9662 const field_ty: ZigType = .fromInterned(field_type);
9663 field_offset = field_ty.abiAlignment(zcu).forward(field_offset);
9664 const field_size = field_ty.abiSize(zcu);
9665 if (offset >= field_offset and offset + size <= field_offset + field_size) {
9666 offset -= field_offset;
9667 constant = switch (aggregate.storage) {
9668 .bytes => unreachable,
9669 .elems => |elems| elems[field_index],
9670 .repeated_elem => |repeated_elem| repeated_elem,
9671 };
9672 constant_key = ip.indexToKey(constant);
9673 continue :constant_key constant_key;
9674 }
9675 field_offset += field_size;
9676 }
9677 },
9678 },
9679 else => {},
9680 }
9681 var buffer: [16]u8 = @splat(0);
9682 if (ZigType.fromInterned(constant_key.typeOf()).abiSize(zcu) <= buffer.len and
9683 try isel.writeToMemory(.fromInterned(constant), &buffer))
9684 {
9685 constant_key = if (mat.ra.isVector()) .{ .float = switch (size) {
9686 else => unreachable,
9687 2 => .{ .ty = .f16_type, .storage = .{ .f16 = @bitCast(std.mem.readInt(
9688 u16,
9689 buffer[@intCast(offset)..][0..2],
9690 isel.target.cpu.arch.endian(),
9691 )) } },
9692 4 => .{ .ty = .f32_type, .storage = .{ .f32 = @bitCast(std.mem.readInt(
9693 u32,
9694 buffer[@intCast(offset)..][0..4],
9695 isel.target.cpu.arch.endian(),
9696 )) } },
9697 8 => .{ .ty = .f64_type, .storage = .{ .f64 = @bitCast(std.mem.readInt(
9698 u64,
9699 buffer[@intCast(offset)..][0..8],
9700 isel.target.cpu.arch.endian(),
9701 )) } },
9702 16 => .{ .ty = .f128_type, .storage = .{ .f128 = @bitCast(std.mem.readInt(
9703 u128,
9704 buffer[@intCast(offset)..][0..16],
9705 isel.target.cpu.arch.endian(),
9706 )) } },
9707 } } else .{ .int = .{
9708 .ty = .u64_type,
9709 .storage = .{ .u64 = switch (size) {
9710 else => unreachable,
9711 inline 1...8 => |ct_size| std.mem.readInt(
9712 @Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 * ct_size } }),
9713 buffer[@intCast(offset)..][0..ct_size],
9714 isel.target.cpu.arch.endian(),
9715 ),
9716 } },
9717 } };
9718 offset = 0;
9719 continue;
9720 }
9721 return isel.fail("unsupported value <{f}, {f}>", .{
9722 isel.fmtType(.fromInterned(constant_key.typeOf())),
9723 isel.fmtConstant(.fromInterned(constant)),
9724 });
9725 }
9726 },
9727 }
9728 }
9729 live_vi.* = .free;
9730 }
9731 };
9732};
9733fn initValue(isel: *Select, ty: ZigType) Value.Index {
9734 const zcu = isel.pt.zcu;
9735 return isel.initValueAdvanced(ty.abiAlignment(zcu), 0, ty.abiSize(zcu));
9736}
9737fn initValueAdvanced(
9738 isel: *Select,
9739 parent_alignment: InternPool.Alignment,
9740 offset_from_parent: u64,
9741 size: u64,
9742) Value.Index {
9743 defer isel.values.addOneAssumeCapacity().* = .{
9744 .refs = 0,
9745 .flags = .{
9746 .alignment = .fromLog2Units(@min(parent_alignment.toLog2Units(), @ctz(offset_from_parent))),
9747 .parent_tag = .unallocated,
9748 .location_tag = if (size > 16) .large else .small,
9749 .parts_len_minus_one = 0,
9750 },
9751 .offset_from_parent = offset_from_parent,
9752 .parent_payload = .{ .unallocated = {} },
9753 .location_payload = if (size > 16) .{ .large = .{
9754 .size = size,
9755 } } else .{ .small = .{
9756 .size = @intCast(size),
9757 .signedness = .unsigned,
9758 .is_vector = false,
9759 .hint = .zr,
9760 .register = .zr,
9761 } },
9762 .parts = undefined,
9763 };
9764 return @enumFromInt(isel.values.items.len);
9765}
9766pub fn dumpValues(isel: *Select, which: enum { only_referenced, all }) void {
9767 errdefer |err| @panic(@errorName(err));
9768 const stderr = std.debug.lockStderrWriter(&.{});
9769 defer std.debug.unlockStderrWriter();
9770
9771 const zcu = isel.pt.zcu;
9772 const gpa = zcu.gpa;
9773 const ip = &zcu.intern_pool;
9774 const nav = ip.getNav(isel.nav_index);
9775
9776 var reverse_live_values: std.AutoArrayHashMapUnmanaged(Value.Index, std.ArrayListUnmanaged(Air.Inst.Index)) = .empty;
9777 defer {
9778 for (reverse_live_values.values()) |*list| list.deinit(gpa);
9779 reverse_live_values.deinit(gpa);
9780 }
9781 {
9782 try reverse_live_values.ensureTotalCapacity(gpa, isel.live_values.count());
9783 var live_val_it = isel.live_values.iterator();
9784 while (live_val_it.next()) |live_val_entry| switch (live_val_entry.value_ptr.*) {
9785 _ => {
9786 const gop = reverse_live_values.getOrPutAssumeCapacity(live_val_entry.value_ptr.*);
9787 if (!gop.found_existing) gop.value_ptr.* = .empty;
9788 try gop.value_ptr.append(gpa, live_val_entry.key_ptr.*);
9789 },
9790 .allocating, .free => unreachable,
9791 };
9792 }
9793
9794 var reverse_live_registers: std.AutoHashMapUnmanaged(Value.Index, Register.Alias) = .empty;
9795 defer reverse_live_registers.deinit(gpa);
9796 {
9797 try reverse_live_registers.ensureTotalCapacity(gpa, @typeInfo(Register.Alias).@"enum".fields.len);
9798 var live_reg_it = isel.live_registers.iterator();
9799 while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) {
9800 _ => reverse_live_registers.putAssumeCapacityNoClobber(live_reg_entry.value.*, live_reg_entry.key),
9801 .allocating, .free => {},
9802 };
9803 }
9804
9805 var roots: std.AutoArrayHashMapUnmanaged(Value.Index, u32) = .empty;
9806 defer roots.deinit(gpa);
9807 {
9808 try roots.ensureTotalCapacity(gpa, isel.values.items.len);
9809 var vi: Value.Index = @enumFromInt(isel.values.items.len);
9810 while (@intFromEnum(vi) > 0) {
9811 vi = @enumFromInt(@intFromEnum(vi) - 1);
9812 if (which == .only_referenced and vi.get(isel).refs == 0) continue;
9813 while (true) switch (vi.parent(isel)) {
9814 .unallocated, .stack_slot, .constant => break,
9815 .value => |parent_vi| vi = parent_vi,
9816 .address => |address_vi| break roots.putAssumeCapacity(address_vi, 0),
9817 };
9818 roots.putAssumeCapacity(vi, 0);
9819 }
9820 }
9821
9822 try stderr.print("# Begin {s} Value Dump: {f}:\n", .{ @typeName(Select), nav.fqn.fmt(ip) });
9823 while (roots.pop()) |root_entry| {
9824 const vi = root_entry.key;
9825 const value = vi.get(isel);
9826 try stderr.splatByteAll(' ', 2 * (@as(usize, 1) + root_entry.value));
9827 try stderr.print("${d}", .{@intFromEnum(vi)});
9828 {
9829 var first = true;
9830 if (reverse_live_values.get(vi)) |aiis| for (aiis.items) |aii| {
9831 if (aii == Block.main) {
9832 try stderr.print("{s}%main", .{if (first) " <- " else ", "});
9833 } else {
9834 try stderr.print("{s}%{d}", .{ if (first) " <- " else ", ", @intFromEnum(aii) });
9835 }
9836 first = false;
9837 };
9838 if (reverse_live_registers.get(vi)) |ra| {
9839 try stderr.print("{s}{s}", .{ if (first) " <- " else ", ", @tagName(ra) });
9840 first = false;
9841 }
9842 }
9843 try stderr.writeByte(':');
9844 switch (value.flags.parent_tag) {
9845 .unallocated => if (value.offset_from_parent != 0) try stderr.print(" +0x{x}", .{value.offset_from_parent}),
9846 .stack_slot => {
9847 try stderr.print(" [{s}, #{s}0x{x}", .{
9848 @tagName(value.parent_payload.stack_slot.base),
9849 if (value.parent_payload.stack_slot.offset < 0) "-" else "",
9850 @abs(value.parent_payload.stack_slot.offset),
9851 });
9852 if (value.offset_from_parent != 0) try stderr.print("+0x{x}", .{value.offset_from_parent});
9853 try stderr.writeByte(']');
9854 },
9855 .value => try stderr.print(" ${d}+0x{x}", .{ @intFromEnum(value.parent_payload.value), value.offset_from_parent }),
9856 .address => try stderr.print(" ${d}[0x{x}]", .{ @intFromEnum(value.parent_payload.address), value.offset_from_parent }),
9857 .constant => try stderr.print(" <{f}, {f}>", .{
9858 isel.fmtType(value.parent_payload.constant.typeOf(zcu)),
9859 isel.fmtConstant(value.parent_payload.constant),
9860 }),
9861 }
9862 try stderr.print(" align({s})", .{@tagName(value.flags.alignment)});
9863 switch (value.flags.location_tag) {
9864 .large => try stderr.print(" size=0x{x} large", .{value.location_payload.large.size}),
9865 .small => {
9866 const loc = value.location_payload.small;
9867 try stderr.print(" size=0x{x}", .{loc.size});
9868 switch (loc.signedness) {
9869 .unsigned => {},
9870 .signed => try stderr.writeAll(" signed"),
9871 }
9872 if (loc.hint != .zr) try stderr.print(" hint={s}", .{@tagName(loc.hint)});
9873 if (loc.register != .zr) try stderr.print(" loc={s}", .{@tagName(loc.register)});
9874 },
9875 }
9876 try stderr.print(" refs={d}\n", .{value.refs});
9877
9878 var part_index = value.flags.parts_len_minus_one;
9879 if (part_index > 0) while (true) : (part_index -= 1) {
9880 roots.putAssumeCapacityNoClobber(
9881 @enumFromInt(@intFromEnum(value.parts) + part_index),
9882 root_entry.value + 1,
9883 );
9884 if (part_index == 0) break;
9885 };
9886 }
9887 try stderr.print("# End {s} Value Dump: {f}\n\n", .{ @typeName(Select), nav.fqn.fmt(ip) });
9888}
9889
9890fn hasRepeatedByteRepr(isel: *Select, constant: Constant) error{OutOfMemory}!?u8 {
9891 const zcu = isel.pt.zcu;
9892 const ty = constant.typeOf(zcu);
9893 const abi_size = std.math.cast(usize, ty.abiSize(zcu)) orelse return null;
9894 const byte_buffer = try zcu.gpa.alloc(u8, abi_size);
9895 defer zcu.gpa.free(byte_buffer);
9896 return if (try isel.writeToMemory(constant, byte_buffer) and
9897 std.mem.allEqual(u8, byte_buffer[1..], byte_buffer[0])) byte_buffer[0] else null;
9898}
9899
9900fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMemory}!bool {
9901 const zcu = isel.pt.zcu;
9902 const ip = &zcu.intern_pool;
9903 switch (ip.indexToKey(constant.toIntern())) {
9904 .int_type,
9905 .ptr_type,
9906 .array_type,
9907 .vector_type,
9908 .opt_type,
9909 .anyframe_type,
9910 .error_union_type,
9911 .simple_type,
9912 .struct_type,
9913 .tuple_type,
9914 .union_type,
9915 .opaque_type,
9916 .enum_type,
9917 .func_type,
9918 .error_set_type,
9919 .inferred_error_set_type,
9920
9921 .enum_literal,
9922 .empty_enum_value,
9923 .memoized_call,
9924 => unreachable, // not a runtime value
9925 .opt => |opt| {
9926 const child_size: usize = @intCast(ZigType.fromInterned(ip.indexToKey(opt.ty).opt_type).abiSize(zcu));
9927 switch (opt.val) {
9928 .none => if (!ZigType.fromInterned(opt.ty).optionalReprIsPayload(zcu)) {
9929 buffer[child_size] = @intFromBool(false);
9930 } else @memset(buffer[0..child_size], 0x00),
9931 else => |child_constant| {
9932 if (!try isel.writeToMemory(.fromInterned(child_constant), buffer[0..child_size])) return false;
9933 if (!ZigType.fromInterned(opt.ty).optionalReprIsPayload(zcu)) buffer[child_size] = @intFromBool(true);
9934 },
9935 }
9936 return true;
9937 },
9938 .aggregate => |aggregate| switch (ip.indexToKey(aggregate.ty)) {
9939 else => unreachable,
9940 .array_type => |array_type| {
9941 var elem_offset: usize = 0;
9942 const elem_size: usize = @intCast(ZigType.fromInterned(array_type.child).abiSize(zcu));
9943 const len_including_sentinel: usize = @intCast(array_type.lenIncludingSentinel());
9944 switch (aggregate.storage) {
9945 .bytes => |bytes| @memcpy(buffer[0..len_including_sentinel], bytes.toSlice(len_including_sentinel, ip)),
9946 .elems => |elems| for (elems) |elem| {
9947 if (!try isel.writeToMemory(.fromInterned(elem), buffer[elem_offset..][0..elem_size])) return false;
9948 elem_offset += elem_size;
9949 },
9950 .repeated_elem => |repeated_elem| for (0..len_including_sentinel) |_| {
9951 if (!try isel.writeToMemory(.fromInterned(repeated_elem), buffer[elem_offset..][0..elem_size])) return false;
9952 elem_offset += elem_size;
9953 },
9954 }
9955 return true;
9956 },
9957 .vector_type => {},
9958 .struct_type => {
9959 const loaded_struct = ip.loadStructType(aggregate.ty);
9960 switch (loaded_struct.layout) {
9961 .auto => {
9962 var field_offset: u64 = 0;
9963 var field_it = loaded_struct.iterateRuntimeOrder(ip);
9964 while (field_it.next()) |field_index| {
9965 if (loaded_struct.fieldIsComptime(ip, field_index)) continue;
9966 const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
9967 field_offset = field_ty.structFieldAlignment(
9968 loaded_struct.fieldAlign(ip, field_index),
9969 loaded_struct.layout,
9970 zcu,
9971 ).forward(field_offset);
9972 const field_size = field_ty.abiSize(zcu);
9973 if (!try isel.writeToMemory(.fromInterned(switch (aggregate.storage) {
9974 .bytes => unreachable,
9975 .elems => |elems| elems[field_index],
9976 .repeated_elem => |repeated_elem| repeated_elem,
9977 }), buffer[@intCast(field_offset)..][0..@intCast(field_size)])) return false;
9978 field_offset += field_size;
9979 }
9980 return true;
9981 },
9982 .@"extern", .@"packed" => {},
9983 }
9984 },
9985 .tuple_type => |tuple_type| {
9986 var field_offset: u64 = 0;
9987 for (tuple_type.types.get(ip), tuple_type.values.get(ip), 0..) |field_type, field_value, field_index| {
9988 if (field_value != .none) continue;
9989 const field_ty: ZigType = .fromInterned(field_type);
9990 field_offset = field_ty.abiAlignment(zcu).forward(field_offset);
9991 const field_size = field_ty.abiSize(zcu);
9992 if (!try isel.writeToMemory(.fromInterned(switch (aggregate.storage) {
9993 .bytes => unreachable,
9994 .elems => |elems| elems[field_index],
9995 .repeated_elem => |repeated_elem| repeated_elem,
9996 }), buffer[@intCast(field_offset)..][0..@intCast(field_size)])) return false;
9997 field_offset += field_size;
9998 }
9999 return true;
10000 },
10001 },
10002 else => {},
10003 }
10004 constant.writeToMemory(isel.pt, buffer) catch |err| switch (err) {
10005 error.OutOfMemory => return error.OutOfMemory,
10006 error.ReinterpretDeclRef, error.Unimplemented, error.IllDefinedMemoryLayout => return false,
10007 };
10008 return true;
10009}
10010
10011const TryAllocRegResult = union(enum) {
10012 allocated: Register.Alias,
10013 fill_candidate: Register.Alias,
10014 out_of_registers,
10015};
10016
10017fn tryAllocIntReg(isel: *Select) TryAllocRegResult {
10018 var failed_result: TryAllocRegResult = .out_of_registers;
10019 var ra: Register.Alias = .r0;
10020 while (true) : (ra = @enumFromInt(@intFromEnum(ra) + 1)) {
10021 if (ra == .r18) continue; // The Platform Register
10022 if (ra == Register.Alias.fp) continue;
10023 const live_vi = isel.live_registers.getPtr(ra);
10024 switch (live_vi.*) {
10025 _ => switch (failed_result) {
10026 .allocated => unreachable,
10027 .fill_candidate => {},
10028 .out_of_registers => failed_result = .{ .fill_candidate = ra },
10029 },
10030 .allocating => {},
10031 .free => {
10032 live_vi.* = .allocating;
10033 isel.saved_registers.insert(ra);
10034 return .{ .allocated = ra };
10035 },
10036 }
10037 if (ra == Register.Alias.lr) return failed_result;
10038 }
10039}
10040
10041fn allocIntReg(isel: *Select) !Register.Alias {
10042 switch (isel.tryAllocIntReg()) {
10043 .allocated => |ra| return ra,
10044 .fill_candidate => |ra| {
10045 assert(try isel.fillMemory(ra));
10046 const live_vi = isel.live_registers.getPtr(ra);
10047 assert(live_vi.* == .free);
10048 live_vi.* = .allocating;
10049 return ra;
10050 },
10051 .out_of_registers => return isel.fail("ran out of registers", .{}),
10052 }
10053}
10054
10055fn tryAllocVecReg(isel: *Select) TryAllocRegResult {
10056 var failed_result: TryAllocRegResult = .out_of_registers;
10057 var ra: Register.Alias = .v0;
10058 while (true) : (ra = @enumFromInt(@intFromEnum(ra) + 1)) {
10059 const live_vi = isel.live_registers.getPtr(ra);
10060 switch (live_vi.*) {
10061 _ => switch (failed_result) {
10062 .allocated => unreachable,
10063 .fill_candidate => {},
10064 .out_of_registers => failed_result = .{ .fill_candidate = ra },
10065 },
10066 .allocating => {},
10067 .free => {
10068 live_vi.* = .allocating;
10069 isel.saved_registers.insert(ra);
10070 return .{ .allocated = ra };
10071 },
10072 }
10073 if (ra == Register.Alias.v31) return failed_result;
10074 }
10075}
10076
10077fn allocVecReg(isel: *Select) !Register.Alias {
10078 switch (isel.tryAllocVecReg()) {
10079 .allocated => |ra| return ra,
10080 .fill_candidate => |ra| {
10081 assert(try isel.fillMemory(ra));
10082 return ra;
10083 },
10084 .out_of_registers => return isel.fail("ran out of registers", .{}),
10085 }
10086}
10087
10088const RegLock = struct {
10089 ra: Register.Alias,
10090 const empty: RegLock = .{ .ra = .zr };
10091 fn unlock(lock: RegLock, isel: *Select) void {
10092 switch (lock.ra) {
10093 else => |ra| isel.freeReg(ra),
10094 .zr => {},
10095 }
10096 }
10097};
10098fn lockReg(isel: *Select, ra: Register.Alias) RegLock {
10099 assert(ra != .zr);
10100 const live_vi = isel.live_registers.getPtr(ra);
10101 assert(live_vi.* == .free);
10102 live_vi.* = .allocating;
10103 return .{ .ra = ra };
10104}
10105fn tryLockReg(isel: *Select, ra: Register.Alias) RegLock {
10106 assert(ra != .zr);
10107 const live_vi = isel.live_registers.getPtr(ra);
10108 switch (live_vi.*) {
10109 _ => unreachable,
10110 .allocating => return .{ .ra = .zr },
10111 .free => {
10112 live_vi.* = .allocating;
10113 return .{ .ra = ra };
10114 },
10115 }
10116}
10117
10118fn freeReg(isel: *Select, ra: Register.Alias) void {
10119 assert(ra != .zr);
10120 const live_vi = isel.live_registers.getPtr(ra);
10121 assert(live_vi.* == .allocating);
10122 live_vi.* = .free;
10123}
10124
10125fn use(isel: *Select, air_ref: Air.Inst.Ref) !Value.Index {
10126 const zcu = isel.pt.zcu;
10127 const ip = &zcu.intern_pool;
10128 try isel.values.ensureUnusedCapacity(zcu.gpa, 1);
10129 const vi, const ty = if (air_ref.toIndex()) |air_inst_index| vi_ty: {
10130 const live_gop = try isel.live_values.getOrPut(zcu.gpa, air_inst_index);
10131 if (live_gop.found_existing) return live_gop.value_ptr.*;
10132 const ty = isel.air.typeOf(air_ref, ip);
10133 const vi = isel.initValue(ty);
10134 tracking_log.debug("${d} <- %{d}", .{
10135 @intFromEnum(vi),
10136 @intFromEnum(air_inst_index),
10137 });
10138 live_gop.value_ptr.* = vi.ref(isel);
10139 break :vi_ty .{ vi, ty };
10140 } else vi_ty: {
10141 const constant: Constant = .fromInterned(air_ref.toInterned().?);
10142 const ty = constant.typeOf(zcu);
10143 const vi = isel.initValue(ty);
10144 tracking_log.debug("${d} <- <{f}, {f}>", .{
10145 @intFromEnum(vi),
10146 isel.fmtType(ty),
10147 isel.fmtConstant(constant),
10148 });
10149 vi.setParent(isel, .{ .constant = constant });
10150 break :vi_ty .{ vi, ty };
10151 };
10152 if (ty.isAbiInt(zcu)) {
10153 const int_info = ty.intInfo(zcu);
10154 if (int_info.bits <= 16) vi.setSignedness(isel, int_info.signedness);
10155 } else if (vi.size(isel) <= 16 and
10156 CallAbiIterator.homogeneousAggregateBaseType(zcu, ty.toIntern()) != null) vi.setIsVector(isel);
10157 return vi;
10158}
10159
10160fn fill(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, CodegenFail }!bool {
10161 switch (dst_ra) {
10162 else => {},
10163 Register.Alias.fp, .zr, .sp, .pc, .fpcr, .fpsr, .ffr => return false,
10164 }
10165 const dst_live_vi = isel.live_registers.getPtr(dst_ra);
10166 const dst_vi = switch (dst_live_vi.*) {
10167 _ => |dst_vi| dst_vi,
10168 .allocating => return false,
10169 .free => return true,
10170 };
10171 const src_ra = src_ra: {
10172 if (dst_vi.hint(isel)) |hint_ra| {
10173 assert(dst_live_vi.* == dst_vi);
10174 dst_live_vi.* = .allocating;
10175 defer dst_live_vi.* = dst_vi;
10176 if (try isel.fill(hint_ra)) {
10177 isel.saved_registers.insert(hint_ra);
10178 break :src_ra hint_ra;
10179 }
10180 }
10181 switch (if (dst_vi.isVector(isel)) isel.tryAllocVecReg() else isel.tryAllocIntReg()) {
10182 .allocated => |ra| break :src_ra ra,
10183 .fill_candidate, .out_of_registers => return isel.fillMemory(dst_ra),
10184 }
10185 };
10186 try dst_vi.liveIn(isel, src_ra, comptime &.initFill(.free));
10187 const src_live_vi = isel.live_registers.getPtr(src_ra);
10188 assert(src_live_vi.* == .allocating);
10189 src_live_vi.* = dst_vi;
10190 return true;
10191}
10192
10193fn fillMemory(isel: *Select, dst_ra: Register.Alias) error{ OutOfMemory, CodegenFail }!bool {
10194 const dst_live_vi = isel.live_registers.getPtr(dst_ra);
10195 const dst_vi = switch (dst_live_vi.*) {
10196 _ => |dst_vi| dst_vi,
10197 .allocating => return false,
10198 .free => return true,
10199 };
10200 const dst_vi_ra = &dst_vi.get(isel).location_payload.small.register;
10201 assert(dst_vi_ra.* == dst_ra);
10202 const base_ra = if (dst_ra.isVector()) try isel.allocIntReg() else dst_ra;
10203 defer if (base_ra != dst_ra) isel.freeReg(base_ra);
10204 try isel.emit(switch (dst_vi.size(isel)) {
10205 else => unreachable,
10206 1 => if (dst_ra.isVector())
10207 .ldr(dst_ra.b(), .{ .base = base_ra.x() })
10208 else switch (dst_vi.signedness(isel)) {
10209 .signed => .ldrsb(dst_ra.w(), .{ .base = base_ra.x() }),
10210 .unsigned => .ldrb(dst_ra.w(), .{ .base = base_ra.x() }),
10211 },
10212 2 => if (dst_ra.isVector())
10213 .ldr(dst_ra.h(), .{ .base = base_ra.x() })
10214 else switch (dst_vi.signedness(isel)) {
10215 .signed => .ldrsh(dst_ra.w(), .{ .base = base_ra.x() }),
10216 .unsigned => .ldrh(dst_ra.w(), .{ .base = base_ra.x() }),
10217 },
10218 4 => .ldr(if (dst_ra.isVector()) dst_ra.s() else dst_ra.w(), .{ .base = base_ra.x() }),
10219 8 => .ldr(if (dst_ra.isVector()) dst_ra.d() else dst_ra.x(), .{ .base = base_ra.x() }),
10220 16 => .ldr(dst_ra.q(), .{ .base = base_ra.x() }),
10221 });
10222 dst_vi_ra.* = .zr;
10223 try dst_vi.address(isel, 0, base_ra);
10224 dst_live_vi.* = .free;
10225 return true;
10226}
10227
10228/// Merges possibly differing value tracking into a consistent state.
10229///
10230/// At a conditional branch, if a value is expected in the same register on both
10231/// paths, or only expected in a register on only one path, tracking is updated:
10232///
10233/// $0 -> r0 // final state is now consistent with both paths
10234/// b.cond else
10235/// then:
10236/// $0 -> r0 // updated if not already consistent with else
10237/// ...
10238/// b end
10239/// else:
10240/// $0 -> r0
10241/// ...
10242/// end:
10243///
10244/// At a conditional branch, if a value is expected in different registers on
10245/// each path, mov instructions are emitted:
10246///
10247/// $0 -> r0 // final state is now consistent with both paths
10248/// b.cond else
10249/// then:
10250/// $0 -> r0 // updated to be consistent with else
10251/// mov x1, x0 // emitted to merge the inconsistent states
10252/// $0 -> r1
10253/// ...
10254/// b end
10255/// else:
10256/// $0 -> r0
10257/// ...
10258/// end:
10259///
10260/// At a loop, a value that is expected in a register at the repeats is updated:
10261///
10262/// $0 -> r0 // final state is now consistent with all paths
10263/// loop:
10264/// $0 -> r0 // updated to be consistent with the repeats
10265/// ...
10266/// $0 -> r0
10267/// b.cond loop
10268/// ...
10269/// $0 -> r0
10270/// b loop
10271///
10272/// At a loop, a value that is expected in a register at the top is filled:
10273///
10274/// $0 -> [sp, #A] // final state is now consistent with all paths
10275/// loop:
10276/// $0 -> [sp, #A] // updated to be consistent with the repeats
10277/// ldr x0, [sp, #A] // emitted to merge the inconsistent states
10278/// $0 -> r0
10279/// ...
10280/// $0 -> [sp, #A]
10281/// b.cond loop
10282/// ...
10283/// $0 -> [sp, #A]
10284/// b loop
10285///
10286/// At a loop, if a value that is expected in different registers on each path,
10287/// mov instructions are emitted:
10288///
10289/// $0 -> r0 // final state is now consistent with all paths
10290/// loop:
10291/// $0 -> r0 // updated to be consistent with the repeats
10292/// mov x1, x0 // emitted to merge the inconsistent states
10293/// $0 -> r1
10294/// ...
10295/// $0 -> r0
10296/// b.cond loop
10297/// ...
10298/// $0 -> r0
10299/// b loop
10300fn merge(
10301 isel: *Select,
10302 expected_live_registers: *const LiveRegisters,
10303 comptime opts: struct { fill_extra: bool = false },
10304) !void {
10305 var live_reg_it = isel.live_registers.iterator();
10306 while (live_reg_it.next()) |live_reg_entry| {
10307 const ra = live_reg_entry.key;
10308 const actual_vi = live_reg_entry.value;
10309 const expected_vi = expected_live_registers.get(ra);
10310 switch (expected_vi) {
10311 else => switch (actual_vi.*) {
10312 _ => {},
10313 .allocating => unreachable,
10314 .free => actual_vi.* = .allocating,
10315 },
10316 .free => {},
10317 }
10318 }
10319 live_reg_it = isel.live_registers.iterator();
10320 while (live_reg_it.next()) |live_reg_entry| {
10321 const ra = live_reg_entry.key;
10322 const actual_vi = live_reg_entry.value;
10323 const expected_vi = expected_live_registers.get(ra);
10324 switch (expected_vi) {
10325 _ => {
10326 switch (actual_vi.*) {
10327 _ => _ = if (opts.fill_extra) {
10328 assert(try isel.fillMemory(ra));
10329 assert(actual_vi.* == .free);
10330 },
10331 .allocating => actual_vi.* = .free,
10332 .free => unreachable,
10333 }
10334 try expected_vi.liveIn(isel, ra, expected_live_registers);
10335 },
10336 .allocating => if (if (opts.fill_extra) try isel.fillMemory(ra) else try isel.fill(ra)) {
10337 assert(actual_vi.* == .free);
10338 actual_vi.* = .allocating;
10339 },
10340 .free => if (opts.fill_extra) assert(try isel.fillMemory(ra) and actual_vi.* == .free),
10341 }
10342 }
10343 live_reg_it = isel.live_registers.iterator();
10344 while (live_reg_it.next()) |live_reg_entry| {
10345 const ra = live_reg_entry.key;
10346 const actual_vi = live_reg_entry.value;
10347 const expected_vi = expected_live_registers.get(ra);
10348 switch (expected_vi) {
10349 _ => {
10350 assert(actual_vi.* == .allocating and expected_vi.register(isel) == ra);
10351 actual_vi.* = expected_vi;
10352 },
10353 .allocating => assert(actual_vi.* == .allocating),
10354 .free => if (opts.fill_extra) assert(actual_vi.* == .free),
10355 }
10356 }
10357}
10358
10359const call = struct {
10360 const param_reg: Value.Index = @enumFromInt(@intFromEnum(Value.Index.allocating) - 2);
10361 const callee_clobbered_reg: Value.Index = @enumFromInt(@intFromEnum(Value.Index.allocating) - 1);
10362 const caller_saved_regs: LiveRegisters = .init(.{
10363 .r0 = param_reg,
10364 .r1 = param_reg,
10365 .r2 = param_reg,
10366 .r3 = param_reg,
10367 .r4 = param_reg,
10368 .r5 = param_reg,
10369 .r6 = param_reg,
10370 .r7 = param_reg,
10371 .r8 = param_reg,
10372 .r9 = callee_clobbered_reg,
10373 .r10 = callee_clobbered_reg,
10374 .r11 = callee_clobbered_reg,
10375 .r12 = callee_clobbered_reg,
10376 .r13 = callee_clobbered_reg,
10377 .r14 = callee_clobbered_reg,
10378 .r15 = callee_clobbered_reg,
10379 .r16 = callee_clobbered_reg,
10380 .r17 = callee_clobbered_reg,
10381 .r18 = callee_clobbered_reg,
10382 .r19 = .free,
10383 .r20 = .free,
10384 .r21 = .free,
10385 .r22 = .free,
10386 .r23 = .free,
10387 .r24 = .free,
10388 .r25 = .free,
10389 .r26 = .free,
10390 .r27 = .free,
10391 .r28 = .free,
10392 .r29 = .free,
10393 .r30 = callee_clobbered_reg,
10394 .zr = .free,
10395 .sp = .free,
10396
10397 .pc = .free,
10398
10399 .v0 = param_reg,
10400 .v1 = param_reg,
10401 .v2 = param_reg,
10402 .v3 = param_reg,
10403 .v4 = param_reg,
10404 .v5 = param_reg,
10405 .v6 = param_reg,
10406 .v7 = param_reg,
10407 .v8 = .free,
10408 .v9 = .free,
10409 .v10 = .free,
10410 .v11 = .free,
10411 .v12 = .free,
10412 .v13 = .free,
10413 .v14 = .free,
10414 .v15 = .free,
10415 .v16 = callee_clobbered_reg,
10416 .v17 = callee_clobbered_reg,
10417 .v18 = callee_clobbered_reg,
10418 .v19 = callee_clobbered_reg,
10419 .v20 = callee_clobbered_reg,
10420 .v21 = callee_clobbered_reg,
10421 .v22 = callee_clobbered_reg,
10422 .v23 = callee_clobbered_reg,
10423 .v24 = callee_clobbered_reg,
10424 .v25 = callee_clobbered_reg,
10425 .v26 = callee_clobbered_reg,
10426 .v27 = callee_clobbered_reg,
10427 .v28 = callee_clobbered_reg,
10428 .v29 = callee_clobbered_reg,
10429 .v30 = callee_clobbered_reg,
10430 .v31 = callee_clobbered_reg,
10431
10432 .fpcr = .free,
10433 .fpsr = .free,
10434
10435 .p0 = callee_clobbered_reg,
10436 .p1 = callee_clobbered_reg,
10437 .p2 = callee_clobbered_reg,
10438 .p3 = callee_clobbered_reg,
10439 .p4 = callee_clobbered_reg,
10440 .p5 = callee_clobbered_reg,
10441 .p6 = callee_clobbered_reg,
10442 .p7 = callee_clobbered_reg,
10443 .p8 = callee_clobbered_reg,
10444 .p9 = callee_clobbered_reg,
10445 .p10 = callee_clobbered_reg,
10446 .p11 = callee_clobbered_reg,
10447 .p12 = callee_clobbered_reg,
10448 .p13 = callee_clobbered_reg,
10449 .p14 = callee_clobbered_reg,
10450 .p15 = callee_clobbered_reg,
10451
10452 .ffr = .free,
10453 });
10454 fn prepareReturn(isel: *Select) !void {
10455 var live_reg_it = isel.live_registers.iterator();
10456 while (live_reg_it.next()) |live_reg_entry| switch (caller_saved_regs.get(live_reg_entry.key)) {
10457 else => unreachable,
10458 param_reg, callee_clobbered_reg => switch (live_reg_entry.value.*) {
10459 _ => {},
10460 .allocating => unreachable,
10461 .free => live_reg_entry.value.* = .allocating,
10462 },
10463 .free => {},
10464 };
10465 }
10466 fn returnFill(isel: *Select, ra: Register.Alias) !void {
10467 const live_vi = isel.live_registers.getPtr(ra);
10468 if (try isel.fill(ra)) {
10469 assert(live_vi.* == .free);
10470 live_vi.* = .allocating;
10471 }
10472 assert(live_vi.* == .allocating);
10473 }
10474 fn returnLiveIn(isel: *Select, vi: Value.Index, ra: Register.Alias) !void {
10475 try vi.defLiveIn(isel, ra, &caller_saved_regs);
10476 }
10477 fn finishReturn(isel: *Select) !void {
10478 var live_reg_it = isel.live_registers.iterator();
10479 while (live_reg_it.next()) |live_reg_entry| {
10480 switch (live_reg_entry.value.*) {
10481 _ => |live_vi| switch (live_vi.size(isel)) {
10482 else => unreachable,
10483 1, 2, 4, 8 => {},
10484 16 => {
10485 assert(try isel.fillMemory(live_reg_entry.key));
10486 assert(live_reg_entry.value.* == .free);
10487 switch (caller_saved_regs.get(live_reg_entry.key)) {
10488 else => unreachable,
10489 param_reg, callee_clobbered_reg => live_reg_entry.value.* = .allocating,
10490 .free => {},
10491 }
10492 continue;
10493 },
10494 },
10495 .allocating, .free => {},
10496 }
10497 switch (caller_saved_regs.get(live_reg_entry.key)) {
10498 else => unreachable,
10499 param_reg, callee_clobbered_reg => switch (live_reg_entry.value.*) {
10500 _ => {
10501 assert(try isel.fill(live_reg_entry.key));
10502 assert(live_reg_entry.value.* == .free);
10503 live_reg_entry.value.* = .allocating;
10504 },
10505 .allocating => {},
10506 .free => unreachable,
10507 },
10508 .free => {},
10509 }
10510 }
10511 }
10512 fn prepareCallee(isel: *Select) !void {
10513 var live_reg_it = isel.live_registers.iterator();
10514 while (live_reg_it.next()) |live_reg_entry| switch (caller_saved_regs.get(live_reg_entry.key)) {
10515 else => unreachable,
10516 param_reg => assert(live_reg_entry.value.* == .allocating),
10517 callee_clobbered_reg => isel.freeReg(live_reg_entry.key),
10518 .free => {},
10519 };
10520 }
10521 fn finishCallee(_: *Select) !void {}
10522 fn prepareParams(_: *Select) !void {}
10523 fn paramLiveOut(isel: *Select, vi: Value.Index, ra: Register.Alias) !void {
10524 isel.freeReg(ra);
10525 try vi.liveOut(isel, ra);
10526 const live_vi = isel.live_registers.getPtr(ra);
10527 if (live_vi.* == .free) live_vi.* = .allocating;
10528 }
10529 fn paramAddress(isel: *Select, vi: Value.Index, ra: Register.Alias) !void {
10530 isel.freeReg(ra);
10531 try vi.address(isel, 0, ra);
10532 const live_vi = isel.live_registers.getPtr(ra);
10533 if (live_vi.* == .free) live_vi.* = .allocating;
10534 }
10535 fn finishParams(isel: *Select) !void {
10536 var live_reg_it = isel.live_registers.iterator();
10537 while (live_reg_it.next()) |live_reg_entry| switch (caller_saved_regs.get(live_reg_entry.key)) {
10538 else => unreachable,
10539 param_reg => switch (live_reg_entry.value.*) {
10540 _ => {},
10541 .allocating => live_reg_entry.value.* = .free,
10542 .free => unreachable,
10543 },
10544 callee_clobbered_reg, .free => {},
10545 };
10546 }
10547};
10548
10549pub const CallAbiIterator = struct {
10550 /// Next General-purpose Register Number
10551 ngrn: Register.Alias,
10552 /// Next SIMD and Floating-point Register Number
10553 nsrn: Register.Alias,
10554 /// next stacked argument address
10555 nsaa: u24,
10556
10557 pub const ngrn_start: Register.Alias = .r0;
10558 pub const ngrn_end: Register.Alias = .r8;
10559 pub const nsrn_start: Register.Alias = .v0;
10560 pub const nsrn_end: Register.Alias = .v8;
10561 pub const nsaa_start: u42 = 0;
10562
10563 pub const init: CallAbiIterator = .{
10564 // A.1
10565 .ngrn = ngrn_start,
10566 // A.2
10567 .nsrn = nsrn_start,
10568 // A.3
10569 .nsaa = nsaa_start,
10570 };
10571
10572 pub fn param(it: *CallAbiIterator, isel: *Select, ty: ZigType) !?Value.Index {
10573 const zcu = isel.pt.zcu;
10574 const ip = &zcu.intern_pool;
10575
10576 if (ty.isNoReturn(zcu) or !ty.hasRuntimeBitsIgnoreComptime(zcu)) return null;
10577 try isel.values.ensureUnusedCapacity(zcu.gpa, Value.max_parts);
10578 const wip_vi = isel.initValue(ty);
10579 type_key: switch (ip.indexToKey(ty.toIntern())) {
10580 else => return isel.fail("CallAbiIterator.param({f})", .{isel.fmtType(ty)}),
10581 .int_type => |int_type| switch (int_type.bits) {
10582 0 => unreachable,
10583 1...16 => {
10584 wip_vi.setSignedness(isel, int_type.signedness);
10585 // C.7
10586 it.integer(isel, wip_vi);
10587 },
10588 // C.7
10589 17...64 => it.integer(isel, wip_vi),
10590 // C.9
10591 65...128 => it.integers(isel, wip_vi, @splat(@divExact(wip_vi.size(isel), 2))),
10592 else => it.indirect(isel, wip_vi),
10593 },
10594 .array_type => switch (wip_vi.size(isel)) {
10595 0 => unreachable,
10596 1...8 => it.integer(isel, wip_vi),
10597 9...16 => |size| it.integers(isel, wip_vi, .{ 8, size - 8 }),
10598 else => it.indirect(isel, wip_vi),
10599 },
10600 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
10601 .one, .many, .c => continue :type_key .{ .int_type = .{
10602 .signedness = .unsigned,
10603 .bits = 64,
10604 } },
10605 .slice => it.integers(isel, wip_vi, @splat(8)),
10606 },
10607 .opt_type => |child_type| if (ty.optionalReprIsPayload(zcu))
10608 continue :type_key ip.indexToKey(child_type)
10609 else switch (ZigType.fromInterned(child_type).abiSize(zcu)) {
10610 0 => continue :type_key .{ .simple_type = .bool },
10611 1...7 => it.integer(isel, wip_vi),
10612 8...15 => |child_size| it.integers(isel, wip_vi, .{ 8, child_size - 7 }),
10613 else => return isel.fail("CallAbiIterator.param({f})", .{isel.fmtType(ty)}),
10614 },
10615 .anyframe_type => unreachable,
10616 .error_union_type => |error_union_type| switch (wip_vi.size(isel)) {
10617 0 => unreachable,
10618 1...8 => it.integer(isel, wip_vi),
10619 9...16 => {
10620 var sizes: [2]u64 = @splat(0);
10621 const payload_ty: ZigType = .fromInterned(error_union_type.payload_type);
10622 {
10623 const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
10624 const offset = codegen.errUnionErrorOffset(payload_ty, zcu);
10625 const size = error_set_ty.abiSize(zcu);
10626 const end = offset % 8 + size;
10627 const part_index: usize = @intCast(offset / 8);
10628 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
10629 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
10630 }
10631 {
10632 const offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
10633 const size = payload_ty.abiSize(zcu);
10634 const end = offset % 8 + size;
10635 const part_index: usize = @intCast(offset / 8);
10636 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
10637 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
10638 }
10639 it.integers(isel, wip_vi, sizes);
10640 },
10641 else => it.indirect(isel, wip_vi),
10642 },
10643 .simple_type => |simple_type| switch (simple_type) {
10644 .f16, .f32, .f64, .f128, .c_longdouble => it.vector(isel, wip_vi),
10645 .f80 => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 80 } },
10646 .usize,
10647 .isize,
10648 .c_char,
10649 .c_short,
10650 .c_ushort,
10651 .c_int,
10652 .c_uint,
10653 .c_long,
10654 .c_ulong,
10655 .c_longlong,
10656 .c_ulonglong,
10657 => continue :type_key .{ .int_type = ty.intInfo(zcu) },
10658 // B.1
10659 .anyopaque => it.indirect(isel, wip_vi),
10660 .bool => continue :type_key .{ .int_type = .{ .signedness = .unsigned, .bits = 1 } },
10661 .anyerror => continue :type_key .{ .int_type = .{
10662 .signedness = .unsigned,
10663 .bits = zcu.errorSetBits(),
10664 } },
10665 .void,
10666 .type,
10667 .comptime_int,
10668 .comptime_float,
10669 .noreturn,
10670 .null,
10671 .undefined,
10672 .enum_literal,
10673 .adhoc_inferred_error_set,
10674 .generic_poison,
10675 => unreachable,
10676 },
10677 .struct_type => {
10678 const size = wip_vi.size(isel);
10679 const loaded_struct = ip.loadStructType(ty.toIntern());
10680 if (size <= 16 * 4) homogeneous_aggregate: {
10681 const fdt = homogeneousStructBaseType(zcu, &loaded_struct) orelse break :homogeneous_aggregate;
10682 const parts_len = @shrExact(size, fdt.log2Size());
10683 if (parts_len > 4) break :homogeneous_aggregate;
10684 it.vectors(isel, wip_vi, fdt, @intCast(parts_len));
10685 break :type_key;
10686 }
10687 switch (size) {
10688 0 => unreachable,
10689 1...8 => it.integer(isel, wip_vi),
10690 9...16 => {
10691 var part_offset: u64 = 0;
10692 var part_sizes: [2]u64 = undefined;
10693 var parts_len: Value.PartsLen = 0;
10694 var next_field_end: u64 = 0;
10695 var field_it = loaded_struct.iterateRuntimeOrder(ip);
10696 while (part_offset < size) {
10697 const field_end = next_field_end;
10698 const next_field_begin = if (field_it.next()) |field_index| next_field_begin: {
10699 const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
10700 const next_field_begin = switch (loaded_struct.fieldAlign(ip, field_index)) {
10701 .none => field_ty.abiAlignment(zcu),
10702 else => |field_align| field_align,
10703 }.forward(field_end);
10704 next_field_end = next_field_begin + field_ty.abiSize(zcu);
10705 break :next_field_begin next_field_begin;
10706 } else std.mem.alignForward(u64, size, 8);
10707 while (next_field_begin - part_offset >= 8) {
10708 const part_size = field_end - part_offset;
10709 part_sizes[parts_len] = part_size;
10710 assert(part_offset + part_size <= size);
10711 parts_len += 1;
10712 part_offset = next_field_begin;
10713 }
10714 }
10715 assert(parts_len == part_sizes.len);
10716 it.integers(isel, wip_vi, part_sizes);
10717 },
10718 else => it.indirect(isel, wip_vi),
10719 }
10720 },
10721 .tuple_type => |tuple_type| {
10722 const size = wip_vi.size(isel);
10723 if (size <= 16 * 4) homogeneous_aggregate: {
10724 const fdt = homogeneousTupleBaseType(zcu, tuple_type) orelse break :homogeneous_aggregate;
10725 const parts_len = @shrExact(size, fdt.log2Size());
10726 if (parts_len > 4) break :homogeneous_aggregate;
10727 it.vectors(isel, wip_vi, fdt, @intCast(parts_len));
10728 break :type_key;
10729 }
10730 switch (size) {
10731 0 => unreachable,
10732 1...8 => it.integer(isel, wip_vi),
10733 9...16 => {
10734 var part_offset: u64 = 0;
10735 var part_sizes: [2]u64 = undefined;
10736 var parts_len: Value.PartsLen = 0;
10737 var next_field_end: u64 = 0;
10738 var field_index: usize = 0;
10739 while (part_offset < size) {
10740 const field_end = next_field_end;
10741 const next_field_begin = while (field_index < tuple_type.types.len) {
10742 defer field_index += 1;
10743 if (tuple_type.values.get(ip)[field_index] != .none) continue;
10744 const field_ty: ZigType = .fromInterned(tuple_type.types.get(ip)[field_index]);
10745 const next_field_begin = field_ty.abiAlignment(zcu).forward(field_end);
10746 next_field_end = next_field_begin + field_ty.abiSize(zcu);
10747 break next_field_begin;
10748 } else std.mem.alignForward(u64, size, 8);
10749 while (next_field_begin - part_offset >= 8) {
10750 const part_size = @min(field_end - part_offset, 8);
10751 part_sizes[parts_len] = part_size;
10752 assert(part_offset + part_size <= size);
10753 parts_len += 1;
10754 part_offset += part_size;
10755 if (part_offset >= field_end) part_offset = next_field_begin;
10756 }
10757 }
10758 assert(parts_len == part_sizes.len);
10759 it.integers(isel, wip_vi, part_sizes);
10760 },
10761 else => it.indirect(isel, wip_vi),
10762 }
10763 },
10764 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
10765 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
10766 .error_set_type,
10767 .inferred_error_set_type,
10768 => continue :type_key .{ .simple_type = .anyerror },
10769 .undef,
10770 .simple_value,
10771 .variable,
10772 .@"extern",
10773 .func,
10774 .int,
10775 .err,
10776 .error_union,
10777 .enum_literal,
10778 .enum_tag,
10779 .empty_enum_value,
10780 .float,
10781 .ptr,
10782 .slice,
10783 .opt,
10784 .aggregate,
10785 .un,
10786 .memoized_call,
10787 => unreachable, // values, not types
10788 }
10789 return wip_vi.ref(isel);
10790 }
10791
10792 pub fn ret(it: *CallAbiIterator, isel: *Select, ty: ZigType) !?Value.Index {
10793 const wip_vi = try it.param(isel, ty) orelse return null;
10794 switch (wip_vi.parent(isel)) {
10795 .unallocated, .stack_slot => {},
10796 .value, .constant => unreachable,
10797 .address => |address_vi| {
10798 assert(address_vi.hint(isel) == ngrn_start);
10799 address_vi.setHint(isel, ngrn_end);
10800 },
10801 }
10802 return wip_vi;
10803 }
10804
10805 pub const FundamentalDataType = enum {
10806 half,
10807 single,
10808 double,
10809 quad,
10810 vector64,
10811 vector128,
10812 fn log2Size(fdt: FundamentalDataType) u3 {
10813 return switch (fdt) {
10814 .half => 1,
10815 .single => 2,
10816 .double, .vector64 => 3,
10817 .quad, .vector128 => 4,
10818 };
10819 }
10820 fn size(fdt: FundamentalDataType) u64 {
10821 return @as(u64, 1) << fdt.log2Size();
10822 }
10823 };
10824 fn homogeneousAggregateBaseType(zcu: *Zcu, initial_ty: InternPool.Index) ?FundamentalDataType {
10825 const ip = &zcu.intern_pool;
10826 var ty = initial_ty;
10827 return type_key: switch (ip.indexToKey(ty)) {
10828 else => null,
10829 .array_type => |array_type| {
10830 ty = array_type.child;
10831 continue :type_key ip.indexToKey(ty);
10832 },
10833 .vector_type => switch (ZigType.fromInterned(ty).abiSize(zcu)) {
10834 else => null,
10835 8 => .vector64,
10836 16 => .vector128,
10837 },
10838 .simple_type => |simple_type| switch (simple_type) {
10839 .f16 => .half,
10840 .f32 => .single,
10841 .f64 => .double,
10842 .f128 => .quad,
10843 .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble)) {
10844 else => unreachable,
10845 16 => .half,
10846 32 => .single,
10847 64 => .double,
10848 80 => null,
10849 128 => .quad,
10850 },
10851 else => null,
10852 },
10853 .struct_type => homogeneousStructBaseType(zcu, &ip.loadStructType(ty)),
10854 .tuple_type => |tuple_type| homogeneousTupleBaseType(zcu, tuple_type),
10855 };
10856 }
10857 fn homogeneousStructBaseType(zcu: *Zcu, loaded_struct: *const InternPool.LoadedStructType) ?FundamentalDataType {
10858 const ip = &zcu.intern_pool;
10859 var common_fdt: ?FundamentalDataType = null;
10860 for (0.., loaded_struct.field_types.get(ip)) |field_index, field_ty| {
10861 if (loaded_struct.fieldIsComptime(ip, field_index)) continue;
10862 if (loaded_struct.fieldAlign(ip, field_index) != .none) return null;
10863 if (!ZigType.fromInterned(field_ty).hasRuntimeBits(zcu)) continue;
10864 const fdt = homogeneousAggregateBaseType(zcu, field_ty);
10865 if (common_fdt == null) common_fdt = fdt else if (fdt != common_fdt) return null;
10866 }
10867 return common_fdt;
10868 }
10869 fn homogeneousTupleBaseType(zcu: *Zcu, tuple_type: InternPool.Key.TupleType) ?FundamentalDataType {
10870 const ip = &zcu.intern_pool;
10871 var common_fdt: ?FundamentalDataType = null;
10872 for (tuple_type.values.get(ip), tuple_type.types.get(ip)) |field_val, field_ty| {
10873 if (field_val != .none) continue;
10874 const fdt = homogeneousAggregateBaseType(zcu, field_ty);
10875 if (common_fdt == null) common_fdt = fdt else if (fdt != common_fdt) return null;
10876 }
10877 return common_fdt;
10878 }
10879
10880 const Spec = struct {
10881 offset: u64,
10882 size: u64,
10883 };
10884
10885 fn stack(it: *CallAbiIterator, isel: *Select, wip_vi: Value.Index) void {
10886 // C.12
10887 it.nsaa = @intCast(wip_vi.alignment(isel).forward(it.nsaa));
10888 const parent_vi = switch (wip_vi.parent(isel)) {
10889 .unallocated, .stack_slot => wip_vi,
10890 .address, .constant => unreachable,
10891 .value => |parent_vi| parent_vi,
10892 };
10893 switch (parent_vi.parent(isel)) {
10894 .unallocated => parent_vi.setParent(isel, .{ .stack_slot = .{
10895 .base = .sp,
10896 .offset = it.nsaa,
10897 } }),
10898 .stack_slot => {},
10899 .address, .value, .constant => unreachable,
10900 }
10901 it.nsaa += @intCast(wip_vi.size(isel));
10902 }
10903
10904 fn integer(it: *CallAbiIterator, isel: *Select, wip_vi: Value.Index) void {
10905 assert(wip_vi.size(isel) <= 8);
10906 const natural_alignment = wip_vi.alignment(isel);
10907 assert(natural_alignment.order(.@"16").compare(.lte));
10908 wip_vi.setAlignment(isel, natural_alignment.maxStrict(.@"8"));
10909 if (it.ngrn == ngrn_end) return it.stack(isel, wip_vi);
10910 wip_vi.setHint(isel, it.ngrn);
10911 it.ngrn = @enumFromInt(@intFromEnum(it.ngrn) + 1);
10912 }
10913
10914 fn integers(it: *CallAbiIterator, isel: *Select, wip_vi: Value.Index, part_sizes: [2]u64) void {
10915 assert(wip_vi.size(isel) <= 16);
10916 const natural_alignment = wip_vi.alignment(isel);
10917 assert(natural_alignment.order(.@"16").compare(.lte));
10918 wip_vi.setAlignment(isel, natural_alignment.maxStrict(.@"8"));
10919 // C.8
10920 if (natural_alignment == .@"16") it.ngrn = @enumFromInt(std.mem.alignForward(
10921 @typeInfo(Register.Alias).@"enum".tag_type,
10922 @intFromEnum(it.ngrn),
10923 2,
10924 ));
10925 if (it.ngrn == ngrn_end) return it.stack(isel, wip_vi);
10926 wip_vi.setParts(isel, part_sizes.len);
10927 for (0.., part_sizes) |part_index, part_size|
10928 it.integer(isel, wip_vi.addPart(isel, 8 * part_index, part_size));
10929 }
10930
10931 fn vector(it: *CallAbiIterator, isel: *Select, wip_vi: Value.Index) void {
10932 assert(wip_vi.size(isel) <= 16);
10933 const natural_alignment = wip_vi.alignment(isel);
10934 assert(natural_alignment.order(.@"16").compare(.lte));
10935 wip_vi.setAlignment(isel, natural_alignment.maxStrict(.@"8"));
10936 wip_vi.setIsVector(isel);
10937 if (it.nsrn == nsrn_end) return it.stack(isel, wip_vi);
10938 wip_vi.setHint(isel, it.nsrn);
10939 it.nsrn = @enumFromInt(@intFromEnum(it.nsrn) + 1);
10940 }
10941
10942 fn vectors(
10943 it: *CallAbiIterator,
10944 isel: *Select,
10945 wip_vi: Value.Index,
10946 fdt: FundamentalDataType,
10947 parts_len: Value.PartsLen,
10948 ) void {
10949 const fdt_log2_size = fdt.log2Size();
10950 assert(wip_vi.size(isel) == @shlExact(@as(u9, parts_len), fdt_log2_size));
10951 const natural_alignment = wip_vi.alignment(isel);
10952 assert(natural_alignment.order(.@"16").compare(.lte));
10953 wip_vi.setAlignment(isel, natural_alignment.maxStrict(.@"8"));
10954 if (@intFromEnum(it.nsrn) > @intFromEnum(nsrn_end) - parts_len) return it.stack(isel, wip_vi);
10955 if (parts_len == 1) return it.vector(isel, wip_vi);
10956 wip_vi.setParts(isel, parts_len);
10957 const fdt_size = @as(u64, 1) << fdt_log2_size;
10958 for (0..parts_len) |part_index|
10959 it.vector(isel, wip_vi.addPart(isel, part_index << fdt_log2_size, fdt_size));
10960 }
10961
10962 fn indirect(it: *CallAbiIterator, isel: *Select, wip_vi: Value.Index) void {
10963 const wip_address_vi = isel.initValue(.usize);
10964 wip_vi.setParent(isel, .{ .address = wip_address_vi });
10965 it.integer(isel, wip_address_vi);
10966 }
10967};
10968
10969const Air = @import("../../Air.zig");
10970const assert = std.debug.assert;
10971const codegen = @import("../../codegen.zig");
10972const Constant = @import("../../Value.zig");
10973const InternPool = @import("../../InternPool.zig");
10974const Package = @import("../../Package.zig");
10975const Register = codegen.aarch64.encoding.Register;
10976const Select = @This();
10977const std = @import("std");
10978const tracking_log = std.log.scoped(.tracking);
10979const wip_mir_log = std.log.scoped(.@"wip-mir");
10980const Zcu = @import("../../Zcu.zig");
10981const ZigType = @import("../../Type.zig");
src/codegen/aarch64/abi.zig+4-16
...@@ -1,7 +1,5 @@...@@ -1,7 +1,5 @@
1const assert = @import("std").debug.assert;
1const std = @import("std");2const std = @import("std");
2const builtin = @import("builtin");
3const bits = @import("../../arch/aarch64/bits.zig");
4const Register = bits.Register;
5const Type = @import("../../Type.zig");3const Type = @import("../../Type.zig");
6const Zcu = @import("../../Zcu.zig");4const Zcu = @import("../../Zcu.zig");
75
...@@ -15,7 +13,7 @@ pub const Class = union(enum) {...@@ -15,7 +13,7 @@ pub const Class = union(enum) {
1513
16/// For `float_array` the second element will be the amount of floats.14/// For `float_array` the second element will be the amount of floats.
17pub fn classifyType(ty: Type, zcu: *Zcu) Class {15pub fn classifyType(ty: Type, zcu: *Zcu) Class {
18 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(zcu));16 assert(ty.hasRuntimeBitsIgnoreComptime(zcu));
1917
20 var maybe_float_bits: ?u16 = null;18 var maybe_float_bits: ?u16 = null;
21 switch (ty.zigTypeTag(zcu)) {19 switch (ty.zigTypeTag(zcu)) {
...@@ -47,11 +45,11 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {...@@ -47,11 +45,11 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class {
47 return .byval;45 return .byval;
48 },46 },
49 .optional => {47 .optional => {
50 std.debug.assert(ty.isPtrLikeOptional(zcu));48 assert(ty.isPtrLikeOptional(zcu));
51 return .byval;49 return .byval;
52 },50 },
53 .pointer => {51 .pointer => {
54 std.debug.assert(!ty.isSlice(zcu));52 assert(!ty.isSlice(zcu));
55 return .byval;53 return .byval;
56 },54 },
57 .error_union,55 .error_union,
...@@ -138,13 +136,3 @@ pub fn getFloatArrayType(ty: Type, zcu: *Zcu) ?Type {...@@ -138,13 +136,3 @@ pub fn getFloatArrayType(ty: Type, zcu: *Zcu) ?Type {
138 else => return null,136 else => return null,
139 }137 }
140}138}
141
142pub const callee_preserved_regs = [_]Register{
143 .x19, .x20, .x21, .x22, .x23,
144 .x24, .x25, .x26, .x27, .x28,
145};
146
147pub const c_abi_int_param_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };
148pub const c_abi_int_return_regs = [_]Register{ .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7 };
149
150const allocatable_registers = callee_preserved_regs;
src/codegen/aarch64/encoding.zig created+11799
...@@ -0,0 +1,11799 @@
1/// B1.2 Registers in AArch64 Execution state
2pub const Register = struct {
3 alias: Alias,
4 format: Format,
5
6 pub const Format = union(enum) {
7 alias,
8 integer: IntegerSize,
9 scalar: VectorSize,
10 vector: Arrangement,
11 element: struct { size: VectorSize, index: u4 },
12 };
13
14 pub const IntegerSize = enum(u1) {
15 word = 0b0,
16 doubleword = 0b1,
17
18 pub fn prefix(is: IntegerSize) u8 {
19 return (comptime std.enums.EnumArray(IntegerSize, u8).init(.{
20 .word = 'w',
21 .doubleword = 'x',
22 })).get(is);
23 }
24 };
25
26 pub const VectorSize = enum(u3) {
27 byte = 0,
28 half = 1,
29 single = 2,
30 double = 3,
31 quad = 4,
32 scalable,
33 predicate,
34
35 pub fn prefix(vs: VectorSize) u8 {
36 return (comptime std.enums.EnumArray(VectorSize, u8).init(.{
37 .byte = 'b',
38 .half = 'h',
39 .single = 's',
40 .double = 'd',
41 .quad = 'q',
42 .scalable = 'z',
43 .predicate = 'p',
44 })).get(vs);
45 }
46 };
47
48 pub const Arrangement = enum {
49 @"2d",
50 @"4s",
51 @"8h",
52 @"16b",
53
54 @"1d",
55 @"2s",
56 @"4h",
57 @"8b",
58
59 pub fn len(arrangement: Arrangement) u5 {
60 return switch (arrangement) {
61 .@"1d" => 1,
62 .@"2d", .@"2s" => 2,
63 .@"4s", .@"4h" => 4,
64 .@"8h", .@"8b" => 8,
65 .@"16b" => 16,
66 };
67 }
68
69 pub fn size(arrangement: Arrangement) Instruction.DataProcessingVector.Q {
70 return switch (arrangement) {
71 .@"2d", .@"4s", .@"8h", .@"16b" => .quad,
72 .@"1d", .@"2s", .@"4h", .@"8b" => .double,
73 };
74 }
75
76 pub fn elemSize(arrangement: Arrangement) Instruction.DataProcessingVector.Size {
77 return switch (arrangement) {
78 .@"2d", .@"1d" => .double,
79 .@"4s", .@"2s" => .single,
80 .@"8h", .@"4h" => .half,
81 .@"16b", .@"8b" => .byte,
82 };
83 }
84 };
85
86 pub const x0: Register = .{ .alias = .r0, .format = .{ .integer = .doubleword } };
87 pub const x1: Register = .{ .alias = .r1, .format = .{ .integer = .doubleword } };
88 pub const x2: Register = .{ .alias = .r2, .format = .{ .integer = .doubleword } };
89 pub const x3: Register = .{ .alias = .r3, .format = .{ .integer = .doubleword } };
90 pub const x4: Register = .{ .alias = .r4, .format = .{ .integer = .doubleword } };
91 pub const x5: Register = .{ .alias = .r5, .format = .{ .integer = .doubleword } };
92 pub const x6: Register = .{ .alias = .r6, .format = .{ .integer = .doubleword } };
93 pub const x7: Register = .{ .alias = .r7, .format = .{ .integer = .doubleword } };
94 pub const x8: Register = .{ .alias = .r8, .format = .{ .integer = .doubleword } };
95 pub const x9: Register = .{ .alias = .r9, .format = .{ .integer = .doubleword } };
96 pub const x10: Register = .{ .alias = .r10, .format = .{ .integer = .doubleword } };
97 pub const x11: Register = .{ .alias = .r11, .format = .{ .integer = .doubleword } };
98 pub const x12: Register = .{ .alias = .r12, .format = .{ .integer = .doubleword } };
99 pub const x13: Register = .{ .alias = .r13, .format = .{ .integer = .doubleword } };
100 pub const x14: Register = .{ .alias = .r14, .format = .{ .integer = .doubleword } };
101 pub const x15: Register = .{ .alias = .r15, .format = .{ .integer = .doubleword } };
102 pub const x16: Register = .{ .alias = .r16, .format = .{ .integer = .doubleword } };
103 pub const x17: Register = .{ .alias = .r17, .format = .{ .integer = .doubleword } };
104 pub const x18: Register = .{ .alias = .r18, .format = .{ .integer = .doubleword } };
105 pub const x19: Register = .{ .alias = .r19, .format = .{ .integer = .doubleword } };
106 pub const x20: Register = .{ .alias = .r20, .format = .{ .integer = .doubleword } };
107 pub const x21: Register = .{ .alias = .r21, .format = .{ .integer = .doubleword } };
108 pub const x22: Register = .{ .alias = .r22, .format = .{ .integer = .doubleword } };
109 pub const x23: Register = .{ .alias = .r23, .format = .{ .integer = .doubleword } };
110 pub const x24: Register = .{ .alias = .r24, .format = .{ .integer = .doubleword } };
111 pub const x25: Register = .{ .alias = .r25, .format = .{ .integer = .doubleword } };
112 pub const x26: Register = .{ .alias = .r26, .format = .{ .integer = .doubleword } };
113 pub const x27: Register = .{ .alias = .r27, .format = .{ .integer = .doubleword } };
114 pub const x28: Register = .{ .alias = .r28, .format = .{ .integer = .doubleword } };
115 pub const x29: Register = .{ .alias = .r29, .format = .{ .integer = .doubleword } };
116 pub const x30: Register = .{ .alias = .r30, .format = .{ .integer = .doubleword } };
117 pub const xzr: Register = .{ .alias = .zr, .format = .{ .integer = .doubleword } };
118 pub const sp: Register = .{ .alias = .sp, .format = .{ .integer = .doubleword } };
119
120 pub const w0: Register = .{ .alias = .r0, .format = .{ .integer = .word } };
121 pub const w1: Register = .{ .alias = .r1, .format = .{ .integer = .word } };
122 pub const w2: Register = .{ .alias = .r2, .format = .{ .integer = .word } };
123 pub const w3: Register = .{ .alias = .r3, .format = .{ .integer = .word } };
124 pub const w4: Register = .{ .alias = .r4, .format = .{ .integer = .word } };
125 pub const w5: Register = .{ .alias = .r5, .format = .{ .integer = .word } };
126 pub const w6: Register = .{ .alias = .r6, .format = .{ .integer = .word } };
127 pub const w7: Register = .{ .alias = .r7, .format = .{ .integer = .word } };
128 pub const w8: Register = .{ .alias = .r8, .format = .{ .integer = .word } };
129 pub const w9: Register = .{ .alias = .r9, .format = .{ .integer = .word } };
130 pub const w10: Register = .{ .alias = .r10, .format = .{ .integer = .word } };
131 pub const w11: Register = .{ .alias = .r11, .format = .{ .integer = .word } };
132 pub const w12: Register = .{ .alias = .r12, .format = .{ .integer = .word } };
133 pub const w13: Register = .{ .alias = .r13, .format = .{ .integer = .word } };
134 pub const w14: Register = .{ .alias = .r14, .format = .{ .integer = .word } };
135 pub const w15: Register = .{ .alias = .r15, .format = .{ .integer = .word } };
136 pub const w16: Register = .{ .alias = .r16, .format = .{ .integer = .word } };
137 pub const w17: Register = .{ .alias = .r17, .format = .{ .integer = .word } };
138 pub const w18: Register = .{ .alias = .r18, .format = .{ .integer = .word } };
139 pub const w19: Register = .{ .alias = .r19, .format = .{ .integer = .word } };
140 pub const w20: Register = .{ .alias = .r20, .format = .{ .integer = .word } };
141 pub const w21: Register = .{ .alias = .r21, .format = .{ .integer = .word } };
142 pub const w22: Register = .{ .alias = .r22, .format = .{ .integer = .word } };
143 pub const w23: Register = .{ .alias = .r23, .format = .{ .integer = .word } };
144 pub const w24: Register = .{ .alias = .r24, .format = .{ .integer = .word } };
145 pub const w25: Register = .{ .alias = .r25, .format = .{ .integer = .word } };
146 pub const w26: Register = .{ .alias = .r26, .format = .{ .integer = .word } };
147 pub const w27: Register = .{ .alias = .r27, .format = .{ .integer = .word } };
148 pub const w28: Register = .{ .alias = .r28, .format = .{ .integer = .word } };
149 pub const w29: Register = .{ .alias = .r29, .format = .{ .integer = .word } };
150 pub const w30: Register = .{ .alias = .r30, .format = .{ .integer = .word } };
151 pub const wzr: Register = .{ .alias = .zr, .format = .{ .integer = .word } };
152 pub const wsp: Register = .{ .alias = .sp, .format = .{ .integer = .word } };
153
154 pub const ip0 = x16;
155 pub const ip1 = x17;
156 pub const fp = x29;
157 pub const lr = x30;
158 pub const pc: Register = .{ .alias = .pc, .format = .{ .integer = .doubleword } };
159
160 pub const q0: Register = .{ .alias = .v0, .format = .{ .scalar = .quad } };
161 pub const q1: Register = .{ .alias = .v1, .format = .{ .scalar = .quad } };
162 pub const q2: Register = .{ .alias = .v2, .format = .{ .scalar = .quad } };
163 pub const q3: Register = .{ .alias = .v3, .format = .{ .scalar = .quad } };
164 pub const q4: Register = .{ .alias = .v4, .format = .{ .scalar = .quad } };
165 pub const q5: Register = .{ .alias = .v5, .format = .{ .scalar = .quad } };
166 pub const q6: Register = .{ .alias = .v6, .format = .{ .scalar = .quad } };
167 pub const q7: Register = .{ .alias = .v7, .format = .{ .scalar = .quad } };
168 pub const q8: Register = .{ .alias = .v8, .format = .{ .scalar = .quad } };
169 pub const q9: Register = .{ .alias = .v9, .format = .{ .scalar = .quad } };
170 pub const q10: Register = .{ .alias = .v10, .format = .{ .scalar = .quad } };
171 pub const q11: Register = .{ .alias = .v11, .format = .{ .scalar = .quad } };
172 pub const q12: Register = .{ .alias = .v12, .format = .{ .scalar = .quad } };
173 pub const q13: Register = .{ .alias = .v13, .format = .{ .scalar = .quad } };
174 pub const q14: Register = .{ .alias = .v14, .format = .{ .scalar = .quad } };
175 pub const q15: Register = .{ .alias = .v15, .format = .{ .scalar = .quad } };
176 pub const q16: Register = .{ .alias = .v16, .format = .{ .scalar = .quad } };
177 pub const q17: Register = .{ .alias = .v17, .format = .{ .scalar = .quad } };
178 pub const q18: Register = .{ .alias = .v18, .format = .{ .scalar = .quad } };
179 pub const q19: Register = .{ .alias = .v19, .format = .{ .scalar = .quad } };
180 pub const q20: Register = .{ .alias = .v20, .format = .{ .scalar = .quad } };
181 pub const q21: Register = .{ .alias = .v21, .format = .{ .scalar = .quad } };
182 pub const q22: Register = .{ .alias = .v22, .format = .{ .scalar = .quad } };
183 pub const q23: Register = .{ .alias = .v23, .format = .{ .scalar = .quad } };
184 pub const q24: Register = .{ .alias = .v24, .format = .{ .scalar = .quad } };
185 pub const q25: Register = .{ .alias = .v25, .format = .{ .scalar = .quad } };
186 pub const q26: Register = .{ .alias = .v26, .format = .{ .scalar = .quad } };
187 pub const q27: Register = .{ .alias = .v27, .format = .{ .scalar = .quad } };
188 pub const q28: Register = .{ .alias = .v28, .format = .{ .scalar = .quad } };
189 pub const q29: Register = .{ .alias = .v29, .format = .{ .scalar = .quad } };
190 pub const q30: Register = .{ .alias = .v30, .format = .{ .scalar = .quad } };
191 pub const q31: Register = .{ .alias = .v31, .format = .{ .scalar = .quad } };
192
193 pub const d0: Register = .{ .alias = .v0, .format = .{ .scalar = .double } };
194 pub const d1: Register = .{ .alias = .v1, .format = .{ .scalar = .double } };
195 pub const d2: Register = .{ .alias = .v2, .format = .{ .scalar = .double } };
196 pub const d3: Register = .{ .alias = .v3, .format = .{ .scalar = .double } };
197 pub const d4: Register = .{ .alias = .v4, .format = .{ .scalar = .double } };
198 pub const d5: Register = .{ .alias = .v5, .format = .{ .scalar = .double } };
199 pub const d6: Register = .{ .alias = .v6, .format = .{ .scalar = .double } };
200 pub const d7: Register = .{ .alias = .v7, .format = .{ .scalar = .double } };
201 pub const d8: Register = .{ .alias = .v8, .format = .{ .scalar = .double } };
202 pub const d9: Register = .{ .alias = .v9, .format = .{ .scalar = .double } };
203 pub const d10: Register = .{ .alias = .v10, .format = .{ .scalar = .double } };
204 pub const d11: Register = .{ .alias = .v11, .format = .{ .scalar = .double } };
205 pub const d12: Register = .{ .alias = .v12, .format = .{ .scalar = .double } };
206 pub const d13: Register = .{ .alias = .v13, .format = .{ .scalar = .double } };
207 pub const d14: Register = .{ .alias = .v14, .format = .{ .scalar = .double } };
208 pub const d15: Register = .{ .alias = .v15, .format = .{ .scalar = .double } };
209 pub const d16: Register = .{ .alias = .v16, .format = .{ .scalar = .double } };
210 pub const d17: Register = .{ .alias = .v17, .format = .{ .scalar = .double } };
211 pub const d18: Register = .{ .alias = .v18, .format = .{ .scalar = .double } };
212 pub const d19: Register = .{ .alias = .v19, .format = .{ .scalar = .double } };
213 pub const d20: Register = .{ .alias = .v20, .format = .{ .scalar = .double } };
214 pub const d21: Register = .{ .alias = .v21, .format = .{ .scalar = .double } };
215 pub const d22: Register = .{ .alias = .v22, .format = .{ .scalar = .double } };
216 pub const d23: Register = .{ .alias = .v23, .format = .{ .scalar = .double } };
217 pub const d24: Register = .{ .alias = .v24, .format = .{ .scalar = .double } };
218 pub const d25: Register = .{ .alias = .v25, .format = .{ .scalar = .double } };
219 pub const d26: Register = .{ .alias = .v26, .format = .{ .scalar = .double } };
220 pub const d27: Register = .{ .alias = .v27, .format = .{ .scalar = .double } };
221 pub const d28: Register = .{ .alias = .v28, .format = .{ .scalar = .double } };
222 pub const d29: Register = .{ .alias = .v29, .format = .{ .scalar = .double } };
223 pub const d30: Register = .{ .alias = .v30, .format = .{ .scalar = .double } };
224 pub const d31: Register = .{ .alias = .v31, .format = .{ .scalar = .double } };
225
226 pub const s0: Register = .{ .alias = .v0, .format = .{ .scalar = .single } };
227 pub const s1: Register = .{ .alias = .v1, .format = .{ .scalar = .single } };
228 pub const s2: Register = .{ .alias = .v2, .format = .{ .scalar = .single } };
229 pub const s3: Register = .{ .alias = .v3, .format = .{ .scalar = .single } };
230 pub const s4: Register = .{ .alias = .v4, .format = .{ .scalar = .single } };
231 pub const s5: Register = .{ .alias = .v5, .format = .{ .scalar = .single } };
232 pub const s6: Register = .{ .alias = .v6, .format = .{ .scalar = .single } };
233 pub const s7: Register = .{ .alias = .v7, .format = .{ .scalar = .single } };
234 pub const s8: Register = .{ .alias = .v8, .format = .{ .scalar = .single } };
235 pub const s9: Register = .{ .alias = .v9, .format = .{ .scalar = .single } };
236 pub const s10: Register = .{ .alias = .v10, .format = .{ .scalar = .single } };
237 pub const s11: Register = .{ .alias = .v11, .format = .{ .scalar = .single } };
238 pub const s12: Register = .{ .alias = .v12, .format = .{ .scalar = .single } };
239 pub const s13: Register = .{ .alias = .v13, .format = .{ .scalar = .single } };
240 pub const s14: Register = .{ .alias = .v14, .format = .{ .scalar = .single } };
241 pub const s15: Register = .{ .alias = .v15, .format = .{ .scalar = .single } };
242 pub const s16: Register = .{ .alias = .v16, .format = .{ .scalar = .single } };
243 pub const s17: Register = .{ .alias = .v17, .format = .{ .scalar = .single } };
244 pub const s18: Register = .{ .alias = .v18, .format = .{ .scalar = .single } };
245 pub const s19: Register = .{ .alias = .v19, .format = .{ .scalar = .single } };
246 pub const s20: Register = .{ .alias = .v20, .format = .{ .scalar = .single } };
247 pub const s21: Register = .{ .alias = .v21, .format = .{ .scalar = .single } };
248 pub const s22: Register = .{ .alias = .v22, .format = .{ .scalar = .single } };
249 pub const s23: Register = .{ .alias = .v23, .format = .{ .scalar = .single } };
250 pub const s24: Register = .{ .alias = .v24, .format = .{ .scalar = .single } };
251 pub const s25: Register = .{ .alias = .v25, .format = .{ .scalar = .single } };
252 pub const s26: Register = .{ .alias = .v26, .format = .{ .scalar = .single } };
253 pub const s27: Register = .{ .alias = .v27, .format = .{ .scalar = .single } };
254 pub const s28: Register = .{ .alias = .v28, .format = .{ .scalar = .single } };
255 pub const s29: Register = .{ .alias = .v29, .format = .{ .scalar = .single } };
256 pub const s30: Register = .{ .alias = .v30, .format = .{ .scalar = .single } };
257 pub const s31: Register = .{ .alias = .v31, .format = .{ .scalar = .single } };
258
259 pub const h0: Register = .{ .alias = .v0, .format = .{ .scalar = .half } };
260 pub const h1: Register = .{ .alias = .v1, .format = .{ .scalar = .half } };
261 pub const h2: Register = .{ .alias = .v2, .format = .{ .scalar = .half } };
262 pub const h3: Register = .{ .alias = .v3, .format = .{ .scalar = .half } };
263 pub const h4: Register = .{ .alias = .v4, .format = .{ .scalar = .half } };
264 pub const h5: Register = .{ .alias = .v5, .format = .{ .scalar = .half } };
265 pub const h6: Register = .{ .alias = .v6, .format = .{ .scalar = .half } };
266 pub const h7: Register = .{ .alias = .v7, .format = .{ .scalar = .half } };
267 pub const h8: Register = .{ .alias = .v8, .format = .{ .scalar = .half } };
268 pub const h9: Register = .{ .alias = .v9, .format = .{ .scalar = .half } };
269 pub const h10: Register = .{ .alias = .v10, .format = .{ .scalar = .half } };
270 pub const h11: Register = .{ .alias = .v11, .format = .{ .scalar = .half } };
271 pub const h12: Register = .{ .alias = .v12, .format = .{ .scalar = .half } };
272 pub const h13: Register = .{ .alias = .v13, .format = .{ .scalar = .half } };
273 pub const h14: Register = .{ .alias = .v14, .format = .{ .scalar = .half } };
274 pub const h15: Register = .{ .alias = .v15, .format = .{ .scalar = .half } };
275 pub const h16: Register = .{ .alias = .v16, .format = .{ .scalar = .half } };
276 pub const h17: Register = .{ .alias = .v17, .format = .{ .scalar = .half } };
277 pub const h18: Register = .{ .alias = .v18, .format = .{ .scalar = .half } };
278 pub const h19: Register = .{ .alias = .v19, .format = .{ .scalar = .half } };
279 pub const h20: Register = .{ .alias = .v20, .format = .{ .scalar = .half } };
280 pub const h21: Register = .{ .alias = .v21, .format = .{ .scalar = .half } };
281 pub const h22: Register = .{ .alias = .v22, .format = .{ .scalar = .half } };
282 pub const h23: Register = .{ .alias = .v23, .format = .{ .scalar = .half } };
283 pub const h24: Register = .{ .alias = .v24, .format = .{ .scalar = .half } };
284 pub const h25: Register = .{ .alias = .v25, .format = .{ .scalar = .half } };
285 pub const h26: Register = .{ .alias = .v26, .format = .{ .scalar = .half } };
286 pub const h27: Register = .{ .alias = .v27, .format = .{ .scalar = .half } };
287 pub const h28: Register = .{ .alias = .v28, .format = .{ .scalar = .half } };
288 pub const h29: Register = .{ .alias = .v29, .format = .{ .scalar = .half } };
289 pub const h30: Register = .{ .alias = .v30, .format = .{ .scalar = .half } };
290 pub const h31: Register = .{ .alias = .v31, .format = .{ .scalar = .half } };
291
292 pub const b0: Register = .{ .alias = .v0, .format = .{ .scalar = .byte } };
293 pub const b1: Register = .{ .alias = .v1, .format = .{ .scalar = .byte } };
294 pub const b2: Register = .{ .alias = .v2, .format = .{ .scalar = .byte } };
295 pub const b3: Register = .{ .alias = .v3, .format = .{ .scalar = .byte } };
296 pub const b4: Register = .{ .alias = .v4, .format = .{ .scalar = .byte } };
297 pub const b5: Register = .{ .alias = .v5, .format = .{ .scalar = .byte } };
298 pub const b6: Register = .{ .alias = .v6, .format = .{ .scalar = .byte } };
299 pub const b7: Register = .{ .alias = .v7, .format = .{ .scalar = .byte } };
300 pub const b8: Register = .{ .alias = .v8, .format = .{ .scalar = .byte } };
301 pub const b9: Register = .{ .alias = .v9, .format = .{ .scalar = .byte } };
302 pub const b10: Register = .{ .alias = .v10, .format = .{ .scalar = .byte } };
303 pub const b11: Register = .{ .alias = .v11, .format = .{ .scalar = .byte } };
304 pub const b12: Register = .{ .alias = .v12, .format = .{ .scalar = .byte } };
305 pub const b13: Register = .{ .alias = .v13, .format = .{ .scalar = .byte } };
306 pub const b14: Register = .{ .alias = .v14, .format = .{ .scalar = .byte } };
307 pub const b15: Register = .{ .alias = .v15, .format = .{ .scalar = .byte } };
308 pub const b16: Register = .{ .alias = .v16, .format = .{ .scalar = .byte } };
309 pub const b17: Register = .{ .alias = .v17, .format = .{ .scalar = .byte } };
310 pub const b18: Register = .{ .alias = .v18, .format = .{ .scalar = .byte } };
311 pub const b19: Register = .{ .alias = .v19, .format = .{ .scalar = .byte } };
312 pub const b20: Register = .{ .alias = .v20, .format = .{ .scalar = .byte } };
313 pub const b21: Register = .{ .alias = .v21, .format = .{ .scalar = .byte } };
314 pub const b22: Register = .{ .alias = .v22, .format = .{ .scalar = .byte } };
315 pub const b23: Register = .{ .alias = .v23, .format = .{ .scalar = .byte } };
316 pub const b24: Register = .{ .alias = .v24, .format = .{ .scalar = .byte } };
317 pub const b25: Register = .{ .alias = .v25, .format = .{ .scalar = .byte } };
318 pub const b26: Register = .{ .alias = .v26, .format = .{ .scalar = .byte } };
319 pub const b27: Register = .{ .alias = .v27, .format = .{ .scalar = .byte } };
320 pub const b28: Register = .{ .alias = .v28, .format = .{ .scalar = .byte } };
321 pub const b29: Register = .{ .alias = .v29, .format = .{ .scalar = .byte } };
322 pub const b30: Register = .{ .alias = .v30, .format = .{ .scalar = .byte } };
323 pub const b31: Register = .{ .alias = .v31, .format = .{ .scalar = .byte } };
324
325 pub const fpcr: Register = .{ .alias = .fpcr, .format = .{ .integer = .doubleword } };
326 pub const fpsr: Register = .{ .alias = .fpsr, .format = .{ .integer = .doubleword } };
327
328 pub const z0: Register = .{ .alias = .v0, .format = .{ .scalar = .scalable } };
329 pub const z1: Register = .{ .alias = .v1, .format = .{ .scalar = .scalable } };
330 pub const z2: Register = .{ .alias = .v2, .format = .{ .scalar = .scalable } };
331 pub const z3: Register = .{ .alias = .v3, .format = .{ .scalar = .scalable } };
332 pub const z4: Register = .{ .alias = .v4, .format = .{ .scalar = .scalable } };
333 pub const z5: Register = .{ .alias = .v5, .format = .{ .scalar = .scalable } };
334 pub const z6: Register = .{ .alias = .v6, .format = .{ .scalar = .scalable } };
335 pub const z7: Register = .{ .alias = .v7, .format = .{ .scalar = .scalable } };
336 pub const z8: Register = .{ .alias = .v8, .format = .{ .scalar = .scalable } };
337 pub const z9: Register = .{ .alias = .v9, .format = .{ .scalar = .scalable } };
338 pub const z10: Register = .{ .alias = .v10, .format = .{ .scalar = .scalable } };
339 pub const z11: Register = .{ .alias = .v11, .format = .{ .scalar = .scalable } };
340 pub const z12: Register = .{ .alias = .v12, .format = .{ .scalar = .scalable } };
341 pub const z13: Register = .{ .alias = .v13, .format = .{ .scalar = .scalable } };
342 pub const z14: Register = .{ .alias = .v14, .format = .{ .scalar = .scalable } };
343 pub const z15: Register = .{ .alias = .v15, .format = .{ .scalar = .scalable } };
344 pub const z16: Register = .{ .alias = .v16, .format = .{ .scalar = .scalable } };
345 pub const z17: Register = .{ .alias = .v17, .format = .{ .scalar = .scalable } };
346 pub const z18: Register = .{ .alias = .v18, .format = .{ .scalar = .scalable } };
347 pub const z19: Register = .{ .alias = .v19, .format = .{ .scalar = .scalable } };
348 pub const z20: Register = .{ .alias = .v20, .format = .{ .scalar = .scalable } };
349 pub const z21: Register = .{ .alias = .v21, .format = .{ .scalar = .scalable } };
350 pub const z22: Register = .{ .alias = .v22, .format = .{ .scalar = .scalable } };
351 pub const z23: Register = .{ .alias = .v23, .format = .{ .scalar = .scalable } };
352 pub const z24: Register = .{ .alias = .v24, .format = .{ .scalar = .scalable } };
353 pub const z25: Register = .{ .alias = .v25, .format = .{ .scalar = .scalable } };
354 pub const z26: Register = .{ .alias = .v26, .format = .{ .scalar = .scalable } };
355 pub const z27: Register = .{ .alias = .v27, .format = .{ .scalar = .scalable } };
356 pub const z28: Register = .{ .alias = .v28, .format = .{ .scalar = .scalable } };
357 pub const z29: Register = .{ .alias = .v29, .format = .{ .scalar = .scalable } };
358 pub const z30: Register = .{ .alias = .v30, .format = .{ .scalar = .scalable } };
359 pub const z31: Register = .{ .alias = .v31, .format = .{ .scalar = .scalable } };
360
361 pub const p0: Register = .{ .alias = .v0, .format = .{ .scalar = .predicate } };
362 pub const p1: Register = .{ .alias = .v1, .format = .{ .scalar = .predicate } };
363 pub const p2: Register = .{ .alias = .v2, .format = .{ .scalar = .predicate } };
364 pub const p3: Register = .{ .alias = .v3, .format = .{ .scalar = .predicate } };
365 pub const p4: Register = .{ .alias = .v4, .format = .{ .scalar = .predicate } };
366 pub const p5: Register = .{ .alias = .v5, .format = .{ .scalar = .predicate } };
367 pub const p6: Register = .{ .alias = .v6, .format = .{ .scalar = .predicate } };
368 pub const p7: Register = .{ .alias = .v7, .format = .{ .scalar = .predicate } };
369 pub const p8: Register = .{ .alias = .v8, .format = .{ .scalar = .predicate } };
370 pub const p9: Register = .{ .alias = .v9, .format = .{ .scalar = .predicate } };
371 pub const p10: Register = .{ .alias = .v10, .format = .{ .scalar = .predicate } };
372 pub const p11: Register = .{ .alias = .v11, .format = .{ .scalar = .predicate } };
373 pub const p12: Register = .{ .alias = .v12, .format = .{ .scalar = .predicate } };
374 pub const p13: Register = .{ .alias = .v13, .format = .{ .scalar = .predicate } };
375 pub const p14: Register = .{ .alias = .v14, .format = .{ .scalar = .predicate } };
376 pub const p15: Register = .{ .alias = .v15, .format = .{ .scalar = .predicate } };
377
378 pub const ffr: Register = .{ .alias = .ffr, .format = .{ .integer = .doubleword } };
379
380 pub const Encoded = enum(u5) {
381 _,
382
383 pub fn decodeInteger(enc: Encoded, sf_enc: IntegerSize, opts: struct { sp: bool = false }) Register {
384 return switch (sf_enc) {
385 .word => switch (@intFromEnum(enc)) {
386 0 => .w0,
387 1 => .w1,
388 2 => .w2,
389 3 => .w3,
390 4 => .w4,
391 5 => .w5,
392 6 => .w6,
393 7 => .w7,
394 8 => .w8,
395 9 => .w9,
396 10 => .w10,
397 11 => .w11,
398 12 => .w12,
399 13 => .w13,
400 14 => .w14,
401 15 => .w15,
402 16 => .w16,
403 17 => .w17,
404 18 => .w18,
405 19 => .w19,
406 20 => .w20,
407 21 => .w21,
408 22 => .w22,
409 23 => .w23,
410 24 => .w24,
411 25 => .w25,
412 26 => .w26,
413 27 => .w27,
414 28 => .w28,
415 29 => .w29,
416 30 => .w30,
417 31 => if (opts.sp) .wsp else .wzr,
418 },
419 .doubleword => switch (@intFromEnum(enc)) {
420 0 => .x0,
421 1 => .x1,
422 2 => .x2,
423 3 => .x3,
424 4 => .x4,
425 5 => .x5,
426 6 => .x6,
427 7 => .x7,
428 8 => .x8,
429 9 => .x9,
430 10 => .x10,
431 11 => .x11,
432 12 => .x12,
433 13 => .x13,
434 14 => .x14,
435 15 => .x15,
436 16 => .x16,
437 17 => .x17,
438 18 => .x18,
439 19 => .x19,
440 20 => .x20,
441 21 => .x21,
442 22 => .x22,
443 23 => .x23,
444 24 => .x24,
445 25 => .x25,
446 26 => .x26,
447 27 => .x27,
448 28 => .x28,
449 29 => .x29,
450 30 => .x30,
451 31 => if (opts.sp) .sp else .xzr,
452 },
453 };
454 }
455
456 pub fn decodeVector(enc: Encoded, vs_enc: VectorSize) Register {
457 return switch (vs_enc) {
458 .byte => switch (@intFromEnum(enc)) {
459 0 => .b0,
460 1 => .b1,
461 2 => .b2,
462 3 => .b3,
463 4 => .b4,
464 5 => .b5,
465 6 => .b6,
466 7 => .b7,
467 8 => .b8,
468 9 => .b9,
469 10 => .b10,
470 11 => .b11,
471 12 => .b12,
472 13 => .b13,
473 14 => .b14,
474 15 => .b15,
475 16 => .b16,
476 17 => .b17,
477 18 => .b18,
478 19 => .b19,
479 20 => .b20,
480 21 => .b21,
481 22 => .b22,
482 23 => .b23,
483 24 => .b24,
484 25 => .b25,
485 26 => .b26,
486 27 => .b27,
487 28 => .b28,
488 29 => .b29,
489 30 => .b30,
490 31 => .b31,
491 },
492 .half => switch (@intFromEnum(enc)) {
493 0 => .h0,
494 1 => .h1,
495 2 => .h2,
496 3 => .h3,
497 4 => .h4,
498 5 => .h5,
499 6 => .h6,
500 7 => .h7,
501 8 => .h8,
502 9 => .h9,
503 10 => .h10,
504 11 => .h11,
505 12 => .h12,
506 13 => .h13,
507 14 => .h14,
508 15 => .h15,
509 16 => .h16,
510 17 => .h17,
511 18 => .h18,
512 19 => .h19,
513 20 => .h20,
514 21 => .h21,
515 22 => .h22,
516 23 => .h23,
517 24 => .h24,
518 25 => .h25,
519 26 => .h26,
520 27 => .h27,
521 28 => .h28,
522 29 => .h29,
523 30 => .h30,
524 31 => .h31,
525 },
526 .single => switch (@intFromEnum(enc)) {
527 0 => .s0,
528 1 => .s1,
529 2 => .s2,
530 3 => .s3,
531 4 => .s4,
532 5 => .s5,
533 6 => .s6,
534 7 => .s7,
535 8 => .s8,
536 9 => .s9,
537 10 => .s10,
538 11 => .s11,
539 12 => .s12,
540 13 => .s13,
541 14 => .s14,
542 15 => .s15,
543 16 => .s16,
544 17 => .s17,
545 18 => .s18,
546 19 => .s19,
547 20 => .s20,
548 21 => .s21,
549 22 => .s22,
550 23 => .s23,
551 24 => .s24,
552 25 => .s25,
553 26 => .s26,
554 27 => .s27,
555 28 => .s28,
556 29 => .s29,
557 30 => .s30,
558 31 => .s31,
559 },
560 .double => switch (@intFromEnum(enc)) {
561 0 => .d0,
562 1 => .d1,
563 2 => .d2,
564 3 => .d3,
565 4 => .d4,
566 5 => .d5,
567 6 => .d6,
568 7 => .d7,
569 8 => .d8,
570 9 => .d9,
571 10 => .d10,
572 11 => .d11,
573 12 => .d12,
574 13 => .d13,
575 14 => .d14,
576 15 => .d15,
577 16 => .d16,
578 17 => .d17,
579 18 => .d18,
580 19 => .d19,
581 20 => .d20,
582 21 => .d21,
583 22 => .d22,
584 23 => .d23,
585 24 => .d24,
586 25 => .d25,
587 26 => .d26,
588 27 => .d27,
589 28 => .d28,
590 29 => .d29,
591 30 => .d30,
592 31 => .d31,
593 },
594 .quad => switch (@intFromEnum(enc)) {
595 0 => .q0,
596 1 => .q1,
597 2 => .q2,
598 3 => .q3,
599 4 => .q4,
600 5 => .q5,
601 6 => .q6,
602 7 => .q7,
603 8 => .q8,
604 9 => .q9,
605 10 => .q10,
606 11 => .q11,
607 12 => .q12,
608 13 => .q13,
609 14 => .q14,
610 15 => .q15,
611 16 => .q16,
612 17 => .q17,
613 18 => .q18,
614 19 => .q19,
615 20 => .q20,
616 21 => .q21,
617 22 => .q22,
618 23 => .q23,
619 24 => .q24,
620 25 => .q25,
621 26 => .q26,
622 27 => .q27,
623 28 => .q28,
624 29 => .q29,
625 30 => .q30,
626 31 => .q31,
627 },
628 .scalable => switch (@intFromEnum(enc)) {
629 0 => .z0,
630 1 => .z1,
631 2 => .z2,
632 3 => .z3,
633 4 => .z4,
634 5 => .z5,
635 6 => .z6,
636 7 => .z7,
637 8 => .z8,
638 9 => .z9,
639 10 => .z10,
640 11 => .z11,
641 12 => .z12,
642 13 => .z13,
643 14 => .z14,
644 15 => .z15,
645 16 => .z16,
646 17 => .z17,
647 18 => .z18,
648 19 => .z19,
649 20 => .z20,
650 21 => .z21,
651 22 => .z22,
652 23 => .z23,
653 24 => .z24,
654 25 => .z25,
655 26 => .z26,
656 27 => .z27,
657 28 => .z28,
658 29 => .z29,
659 30 => .z30,
660 31 => .z31,
661 },
662 .predicate => switch (@as(u4, @intCast(@intFromEnum(enc)))) {
663 0 => .p0,
664 1 => .p1,
665 2 => .p2,
666 3 => .p3,
667 4 => .p4,
668 5 => .p5,
669 6 => .p6,
670 7 => .p7,
671 8 => .p8,
672 9 => .p9,
673 10 => .p10,
674 11 => .p11,
675 12 => .p12,
676 13 => .p13,
677 14 => .p14,
678 15 => .p15,
679 },
680 };
681 }
682 };
683
684 /// One tag per set of aliasing registers.
685 pub const Alias = enum(u7) {
686 r0,
687 r1,
688 r2,
689 r3,
690 r4,
691 r5,
692 r6,
693 r7,
694 r8,
695 r9,
696 r10,
697 r11,
698 r12,
699 r13,
700 r14,
701 r15,
702 r16,
703 r17,
704 r18,
705 r19,
706 r20,
707 r21,
708 r22,
709 r23,
710 r24,
711 r25,
712 r26,
713 r27,
714 r28,
715 r29,
716 r30,
717 zr,
718 sp,
719
720 pc,
721
722 v0,
723 v1,
724 v2,
725 v3,
726 v4,
727 v5,
728 v6,
729 v7,
730 v8,
731 v9,
732 v10,
733 v11,
734 v12,
735 v13,
736 v14,
737 v15,
738 v16,
739 v17,
740 v18,
741 v19,
742 v20,
743 v21,
744 v22,
745 v23,
746 v24,
747 v25,
748 v26,
749 v27,
750 v28,
751 v29,
752 v30,
753 v31,
754
755 fpcr,
756 fpsr,
757
758 p0,
759 p1,
760 p2,
761 p3,
762 p4,
763 p5,
764 p6,
765 p7,
766 p8,
767 p9,
768 p10,
769 p11,
770 p12,
771 p13,
772 p14,
773 p15,
774
775 ffr,
776
777 pub const ip0: Alias = .r16;
778 pub const ip1: Alias = .r17;
779 pub const fp: Alias = .r29;
780 pub const lr: Alias = .r30;
781
782 pub fn r(ra: Alias) Register {
783 assert(@intFromEnum(ra) >= @intFromEnum(Alias.r0) and @intFromEnum(ra) <= @intFromEnum(Alias.pc));
784 return .{ .alias = ra, .format = .alias };
785 }
786 pub fn x(ra: Alias) Register {
787 assert(@intFromEnum(ra) >= @intFromEnum(Alias.r0) and @intFromEnum(ra) <= @intFromEnum(Alias.sp));
788 return .{ .alias = ra, .format = .{ .integer = .doubleword } };
789 }
790 pub fn w(ra: Alias) Register {
791 assert(@intFromEnum(ra) >= @intFromEnum(Alias.r0) and @intFromEnum(ra) <= @intFromEnum(Alias.sp));
792 return .{ .alias = ra, .format = .{ .integer = .word } };
793 }
794 pub fn v(ra: Alias) Register {
795 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
796 return .{ .alias = ra, .format = .alias };
797 }
798 pub fn q(ra: Alias) Register {
799 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
800 return .{ .alias = ra, .format = .{ .scalar = .quad } };
801 }
802 pub fn d(ra: Alias) Register {
803 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
804 return .{ .alias = ra, .format = .{ .scalar = .double } };
805 }
806 pub fn s(ra: Alias) Register {
807 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
808 return .{ .alias = ra, .format = .{ .scalar = .single } };
809 }
810 pub fn h(ra: Alias) Register {
811 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
812 return .{ .alias = ra, .format = .{ .scalar = .half } };
813 }
814 pub fn b(ra: Alias) Register {
815 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
816 return .{ .alias = ra, .format = .{ .scalar = .byte } };
817 }
818 pub fn z(ra: Alias) Register {
819 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
820 return .{ .alias = ra, .format = .{ .scalar = .scalable } };
821 }
822 pub fn p(ra: Alias) Register {
823 assert(@intFromEnum(ra) >= @intFromEnum(Alias.p0) and @intFromEnum(ra) <= @intFromEnum(Alias.p15));
824 return .{ .alias = ra, .format = .{ .scalar = .predicate } };
825 }
826 pub fn @"2d"(ra: Alias) Register {
827 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
828 return .{ .alias = ra, .format = .{ .vector = .@"2d" } };
829 }
830 pub fn @"4s"(ra: Alias) Register {
831 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
832 return .{ .alias = ra, .format = .{ .vector = .@"4s" } };
833 }
834 pub fn @"8h"(ra: Alias) Register {
835 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
836 return .{ .alias = ra, .format = .{ .vector = .@"8h" } };
837 }
838 pub fn @"16b"(ra: Alias) Register {
839 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
840 return .{ .alias = ra, .format = .{ .vector = .@"16b" } };
841 }
842 pub fn @"1d"(ra: Alias) Register {
843 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
844 return .{ .alias = ra, .format = .{ .vector = .@"1d" } };
845 }
846 pub fn @"2s"(ra: Alias) Register {
847 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
848 return .{ .alias = ra, .format = .{ .vector = .@"2s" } };
849 }
850 pub fn @"4h"(ra: Alias) Register {
851 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
852 return .{ .alias = ra, .format = .{ .vector = .@"4h" } };
853 }
854 pub fn @"8b"(ra: Alias) Register {
855 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
856 return .{ .alias = ra, .format = .{ .vector = .@"8b" } };
857 }
858 pub fn @"d[]"(ra: Alias, index: u1) Register {
859 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
860 return .{ .alias = ra, .format = .{ .element = .{ .size = .double, .index = index } } };
861 }
862 pub fn @"s[]"(ra: Alias, index: u2) Register {
863 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
864 return .{ .alias = ra, .format = .{ .element = .{ .size = .single, .index = index } } };
865 }
866 pub fn @"h[]"(ra: Alias, index: u3) Register {
867 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
868 return .{ .alias = ra, .format = .{ .element = .{ .size = .half, .index = index } } };
869 }
870 pub fn @"b[]"(ra: Alias, index: u4) Register {
871 assert(@intFromEnum(ra) >= @intFromEnum(Alias.v0) and @intFromEnum(ra) <= @intFromEnum(Alias.v31));
872 return .{ .alias = ra, .format = .{ .element = .{ .size = .byte, .index = index } } };
873 }
874
875 pub fn isVector(ra: Alias) bool {
876 return switch (ra) {
877 .r0,
878 .r1,
879 .r2,
880 .r3,
881 .r4,
882 .r5,
883 .r6,
884 .r7,
885 .r8,
886 .r9,
887 .r10,
888 .r11,
889 .r12,
890 .r13,
891 .r14,
892 .r15,
893 .r16,
894 .r17,
895 .r18,
896 .r19,
897 .r20,
898 .r21,
899 .r22,
900 .r23,
901 .r24,
902 .r25,
903 .r26,
904 .r27,
905 .r28,
906 .r29,
907 .r30,
908 .zr,
909 .sp,
910
911 .pc,
912
913 .fpcr,
914 .fpsr,
915
916 .ffr,
917 => false,
918
919 .v0,
920 .v1,
921 .v2,
922 .v3,
923 .v4,
924 .v5,
925 .v6,
926 .v7,
927 .v8,
928 .v9,
929 .v10,
930 .v11,
931 .v12,
932 .v13,
933 .v14,
934 .v15,
935 .v16,
936 .v17,
937 .v18,
938 .v19,
939 .v20,
940 .v21,
941 .v22,
942 .v23,
943 .v24,
944 .v25,
945 .v26,
946 .v27,
947 .v28,
948 .v29,
949 .v30,
950 .v31,
951
952 .p0,
953 .p1,
954 .p2,
955 .p3,
956 .p4,
957 .p5,
958 .p6,
959 .p7,
960 .p8,
961 .p9,
962 .p10,
963 .p11,
964 .p12,
965 .p13,
966 .p14,
967 .p15,
968 => true,
969 };
970 }
971
972 pub fn encode(ra: Alias, comptime opts: struct { sp: bool = false, V: bool = false }) Encoded {
973 return @enumFromInt(@as(u5, switch (ra) {
974 .r0 => if (opts.V) unreachable else 0,
975 .r1 => if (opts.V) unreachable else 1,
976 .r2 => if (opts.V) unreachable else 2,
977 .r3 => if (opts.V) unreachable else 3,
978 .r4 => if (opts.V) unreachable else 4,
979 .r5 => if (opts.V) unreachable else 5,
980 .r6 => if (opts.V) unreachable else 6,
981 .r7 => if (opts.V) unreachable else 7,
982 .r8 => if (opts.V) unreachable else 8,
983 .r9 => if (opts.V) unreachable else 9,
984 .r10 => if (opts.V) unreachable else 10,
985 .r11 => if (opts.V) unreachable else 11,
986 .r12 => if (opts.V) unreachable else 12,
987 .r13 => if (opts.V) unreachable else 13,
988 .r14 => if (opts.V) unreachable else 14,
989 .r15 => if (opts.V) unreachable else 15,
990 .r16 => if (opts.V) unreachable else 16,
991 .r17 => if (opts.V) unreachable else 17,
992 .r18 => if (opts.V) unreachable else 18,
993 .r19 => if (opts.V) unreachable else 19,
994 .r20 => if (opts.V) unreachable else 20,
995 .r21 => if (opts.V) unreachable else 21,
996 .r22 => if (opts.V) unreachable else 22,
997 .r23 => if (opts.V) unreachable else 23,
998 .r24 => if (opts.V) unreachable else 24,
999 .r25 => if (opts.V) unreachable else 25,
1000 .r26 => if (opts.V) unreachable else 26,
1001 .r27 => if (opts.V) unreachable else 27,
1002 .r28 => if (opts.V) unreachable else 28,
1003 .r29 => if (opts.V) unreachable else 29,
1004 .r30 => if (opts.V) unreachable else 30,
1005 .zr => if (opts.sp or opts.V) unreachable else 31,
1006 .sp => if (opts.sp and !opts.V) 31 else unreachable,
1007 .pc => unreachable,
1008 .v0 => if (opts.V) 0 else unreachable,
1009 .v1 => if (opts.V) 1 else unreachable,
1010 .v2 => if (opts.V) 2 else unreachable,
1011 .v3 => if (opts.V) 3 else unreachable,
1012 .v4 => if (opts.V) 4 else unreachable,
1013 .v5 => if (opts.V) 5 else unreachable,
1014 .v6 => if (opts.V) 6 else unreachable,
1015 .v7 => if (opts.V) 7 else unreachable,
1016 .v8 => if (opts.V) 8 else unreachable,
1017 .v9 => if (opts.V) 9 else unreachable,
1018 .v10 => if (opts.V) 10 else unreachable,
1019 .v11 => if (opts.V) 11 else unreachable,
1020 .v12 => if (opts.V) 12 else unreachable,
1021 .v13 => if (opts.V) 13 else unreachable,
1022 .v14 => if (opts.V) 14 else unreachable,
1023 .v15 => if (opts.V) 15 else unreachable,
1024 .v16 => if (opts.V) 16 else unreachable,
1025 .v17 => if (opts.V) 17 else unreachable,
1026 .v18 => if (opts.V) 18 else unreachable,
1027 .v19 => if (opts.V) 19 else unreachable,
1028 .v20 => if (opts.V) 20 else unreachable,
1029 .v21 => if (opts.V) 21 else unreachable,
1030 .v22 => if (opts.V) 22 else unreachable,
1031 .v23 => if (opts.V) 23 else unreachable,
1032 .v24 => if (opts.V) 24 else unreachable,
1033 .v25 => if (opts.V) 25 else unreachable,
1034 .v26 => if (opts.V) 26 else unreachable,
1035 .v27 => if (opts.V) 27 else unreachable,
1036 .v28 => if (opts.V) 28 else unreachable,
1037 .v29 => if (opts.V) 29 else unreachable,
1038 .v30 => if (opts.V) 30 else unreachable,
1039 .v31 => if (opts.V) 31 else unreachable,
1040 .fpcr, .fpsr => unreachable,
1041 .p0, .p1, .p2, .p3, .p4, .p5, .p6, .p7, .p8, .p9, .p10, .p11, .p12, .p13, .p14, .p15 => unreachable,
1042 .ffr => unreachable,
1043 }));
1044 }
1045 };
1046
1047 pub fn isVector(reg: Register) bool {
1048 return reg.alias.isVector();
1049 }
1050
1051 pub fn size(reg: Register) ?u5 {
1052 return format: switch (reg.format) {
1053 .alias => unreachable,
1054 .integer => |sf| switch (sf) {
1055 .word => 4,
1056 .doubleword => 8,
1057 },
1058 .vector => |vs| switch (vs) {
1059 .byte => 1,
1060 .word => 2,
1061 .single => 4,
1062 .double => 8,
1063 .quad => 16,
1064 .scalable, .predicate => null,
1065 },
1066 .arrangement => |arrangement| switch (arrangement) {
1067 .@"2d", .@"4s", .@"8h", .@"16b" => 16,
1068 .@"1d", .@"2s", .@"4h", .@"8b" => 8,
1069 },
1070 .element => |element| continue :format .{ .vector = element.size },
1071 };
1072 }
1073
1074 pub fn parse(reg: []const u8) ?Register {
1075 return if (reg.len == 0) null else switch (reg[0]) {
1076 else => null,
1077 'r' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
1078 0...30 => .{
1079 .alias = @enumFromInt(@intFromEnum(Alias.r0) + n),
1080 .format = .alias,
1081 },
1082 31 => null,
1083 } else |_| null,
1084 'x' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
1085 0...30 => .{
1086 .alias = @enumFromInt(@intFromEnum(Alias.r0) + n),
1087 .format = .{ .integer = .doubleword },
1088 },
1089 31 => null,
1090 } else |_| if (std.mem.eql(u8, reg, "xzr")) .xzr else null,
1091 'w' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
1092 0...30 => .{
1093 .alias = @enumFromInt(@intFromEnum(Alias.r0) + n),
1094 .format = .{ .integer = .word },
1095 },
1096 31 => null,
1097 } else |_| if (std.mem.eql(u8, reg, "wzr"))
1098 .wzr
1099 else if (std.mem.eql(u8, reg, "wsp"))
1100 .wsp
1101 else
1102 null,
1103 'i' => return if (std.mem.eql(u8, reg, "ip") or std.mem.eql(u8, reg, "ip0"))
1104 .ip0
1105 else if (std.mem.eql(u8, reg, "ip1"))
1106 .ip1
1107 else
1108 null,
1109 'f' => return if (std.mem.eql(u8, reg, "fp")) .fp else null,
1110 'p' => return if (std.mem.eql(u8, reg, "pc")) .pc else null,
1111 'v' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
1112 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
1113 .format = .alias,
1114 } else |_| null,
1115 'q' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
1116 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
1117 .format = .{ .scalar = .quad },
1118 } else |_| null,
1119 'd' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
1120 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
1121 .format = .{ .scalar = .double },
1122 } else |_| null,
1123 's' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
1124 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
1125 .format = .{ .scalar = .single },
1126 } else |_| if (std.mem.eql(u8, reg, "sp")) .sp else null,
1127 'h' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
1128 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
1129 .format = .{ .scalar = .half },
1130 } else |_| null,
1131 'b' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
1132 .alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
1133 .format = .{ .scalar = .byte },
1134 } else |_| null,
1135 };
1136 }
1137
1138 pub fn fmt(reg: Register) aarch64.Disassemble.RegisterFormatter {
1139 return reg.fmtCase(.lower);
1140 }
1141 pub fn fmtCase(reg: Register, case: aarch64.Disassemble.Case) aarch64.Disassemble.RegisterFormatter {
1142 return .{ .reg = reg, .case = case };
1143 }
1144};
1145
1146/// C1.2.4 Condition code
1147pub const ConditionCode = enum(u4) {
1148 /// integer: Equal
1149 /// floating-point: Equal
1150 /// Z == 1
1151 eq = 0b0000,
1152 /// integer: Not equal
1153 /// floating-point: Not equal or unordered
1154 /// Z == 0
1155 ne = 0b0001,
1156 /// integer: Unsigned higher or same
1157 /// floating-point: Greater than, equal, or unordered
1158 /// C == 1
1159 hs = 0b0010,
1160 /// integer: Unsigned lower
1161 /// floating-point: Less than
1162 /// C == 0
1163 lo = 0b0011,
1164 /// integer: Minus, negative
1165 /// floating-point: Less than
1166 /// N == 1
1167 mi = 0b0100,
1168 /// integer: Plus, positive or zero
1169 /// floating-point: Greater than, equal, or unordered
1170 /// N == 0
1171 pl = 0b0101,
1172 /// integer: Overflow
1173 /// floating-point: Unordered
1174 /// V == 1
1175 vs = 0b0110,
1176 /// integer: No overflow
1177 /// floating-point: Ordered
1178 /// V == 0
1179 vc = 0b0111,
1180 /// integer: Unsigned higher
1181 /// floating-point: Greater than, or unordered
1182 /// C == 1 and Z == 0
1183 hi = 0b1000,
1184 /// integer: Unsigned lower or same
1185 /// floating-point: Less than or equal
1186 /// C == 0 or Z == 1
1187 ls = 0b1001,
1188 /// integer: Signed greater than or equal
1189 /// floating-point: Greater than or equal
1190 /// N == V
1191 ge = 0b1010,
1192 /// integer: Signed less than
1193 /// floating-point: Less than, or unordered
1194 /// N != V
1195 lt = 0b1011,
1196 /// integer: Signed greater than
1197 /// floating-point: Greater than
1198 /// Z == 0 and N == V
1199 gt = 0b1100,
1200 /// integer: Signed less than or equal
1201 /// floating-point: Less than, equal, or unordered
1202 /// Z == 1 or N != V
1203 le = 0b1101,
1204 /// integer: Always
1205 /// floating-point: Always
1206 /// true
1207 al = 0b1110,
1208 /// integer: Always
1209 /// floating-point: Always
1210 /// true
1211 nv = 0b1111,
1212 /// Carry set
1213 /// C == 1
1214 pub const cs: ConditionCode = .hs;
1215 /// Carry clear
1216 /// C == 0
1217 pub const cc: ConditionCode = .lo;
1218
1219 pub fn invert(cond: ConditionCode) ConditionCode {
1220 return @enumFromInt(@intFromEnum(cond) ^ 0b0001);
1221 }
1222};
1223
1224/// C4.1 A64 instruction set encoding
1225pub const Instruction = packed union {
1226 group: Group,
1227 reserved: Reserved,
1228 sme: Sme,
1229 sve: Sve,
1230 data_processing_immediate: DataProcessingImmediate,
1231 branch_exception_generating_system: BranchExceptionGeneratingSystem,
1232 load_store: LoadStore,
1233 data_processing_register: DataProcessingRegister,
1234 data_processing_vector: DataProcessingVector,
1235
1236 /// Table C4-1 Main encoding table for the A64 instruction set
1237 pub const Group = packed struct {
1238 encoded0: u25,
1239 op1: u4,
1240 encoded29: u2,
1241 op0: u1,
1242 };
1243
1244 /// C4.1.1 Reserved
1245 pub const Reserved = packed union {
1246 group: @This().Group,
1247 udf: Udf,
1248
1249 /// Table C4-2 Encoding table for the Reserved group
1250 pub const Group = packed struct {
1251 encoded0: u16,
1252 op1: u9,
1253 decoded25: u4 = 0b0000,
1254 op0: u2,
1255 decoded31: u1 = 0b0,
1256 };
1257
1258 /// C6.2.387 UDF
1259 pub const Udf = packed struct {
1260 imm16: u16,
1261 decoded16: u16 = 0b0000000000000000,
1262 };
1263
1264 pub const Decoded = union(enum) {
1265 unallocated,
1266 udf: Udf,
1267 };
1268 pub fn decode(inst: @This()) @This().Decoded {
1269 return switch (inst.group.op0) {
1270 0b00 => switch (inst.group.op1) {
1271 0b000000000 => .{ .udf = inst.udf },
1272 else => .unallocated,
1273 },
1274 else => .unallocated,
1275 };
1276 }
1277 };
1278
1279 /// C4.1.2 SME encodings
1280 pub const Sme = packed union {
1281 group: @This().Group,
1282
1283 /// Table C4-3 Encodings table for the SME encodings group
1284 pub const Group = packed struct {
1285 encoded0: u2,
1286 op2: u3,
1287 encoded5: u5,
1288 op1: u15,
1289 decoded25: u4 = 0b0000,
1290 op0: u2,
1291 decoded31: u1 = 0b1,
1292 };
1293 };
1294
1295 /// C4.1.30 SVE encodings
1296 pub const Sve = packed union {
1297 group: @This().Group,
1298
1299 /// Table C4-31 Encoding table for the SVE encodings group
1300 pub const Group = packed struct {
1301 encoded0: u4,
1302 op2: u1,
1303 encoded5: u5,
1304 op1: u15,
1305 decoded25: u4 = 0b0010,
1306 op0: u3,
1307 };
1308 };
1309
1310 /// C4.1.86 Data Processing -- Immediate
1311 pub const DataProcessingImmediate = packed union {
1312 group: @This().Group,
1313 pc_relative_addressing: PcRelativeAddressing,
1314 add_subtract_immediate: AddSubtractImmediate,
1315 add_subtract_immediate_with_tags: AddSubtractImmediateWithTags,
1316 logical_immediate: LogicalImmediate,
1317 move_wide_immediate: MoveWideImmediate,
1318 bitfield: Bitfield,
1319 extract: Extract,
1320
1321 /// Table C4-87 Encoding table for the Data Processing -- Immediate group
1322 pub const Group = packed struct {
1323 encoded0: u23,
1324 op0: u3,
1325 decoded26: u3 = 0b100,
1326 encoded29: u3,
1327 };
1328
1329 /// PC-rel. addressing
1330 pub const PcRelativeAddressing = packed union {
1331 group: @This().Group,
1332 adr: Adr,
1333 adrp: Adrp,
1334
1335 pub const Group = packed struct {
1336 Rd: Register.Encoded,
1337 immhi: i19,
1338 decoded24: u5 = 0b10000,
1339 immlo: u2,
1340 op: Op,
1341 };
1342
1343 /// C6.2.10 ADR
1344 pub const Adr = packed struct {
1345 Rd: Register.Encoded,
1346 immhi: i19,
1347 decoded24: u5 = 0b10000,
1348 immlo: u2,
1349 op: Op = .adr,
1350 };
1351
1352 /// C6.2.11 ADRP
1353 pub const Adrp = packed struct {
1354 Rd: Register.Encoded,
1355 immhi: i19,
1356 decoded24: u5 = 0b10000,
1357 immlo: u2,
1358 op: Op = .adrp,
1359 };
1360
1361 pub const Op = enum(u1) {
1362 adr = 0b0,
1363 adrp = 0b1,
1364 };
1365 };
1366
1367 /// Add/subtract (immediate)
1368 pub const AddSubtractImmediate = packed union {
1369 group: @This().Group,
1370 add: Add,
1371 adds: Adds,
1372 sub: Sub,
1373 subs: Subs,
1374
1375 pub const Group = packed struct {
1376 Rd: Register.Encoded,
1377 Rn: Register.Encoded,
1378 imm12: u12,
1379 sh: Shift,
1380 decoded23: u6 = 0b100010,
1381 S: bool,
1382 op: AddSubtractOp,
1383 sf: Register.IntegerSize,
1384 };
1385
1386 /// C6.2.4 ADD (immediate)
1387 pub const Add = packed struct {
1388 Rd: Register.Encoded,
1389 Rn: Register.Encoded,
1390 imm12: u12,
1391 sh: Shift,
1392 decoded23: u6 = 0b100010,
1393 S: bool = false,
1394 op: AddSubtractOp = .add,
1395 sf: Register.IntegerSize,
1396 };
1397
1398 /// C6.2.8 ADDS (immediate)
1399 pub const Adds = packed struct {
1400 Rd: Register.Encoded,
1401 Rn: Register.Encoded,
1402 imm12: u12,
1403 sh: Shift,
1404 decoded23: u6 = 0b100010,
1405 S: bool = true,
1406 op: AddSubtractOp = .add,
1407 sf: Register.IntegerSize,
1408 };
1409
1410 /// C6.2.357 SUB (immediate)
1411 pub const Sub = packed struct {
1412 Rd: Register.Encoded,
1413 Rn: Register.Encoded,
1414 imm12: u12,
1415 sh: Shift,
1416 decoded23: u6 = 0b100010,
1417 S: bool = false,
1418 op: AddSubtractOp = .sub,
1419 sf: Register.IntegerSize,
1420 };
1421
1422 /// C6.2.363 SUBS (immediate)
1423 pub const Subs = packed struct {
1424 Rd: Register.Encoded,
1425 Rn: Register.Encoded,
1426 imm12: u12,
1427 sh: Shift,
1428 decoded23: u6 = 0b100010,
1429 S: bool = true,
1430 op: AddSubtractOp = .sub,
1431 sf: Register.IntegerSize,
1432 };
1433
1434 pub const Shift = enum(u1) {
1435 @"0" = 0b0,
1436 @"12" = 0b1,
1437 };
1438 };
1439
1440 /// Add/subtract (immediate, with tags)
1441 pub const AddSubtractImmediateWithTags = packed union {
1442 group: @This().Group,
1443
1444 pub const Group = packed struct {
1445 Rd: Register.Encoded,
1446 Rn: Register.Encoded,
1447 uimm4: u4,
1448 op3: u2,
1449 uimm6: u6,
1450 o2: u1,
1451 decoded23: u6 = 0b100011,
1452 S: bool,
1453 op: AddSubtractOp,
1454 sf: Register.IntegerSize,
1455 };
1456 };
1457
1458 /// Logical (immediate)
1459 pub const LogicalImmediate = packed union {
1460 group: @This().Group,
1461 @"and": And,
1462 orr: Orr,
1463 eor: Eor,
1464 ands: Ands,
1465
1466 pub const Group = packed struct {
1467 Rd: Register.Encoded,
1468 Rn: Register.Encoded,
1469 imm: Bitmask,
1470 decoded23: u6 = 0b100100,
1471 opc: LogicalOpc,
1472 sf: Register.IntegerSize,
1473 };
1474
1475 /// C6.2.12 AND (immediate)
1476 pub const And = packed struct {
1477 Rd: Register.Encoded,
1478 Rn: Register.Encoded,
1479 imm: Bitmask,
1480 decoded23: u6 = 0b100100,
1481 opc: LogicalOpc = .@"and",
1482 sf: Register.IntegerSize,
1483 };
1484
1485 /// C6.2.240 ORR (immediate)
1486 pub const Orr = packed struct {
1487 Rd: Register.Encoded,
1488 Rn: Register.Encoded,
1489 imm: Bitmask,
1490 decoded23: u6 = 0b100100,
1491 opc: LogicalOpc = .orr,
1492 sf: Register.IntegerSize,
1493 };
1494
1495 /// C6.2.119 EOR (immediate)
1496 pub const Eor = packed struct {
1497 Rd: Register.Encoded,
1498 Rn: Register.Encoded,
1499 imm: Bitmask,
1500 decoded23: u6 = 0b100100,
1501 opc: LogicalOpc = .eor,
1502 sf: Register.IntegerSize,
1503 };
1504
1505 /// C6.2.14 ANDS (immediate)
1506 pub const Ands = packed struct {
1507 Rd: Register.Encoded,
1508 Rn: Register.Encoded,
1509 imm: Bitmask,
1510 decoded23: u6 = 0b100100,
1511 opc: LogicalOpc = .ands,
1512 sf: Register.IntegerSize,
1513 };
1514
1515 pub const Decoded = union(enum) {
1516 unallocated,
1517 @"and": And,
1518 orr: Orr,
1519 eor: Eor,
1520 ands: Ands,
1521 };
1522 pub fn decode(inst: @This()) @This().Decoded {
1523 return if (!inst.group.imm.validImmediate(inst.group.sf))
1524 .unallocated
1525 else switch (inst.group.opc) {
1526 .@"and" => .{ .@"and" = inst.@"and" },
1527 .orr => .{ .orr = inst.orr },
1528 .eor => .{ .eor = inst.eor },
1529 .ands => .{ .ands = inst.ands },
1530 };
1531 }
1532 };
1533
1534 /// Move wide (immediate)
1535 pub const MoveWideImmediate = packed union {
1536 group: @This().Group,
1537 movn: Movn,
1538 movz: Movz,
1539 movk: Movk,
1540
1541 pub const Group = packed struct {
1542 Rd: Register.Encoded,
1543 imm16: u16,
1544 hw: Hw,
1545 decoded23: u6 = 0b100101,
1546 opc: Opc,
1547 sf: Register.IntegerSize,
1548 };
1549
1550 /// C6.2.226 MOVN
1551 pub const Movn = packed struct {
1552 Rd: Register.Encoded,
1553 imm16: u16,
1554 hw: Hw,
1555 decoded23: u6 = 0b100101,
1556 opc: Opc = .movn,
1557 sf: Register.IntegerSize,
1558 };
1559
1560 /// C6.2.227 MOVZ
1561 pub const Movz = packed struct {
1562 Rd: Register.Encoded,
1563 imm16: u16,
1564 hw: Hw,
1565 decoded23: u6 = 0b100101,
1566 opc: Opc = .movz,
1567 sf: Register.IntegerSize,
1568 };
1569
1570 /// C6.2.225 MOVK
1571 pub const Movk = packed struct {
1572 Rd: Register.Encoded,
1573 imm16: u16,
1574 hw: Hw,
1575 decoded23: u6 = 0b100101,
1576 opc: Opc = .movk,
1577 sf: Register.IntegerSize,
1578 };
1579
1580 pub const Hw = enum(u2) {
1581 @"0" = 0b00,
1582 @"16" = 0b01,
1583 @"32" = 0b10,
1584 @"48" = 0b11,
1585
1586 pub fn int(hw: Hw) u6 {
1587 return switch (hw) {
1588 .@"0" => 0,
1589 .@"16" => 16,
1590 .@"32" => 32,
1591 .@"48" => 48,
1592 };
1593 }
1594
1595 pub fn sf(hw: Hw) Register.IntegerSize {
1596 return switch (hw) {
1597 .@"0", .@"16" => .word,
1598 .@"32", .@"48" => .doubleword,
1599 };
1600 }
1601 };
1602
1603 pub const Opc = enum(u2) {
1604 movn = 0b00,
1605 movz = 0b10,
1606 movk = 0b11,
1607 _,
1608 };
1609
1610 pub const Decoded = union(enum) {
1611 unallocated,
1612 movn: Movn,
1613 movz: Movz,
1614 movk: Movk,
1615 };
1616 pub fn decode(inst: @This()) @This().Decoded {
1617 return if (inst.group.sf == .word and inst.group.hw.sf() == .doubleword)
1618 .unallocated
1619 else switch (inst.group.opc) {
1620 _ => .unallocated,
1621 .movn => .{ .movn = inst.movn },
1622 .movz => .{ .movz = inst.movz },
1623 .movk => .{ .movk = inst.movk },
1624 };
1625 }
1626 };
1627
1628 /// Bitfield
1629 pub const Bitfield = packed union {
1630 group: @This().Group,
1631 sbfm: Sbfm,
1632 bfm: Bfm,
1633 ubfm: Ubfm,
1634
1635 pub const Group = packed struct {
1636 Rd: Register.Encoded,
1637 Rn: Register.Encoded,
1638 imm: Bitmask,
1639 decoded23: u6 = 0b100110,
1640 opc: Opc,
1641 sf: Register.IntegerSize,
1642 };
1643
1644 pub const Sbfm = packed struct {
1645 Rd: Register.Encoded,
1646 Rn: Register.Encoded,
1647 imm: Bitmask,
1648 decoded23: u6 = 0b100110,
1649 opc: Opc = .sbfm,
1650 sf: Register.IntegerSize,
1651 };
1652
1653 pub const Bfm = packed struct {
1654 Rd: Register.Encoded,
1655 Rn: Register.Encoded,
1656 imm: Bitmask,
1657 decoded23: u6 = 0b100110,
1658 opc: Opc = .bfm,
1659 sf: Register.IntegerSize,
1660 };
1661
1662 pub const Ubfm = packed struct {
1663 Rd: Register.Encoded,
1664 Rn: Register.Encoded,
1665 imm: Bitmask,
1666 decoded23: u6 = 0b100110,
1667 opc: Opc = .ubfm,
1668 sf: Register.IntegerSize,
1669 };
1670
1671 pub const Opc = enum(u2) {
1672 sbfm = 0b00,
1673 bfm = 0b01,
1674 ubfm = 0b10,
1675 _,
1676 };
1677
1678 pub const Decoded = union(enum) {
1679 unallocated,
1680 sbfm: Sbfm,
1681 bfm: Bfm,
1682 ubfm: Ubfm,
1683 };
1684 pub fn decode(inst: @This()) @This().Decoded {
1685 return if (!inst.group.imm.validBitfield(inst.group.sf))
1686 .unallocated
1687 else switch (inst.group.opc) {
1688 _ => .unallocated,
1689 .sbfm => .{ .sbfm = inst.sbfm },
1690 .bfm => .{ .bfm = inst.bfm },
1691 .ubfm => .{ .ubfm = inst.ubfm },
1692 };
1693 }
1694 };
1695
1696 /// Extract
1697 pub const Extract = packed union {
1698 group: @This().Group,
1699 extr: Extr,
1700
1701 pub const Group = packed struct {
1702 Rd: Register.Encoded,
1703 Rn: Register.Encoded,
1704 imms: u6,
1705 Rm: Register.Encoded,
1706 o0: u1,
1707 N: Register.IntegerSize,
1708 decoded23: u6 = 0b100111,
1709 op21: u2,
1710 sf: Register.IntegerSize,
1711 };
1712
1713 pub const Extr = packed struct {
1714 Rd: Register.Encoded,
1715 Rn: Register.Encoded,
1716 imms: u6,
1717 Rm: Register.Encoded,
1718 o0: u1 = 0b0,
1719 N: Register.IntegerSize,
1720 decoded23: u6 = 0b100111,
1721 op21: u2 = 0b00,
1722 sf: Register.IntegerSize,
1723 };
1724
1725 pub const Decoded = union(enum) {
1726 unallocated,
1727 extr: Extr,
1728 };
1729 pub fn decode(inst: @This()) @This().Decoded {
1730 return switch (inst.group.op21) {
1731 0b01, 0b10...0b11 => .unallocated,
1732 0b00 => switch (inst.group.o0) {
1733 0b1 => .unallocated,
1734 0b0 => if ((inst.group.sf == .word and @as(u1, @truncate(inst.group.imms >> 5)) == 0b1) or
1735 inst.group.sf != inst.group.N)
1736 .unallocated
1737 else
1738 .{ .extr = inst.extr },
1739 },
1740 };
1741 }
1742 };
1743
1744 pub const Bitmask = packed struct {
1745 imms: u6,
1746 immr: u6,
1747 N: Register.IntegerSize,
1748
1749 fn lenHsb(bitmask: Bitmask) u7 {
1750 return @bitCast(packed struct {
1751 not_imms: u6,
1752 N: Register.IntegerSize,
1753 }{ .not_imms = ~bitmask.imms, .N = bitmask.N });
1754 }
1755
1756 fn validImmediate(bitmask: Bitmask, sf: Register.IntegerSize) bool {
1757 if (sf == .word and bitmask.N == .doubleword) return false;
1758 const len_hsb = bitmask.lenHsb();
1759 return (len_hsb -% 1) & len_hsb != 0b0_000000;
1760 }
1761
1762 fn validBitfield(bitmask: Bitmask, sf: Register.IntegerSize) bool {
1763 if (sf != bitmask.N) return false;
1764 if (sf == .word and (@as(u1, @truncate(bitmask.immr >> 5)) != 0b0 or
1765 @as(u1, @truncate(bitmask.imms >> 5)) != 0b0)) return false;
1766 const len_hsb = bitmask.lenHsb();
1767 return len_hsb >= 0b0_000010;
1768 }
1769
1770 fn decode(bitmask: Bitmask, sf: Register.IntegerSize) struct { u64, u64 } {
1771 const esize = @as(u7, 1 << 6) >> @clz(bitmask.lenHsb());
1772 const levels: u6 = @intCast(esize - 1);
1773 const s = bitmask.imms & levels;
1774 const r = bitmask.immr & levels;
1775 const d = (s -% r) & levels;
1776 const welem = @as(u64, std.math.maxInt(u64)) >> (63 - s);
1777 const telem = @as(u64, std.math.maxInt(u64)) >> (63 - d);
1778 const emask = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - esize);
1779 const rmask = @divExact(std.math.maxInt(u64), emask);
1780 const wmask = std.math.rotr(u64, welem * rmask, r);
1781 const tmask = telem * rmask;
1782 return switch (sf) {
1783 .word => .{ @as(u32, @truncate(wmask)), @as(u32, @truncate(tmask)) },
1784 .doubleword => .{ wmask, tmask },
1785 };
1786 }
1787
1788 pub fn decodeImmediate(bitmask: Bitmask, sf: Register.IntegerSize) u64 {
1789 assert(bitmask.validImmediate(sf));
1790 const imm, _ = bitmask.decode(sf);
1791 return imm;
1792 }
1793
1794 pub fn decodeBitfield(bitmask: Bitmask, sf: Register.IntegerSize) struct { u64, u64 } {
1795 assert(bitmask.validBitfield(sf));
1796 return bitmask.decode(sf);
1797 }
1798
1799 pub fn moveWidePreferred(bitmask: Bitmask, sf: Register.IntegerSize) bool {
1800 const s = bitmask.imms;
1801 const r = bitmask.immr;
1802 const width: u7 = switch (sf) {
1803 .word => 32,
1804 .doubleword => 64,
1805 };
1806 if (sf != bitmask.N) return false;
1807 if (sf == .word and @as(u1, @truncate(s >> 5)) != 0b0) return false;
1808 if (s < 16) return (-%r % 16) <= (15 - s);
1809 if (s >= width - 15) return (r % 16) <= (s - (width - 15));
1810 return false;
1811 }
1812 };
1813
1814 pub const Decoded = union(enum) {
1815 unallocated,
1816 pc_relative_addressing: PcRelativeAddressing,
1817 add_subtract_immediate: AddSubtractImmediate,
1818 add_subtract_immediate_with_tags: AddSubtractImmediateWithTags,
1819 logical_immediate: LogicalImmediate,
1820 move_wide_immediate: MoveWideImmediate,
1821 bitfield: Bitfield,
1822 extract: Extract,
1823 };
1824 pub fn decode(inst: @This()) @This().Decoded {
1825 return switch (inst.group.op0) {
1826 0b000, 0b001 => .{ .pc_relative_addressing = inst.pc_relative_addressing },
1827 0b010 => .{ .add_subtract_immediate = inst.add_subtract_immediate },
1828 0b011 => .{ .add_subtract_immediate_with_tags = inst.add_subtract_immediate_with_tags },
1829 0b100 => .{ .logical_immediate = inst.logical_immediate },
1830 0b101 => .{ .move_wide_immediate = inst.move_wide_immediate },
1831 0b110 => .{ .bitfield = inst.bitfield },
1832 0b111 => .{ .extract = inst.extract },
1833 };
1834 }
1835 };
1836
1837 /// C4.1.87 Branches, Exception Generating and System instructions
1838 pub const BranchExceptionGeneratingSystem = packed union {
1839 group: @This().Group,
1840 conditional_branch_immediate: ConditionalBranchImmediate,
1841 exception_generating: ExceptionGenerating,
1842 system_register_argument: SystemRegisterArgument,
1843 hints: Hints,
1844 barriers: Barriers,
1845 pstate: Pstate,
1846 system_result: SystemResult,
1847 system: System,
1848 system_register_move: SystemRegisterMove,
1849 unconditional_branch_register: UnconditionalBranchRegister,
1850 unconditional_branch_immediate: UnconditionalBranchImmediate,
1851 compare_branch_immediate: CompareBranchImmediate,
1852 test_branch_immediate: TestBranchImmediate,
1853
1854 /// Table C4-88 Encoding table for the Branches, Exception Generating and System instructions group
1855 pub const Group = packed struct {
1856 op2: u5,
1857 encoded5: u7,
1858 op1: u14,
1859 decoded26: u3 = 0b101,
1860 op0: u3,
1861 };
1862
1863 /// Conditional branch (immediate)
1864 pub const ConditionalBranchImmediate = packed union {
1865 group: @This().Group,
1866 b: B,
1867 bc: Bc,
1868
1869 pub const Group = packed struct {
1870 cond: ConditionCode,
1871 o0: u1,
1872 imm19: i19,
1873 o1: u1,
1874 decoded25: u7 = 0b0101010,
1875 };
1876
1877 /// C6.2.26 B.cond
1878 pub const B = packed struct {
1879 cond: ConditionCode,
1880 o0: u1 = 0b0,
1881 imm19: i19,
1882 o1: u1 = 0b0,
1883 decoded25: u7 = 0b0101010,
1884 };
1885
1886 /// C6.2.27 BC.cond
1887 pub const Bc = packed struct {
1888 cond: ConditionCode,
1889 o0: u1 = 0b1,
1890 imm19: i19,
1891 o1: u1 = 0b0,
1892 decoded25: u7 = 0b0101010,
1893 };
1894
1895 pub const Decoded = union(enum) {
1896 unallocated,
1897 b: B,
1898 bc: Bc,
1899 };
1900 pub fn decode(inst: @This()) @This().Decoded {
1901 return switch (inst.group.o1) {
1902 0b0 => switch (inst.group.o0) {
1903 0b0 => .{ .b = inst.b },
1904 0b1 => .{ .bc = inst.bc },
1905 },
1906 0b1 => .unallocated,
1907 };
1908 }
1909 };
1910
1911 /// Exception generating
1912 pub const ExceptionGenerating = packed union {
1913 group: @This().Group,
1914 svc: Svc,
1915 hvc: Hvc,
1916 smc: Smc,
1917 brk: Brk,
1918 hlt: Hlt,
1919 tcancel: Tcancel,
1920 dcps1: Dcps1,
1921 dcps2: Dcps2,
1922 dcps3: Dcps3,
1923
1924 pub const Group = packed struct {
1925 LL: u2,
1926 op2: u3,
1927 imm16: u16,
1928 opc: u3,
1929 decoded24: u8 = 0b11010100,
1930 };
1931
1932 /// C6.2.365 SVC
1933 pub const Svc = packed struct {
1934 decoded0: u2 = 0b01,
1935 decoded2: u3 = 0b000,
1936 imm16: u16,
1937 decoded21: u3 = 0b000,
1938 decoded24: u8 = 0b11010100,
1939 };
1940
1941 /// C6.2.128 HVC
1942 pub const Hvc = packed struct {
1943 decoded0: u2 = 0b10,
1944 decoded2: u3 = 0b000,
1945 imm16: u16,
1946 decoded21: u3 = 0b000,
1947 decoded24: u8 = 0b11010100,
1948 };
1949
1950 /// C6.2.283 SMC
1951 pub const Smc = packed struct {
1952 decoded0: u2 = 0b11,
1953 decoded2: u3 = 0b000,
1954 imm16: u16,
1955 decoded21: u3 = 0b000,
1956 decoded24: u8 = 0b11010100,
1957 };
1958
1959 /// C6.2.40 BRK
1960 pub const Brk = packed struct {
1961 decoded0: u2 = 0b00,
1962 decoded2: u3 = 0b000,
1963 imm16: u16,
1964 decoded21: u3 = 0b001,
1965 decoded24: u8 = 0b11010100,
1966 };
1967
1968 /// C6.2.127 HLT
1969 pub const Hlt = packed struct {
1970 decoded0: u2 = 0b00,
1971 decoded2: u3 = 0b000,
1972 imm16: u16,
1973 decoded21: u3 = 0b010,
1974 decoded24: u8 = 0b11010100,
1975 };
1976
1977 /// C6.2.376 TCANCEL
1978 pub const Tcancel = packed struct {
1979 decoded0: u2 = 0b00,
1980 decoded2: u3 = 0b000,
1981 imm16: u16,
1982 decoded21: u3 = 0b011,
1983 decoded24: u8 = 0b11010100,
1984 };
1985
1986 /// C6.2.110 DCPS1
1987 pub const Dcps1 = packed struct {
1988 LL: u2 = 0b01,
1989 decoded2: u3 = 0b000,
1990 imm16: u16,
1991 decoded21: u3 = 0b101,
1992 decoded24: u8 = 0b11010100,
1993 };
1994
1995 /// C6.2.110 DCPS2
1996 pub const Dcps2 = packed struct {
1997 LL: u2 = 0b10,
1998 decoded2: u3 = 0b000,
1999 imm16: u16,
2000 decoded21: u3 = 0b101,
2001 decoded24: u8 = 0b11010100,
2002 };
2003
2004 /// C6.2.110 DCPS3
2005 pub const Dcps3 = packed struct {
2006 LL: u2 = 0b11,
2007 decoded2: u3 = 0b000,
2008 imm16: u16,
2009 decoded21: u3 = 0b101,
2010 decoded24: u8 = 0b11010100,
2011 };
2012
2013 pub const Decoded = union(enum) {
2014 unallocated,
2015 svc: Svc,
2016 hvc: Hvc,
2017 smc: Smc,
2018 brk: Brk,
2019 hlt: Hlt,
2020 tcancel: Tcancel,
2021 dcps1: Dcps1,
2022 dcps2: Dcps2,
2023 dcps3: Dcps3,
2024 };
2025 pub fn decode(inst: @This()) @This().Decoded {
2026 return switch (inst.group.op2) {
2027 0b001 => .unallocated,
2028 0b010...0b011 => .unallocated,
2029 0b100...0b111 => .unallocated,
2030 0b000 => switch (inst.group.opc) {
2031 0b000 => switch (inst.group.LL) {
2032 0b00 => .unallocated,
2033 0b01 => .{ .svc = inst.svc },
2034 0b10 => .{ .hvc = inst.hvc },
2035 0b11 => .{ .smc = inst.smc },
2036 },
2037 0b001 => switch (inst.group.LL) {
2038 0b01 => .unallocated,
2039 0b00 => .{ .brk = inst.brk },
2040 0b10...0b11 => .unallocated,
2041 },
2042 0b010 => switch (inst.group.LL) {
2043 0b01 => .unallocated,
2044 0b00 => .{ .hlt = inst.hlt },
2045 0b10...0b11 => .unallocated,
2046 },
2047 0b011 => switch (inst.group.LL) {
2048 0b00 => .{ .tcancel = inst.tcancel },
2049 0b01 => .unallocated,
2050 0b10...0b11 => .unallocated,
2051 },
2052 0b100 => .unallocated,
2053 0b101 => switch (inst.group.LL) {
2054 0b00 => .unallocated,
2055 0b01 => .{ .dcps1 = inst.dcps1 },
2056 0b10 => .{ .dcps2 = inst.dcps2 },
2057 0b11 => .{ .dcps3 = inst.dcps3 },
2058 },
2059 0b110 => .unallocated,
2060 0b111 => .unallocated,
2061 },
2062 };
2063 }
2064 };
2065
2066 /// System instructions with register argument
2067 pub const SystemRegisterArgument = packed struct {
2068 Rt: Register.Encoded,
2069 op2: u3,
2070 CRm: u4,
2071 decoded12: u20 = 0b11010101000000110001,
2072 };
2073
2074 /// Hints
2075 pub const Hints = packed union {
2076 group: @This().Group,
2077 hint: Hint,
2078 nop: Nop,
2079 yield: Yield,
2080 wfe: Wfe,
2081 wfi: Wfi,
2082 sev: Sev,
2083 sevl: Sevl,
2084
2085 pub const Group = packed struct {
2086 decoded0: u5 = 0b11111,
2087 op2: u3,
2088 CRm: u4,
2089 decoded12: u20 = 0b11010101000000110010,
2090 };
2091
2092 /// C6.2.126 HINT
2093 pub const Hint = packed struct {
2094 decoded0: u5 = 0b11111,
2095 op2: u3,
2096 CRm: u4,
2097 decoded12: u4 = 0b0010,
2098 decoded16: u3 = 0b011,
2099 decoded19: u2 = 0b00,
2100 decoded21: u1 = 0b0,
2101 decoded22: u10 = 0b1101010100,
2102 };
2103
2104 /// C6.2.238 NOP
2105 pub const Nop = packed struct {
2106 decoded0: u5 = 0b11111,
2107 op2: u3 = 0b000,
2108 CRm: u4 = 0b0000,
2109 decoded12: u4 = 0b0010,
2110 decoded16: u3 = 0b011,
2111 decoded19: u2 = 0b00,
2112 decoded21: u1 = 0b0,
2113 decoded22: u10 = 0b1101010100,
2114 };
2115
2116 /// C6.2.402 YIELD
2117 pub const Yield = packed struct {
2118 decoded0: u5 = 0b11111,
2119 op2: u3 = 0b001,
2120 CRm: u4 = 0b0000,
2121 decoded12: u4 = 0b0010,
2122 decoded16: u3 = 0b011,
2123 decoded19: u2 = 0b00,
2124 decoded21: u1 = 0b0,
2125 decoded22: u10 = 0b1101010100,
2126 };
2127
2128 /// C6.2.396 WFE
2129 pub const Wfe = packed struct {
2130 decoded0: u5 = 0b11111,
2131 op2: u3 = 0b010,
2132 CRm: u4 = 0b0000,
2133 decoded12: u4 = 0b0010,
2134 decoded16: u3 = 0b011,
2135 decoded19: u2 = 0b00,
2136 decoded21: u1 = 0b0,
2137 decoded22: u10 = 0b1101010100,
2138 };
2139
2140 /// C6.2.398 WFI
2141 pub const Wfi = packed struct {
2142 decoded0: u5 = 0b11111,
2143 op2: u3 = 0b011,
2144 CRm: u4 = 0b0000,
2145 decoded12: u4 = 0b0010,
2146 decoded16: u3 = 0b011,
2147 decoded19: u2 = 0b00,
2148 decoded21: u1 = 0b0,
2149 decoded22: u10 = 0b1101010100,
2150 };
2151
2152 /// C6.2.280 SEV
2153 pub const Sev = packed struct {
2154 decoded0: u5 = 0b11111,
2155 op2: u3 = 0b100,
2156 CRm: u4 = 0b0000,
2157 decoded12: u4 = 0b0010,
2158 decoded16: u3 = 0b011,
2159 decoded19: u2 = 0b00,
2160 decoded21: u1 = 0b0,
2161 decoded22: u10 = 0b1101010100,
2162 };
2163
2164 /// C6.2.280 SEVL
2165 pub const Sevl = packed struct {
2166 decoded0: u5 = 0b11111,
2167 op2: u3 = 0b101,
2168 CRm: u4 = 0b0000,
2169 decoded12: u4 = 0b0010,
2170 decoded16: u3 = 0b011,
2171 decoded19: u2 = 0b00,
2172 decoded21: u1 = 0b0,
2173 decoded22: u10 = 0b1101010100,
2174 };
2175
2176 pub const Decoded = union(enum) {
2177 hint: Hint,
2178 nop: Nop,
2179 yield: Yield,
2180 wfe: Wfe,
2181 wfi: Wfi,
2182 sev: Sev,
2183 sevl: Sevl,
2184 };
2185 pub fn decode(inst: @This()) @This().Decoded {
2186 return switch (inst.group.CRm) {
2187 else => .{ .hint = inst.hint },
2188 0b0000 => switch (inst.group.op2) {
2189 else => .{ .hint = inst.hint },
2190 0b000 => .{ .nop = inst.nop },
2191 0b001 => .{ .yield = inst.yield },
2192 0b010 => .{ .wfe = inst.wfe },
2193 0b011 => .{ .wfi = inst.wfi },
2194 0b100 => .{ .sev = inst.sev },
2195 0b101 => .{ .sevl = inst.sevl },
2196 },
2197 };
2198 }
2199 };
2200
2201 /// Barriers
2202 pub const Barriers = packed union {
2203 group: @This().Group,
2204 clrex: Clrex,
2205 dsb: Dsb,
2206 dmb: Dmb,
2207 isb: Isb,
2208 sb: Sb,
2209
2210 pub const Group = packed struct {
2211 Rt: Register.Encoded,
2212 op2: u3,
2213 CRm: u4,
2214 decoded12: u4 = 0b0011,
2215 decoded16: u3 = 0b011,
2216 decoded19: u2 = 0b00,
2217 decoded21: u1 = 0b0,
2218 decoded22: u10 = 0b1101010100,
2219 };
2220
2221 /// C6.2.56 CLREX
2222 pub const Clrex = packed struct {
2223 Rt: Register.Encoded = @enumFromInt(0b11111),
2224 op2: u3 = 0b010,
2225 CRm: u4,
2226 decoded12: u4 = 0b0011,
2227 decoded16: u3 = 0b011,
2228 decoded19: u2 = 0b00,
2229 decoded21: u1 = 0b0,
2230 decoded22: u10 = 0b1101010100,
2231 };
2232
2233 /// C6.2.116 DSB
2234 pub const Dsb = packed struct {
2235 Rt: Register.Encoded = @enumFromInt(0b11111),
2236 opc: u2 = 0b00,
2237 decoded7: u1 = 0b1,
2238 CRm: Option,
2239 decoded12: u4 = 0b0011,
2240 decoded16: u3 = 0b011,
2241 decoded19: u2 = 0b00,
2242 decoded21: u1 = 0b0,
2243 decoded22: u10 = 0b1101010100,
2244 };
2245
2246 /// C6.2.114 DMB
2247 pub const Dmb = packed struct {
2248 Rt: Register.Encoded = @enumFromInt(0b11111),
2249 opc: u2 = 0b01,
2250 decoded7: u1 = 0b1,
2251 CRm: Option,
2252 decoded12: u4 = 0b0011,
2253 decoded16: u3 = 0b011,
2254 decoded19: u2 = 0b00,
2255 decoded21: u1 = 0b0,
2256 decoded22: u10 = 0b1101010100,
2257 };
2258
2259 /// C6.2.131 ISB
2260 pub const Isb = packed struct {
2261 Rt: Register.Encoded = @enumFromInt(0b11111),
2262 opc: u2 = 0b10,
2263 decoded7: u1 = 0b1,
2264 CRm: Option,
2265 decoded12: u4 = 0b0011,
2266 decoded16: u3 = 0b011,
2267 decoded19: u2 = 0b00,
2268 decoded21: u1 = 0b0,
2269 decoded22: u10 = 0b1101010100,
2270 };
2271
2272 /// C6.2.264 SB
2273 pub const Sb = packed struct {
2274 Rt: Register.Encoded = @enumFromInt(0b11111),
2275 opc: u2 = 0b11,
2276 decoded7: u1 = 0b1,
2277 CRm: u4 = 0b0000,
2278 decoded12: u4 = 0b0011,
2279 decoded16: u3 = 0b011,
2280 decoded19: u2 = 0b00,
2281 decoded21: u1 = 0b0,
2282 decoded22: u10 = 0b1101010100,
2283 };
2284
2285 pub const Option = enum(u4) {
2286 oshld = 0b0001,
2287 oshst = 0b0010,
2288 osh = 0b0011,
2289 nshld = 0b0101,
2290 nshst = 0b0110,
2291 nsh = 0b0111,
2292 ishld = 0b1001,
2293 ishst = 0b1010,
2294 ish = 0b1011,
2295 ld = 0b1101,
2296 st = 0b1110,
2297 sy = 0b1111,
2298 _,
2299 };
2300 };
2301
2302 /// PSTATE
2303 pub const Pstate = packed struct {
2304 Rt: Register.Encoded,
2305 op2: u3,
2306 CRm: u4,
2307 decoded12: u4 = 0b0100,
2308 op1: u3,
2309 decoded19: u13 = 0b1101010100000,
2310 };
2311
2312 /// System with result
2313 pub const SystemResult = packed struct {
2314 Rt: Register.Encoded,
2315 op2: u3,
2316 CRm: u4,
2317 CRn: u4,
2318 op1: u3,
2319 decoded19: u13 = 0b1101010100100,
2320 };
2321
2322 /// System instructions
2323 pub const System = packed union {
2324 group: @This().Group,
2325 sys: Sys,
2326 sysl: Sysl,
2327
2328 pub const Group = packed struct {
2329 Rt: Register.Encoded,
2330 op2: u3,
2331 CRm: u4,
2332 CRn: u4,
2333 op1: u3,
2334 decoded19: u2 = 0b01,
2335 L: L,
2336 decoded22: u10 = 0b1101010100,
2337 };
2338
2339 /// C6.2.372 SYS
2340 pub const Sys = packed struct {
2341 Rt: Register.Encoded,
2342 op2: u3,
2343 CRm: u4,
2344 CRn: u4,
2345 op1: u3,
2346 decoded19: u2 = 0b01,
2347 L: L = .sys,
2348 decoded22: u10 = 0b1101010100,
2349 };
2350
2351 /// C6.2.373 SYSL
2352 pub const Sysl = packed struct {
2353 Rt: Register.Encoded,
2354 op2: u3,
2355 CRm: u4,
2356 CRn: u4,
2357 op1: u3,
2358 decoded19: u2 = 0b01,
2359 L: L = .sysl,
2360 decoded22: u10 = 0b1101010100,
2361 };
2362
2363 const L = enum(u1) {
2364 sys = 0b0,
2365 sysl = 0b1,
2366 };
2367
2368 pub const Decoded = union(enum) {
2369 sys: Sys,
2370 sysl: Sysl,
2371 };
2372 pub fn decode(inst: @This()) @This().Decoded {
2373 return switch (inst.group.L) {
2374 .sys => .{ .sys = inst.sys },
2375 .sysl => .{ .sysl = inst.sysl },
2376 };
2377 }
2378 };
2379
2380 /// System register move
2381 pub const SystemRegisterMove = packed union {
2382 group: @This().Group,
2383 msr: Msr,
2384 mrs: Mrs,
2385
2386 pub const Group = packed struct {
2387 Rt: Register.Encoded,
2388 op2: u3,
2389 CRm: u4,
2390 CRn: u4,
2391 op1: u3,
2392 o0: u1,
2393 decoded20: u1 = 0b1,
2394 L: L,
2395 decoded22: u10 = 0b1101010100,
2396 };
2397
2398 /// C6.2.230 MSR (register)
2399 pub const Msr = packed struct {
2400 Rt: Register.Encoded,
2401 op2: u3,
2402 CRm: u4,
2403 CRn: u4,
2404 op1: u3,
2405 o0: u1,
2406 decoded20: u1 = 0b1,
2407 L: L = .msr,
2408 decoded22: u10 = 0b1101010100,
2409 };
2410
2411 /// C6.2.228 MRS
2412 pub const Mrs = packed struct {
2413 Rt: Register.Encoded,
2414 op2: u3,
2415 CRm: u4,
2416 CRn: u4,
2417 op1: u3,
2418 o0: u1,
2419 decoded20: u1 = 0b1,
2420 L: L = .mrs,
2421 decoded22: u10 = 0b1101010100,
2422 };
2423
2424 pub const L = enum(u1) {
2425 msr = 0b0,
2426 mrs = 0b1,
2427 };
2428
2429 pub const Decoded = union(enum) {
2430 msr: Msr,
2431 mrs: Mrs,
2432 };
2433 pub fn decode(inst: @This()) @This().Decoded {
2434 return switch (inst.group.L) {
2435 .msr => .{ .msr = inst.msr },
2436 .mrs => .{ .mrs = inst.mrs },
2437 };
2438 }
2439 };
2440
2441 /// Unconditional branch (register)
2442 pub const UnconditionalBranchRegister = packed union {
2443 group: @This().Group,
2444 br: Br,
2445 blr: Blr,
2446 ret: Ret,
2447
2448 pub const Group = packed struct {
2449 op4: u5,
2450 Rn: Register.Encoded,
2451 op3: u6,
2452 op2: u5,
2453 opc: u4,
2454 decoded25: u7 = 0b1101011,
2455 };
2456
2457 /// C6.2.37 BR
2458 pub const Br = packed struct {
2459 Rm: Register.Encoded = @enumFromInt(0),
2460 Rn: Register.Encoded,
2461 M: bool = false,
2462 A: bool = false,
2463 decoded12: u4 = 0b0000,
2464 decoded16: u5 = 0b11111,
2465 op: u2 = 0b00,
2466 decoded23: u1 = 0b0,
2467 Z: bool = false,
2468 decoded25: u7 = 0b1101011,
2469 };
2470
2471 /// C6.2.35 BLR
2472 pub const Blr = packed struct {
2473 Rm: Register.Encoded = @enumFromInt(0),
2474 Rn: Register.Encoded,
2475 M: bool = false,
2476 A: bool = false,
2477 decoded12: u4 = 0b0000,
2478 decoded16: u5 = 0b11111,
2479 op: u2 = 0b01,
2480 decoded23: u1 = 0b0,
2481 Z: bool = false,
2482 decoded25: u7 = 0b1101011,
2483 };
2484
2485 /// C6.2.254 RET
2486 pub const Ret = packed struct {
2487 Rm: Register.Encoded = @enumFromInt(0),
2488 Rn: Register.Encoded,
2489 M: bool = false,
2490 A: bool = false,
2491 decoded12: u4 = 0b0000,
2492 decoded16: u5 = 0b11111,
2493 op: u2 = 0b10,
2494 decoded23: u1 = 0b0,
2495 Z: bool = false,
2496 decoded25: u7 = 0b1101011,
2497 };
2498
2499 pub const Decoded = union(enum) {
2500 unallocated,
2501 br: Br,
2502 blr: Blr,
2503 ret: Ret,
2504 };
2505 pub fn decode(inst: @This()) @This().Decoded {
2506 return switch (inst.group.op2) {
2507 else => .unallocated,
2508 0b11111 => switch (inst.group.opc) {
2509 0b0000 => switch (inst.group.op4) {
2510 else => .unallocated,
2511 0b00000 => .{ .br = inst.br },
2512 },
2513 0b0001 => switch (inst.group.op4) {
2514 else => .unallocated,
2515 0b00000 => .{ .blr = inst.blr },
2516 },
2517 0b0010 => switch (inst.group.op4) {
2518 else => .unallocated,
2519 0b00000 => .{ .ret = inst.ret },
2520 },
2521 else => .unallocated,
2522 },
2523 };
2524 }
2525 };
2526
2527 /// Unconditional branch (immediate)
2528 pub const UnconditionalBranchImmediate = packed union {
2529 group: @This().Group,
2530 b: B,
2531 bl: Bl,
2532
2533 pub const Group = packed struct {
2534 imm26: i26,
2535 decoded26: u5 = 0b00101,
2536 op: Op,
2537 };
2538
2539 /// C6.2.25 B
2540 pub const B = packed struct {
2541 imm26: i26,
2542 decoded26: u5 = 0b00101,
2543 op: Op = .b,
2544 };
2545
2546 /// C6.2.34 BL
2547 pub const Bl = packed struct {
2548 imm26: i26,
2549 decoded26: u5 = 0b00101,
2550 op: Op = .bl,
2551 };
2552
2553 pub const Op = enum(u1) {
2554 b = 0b0,
2555 bl = 0b1,
2556 };
2557 };
2558
2559 /// Compare and branch (immediate)
2560 pub const CompareBranchImmediate = packed union {
2561 group: @This().Group,
2562 cbz: Cbz,
2563 cbnz: Cbnz,
2564
2565 pub const Group = packed struct {
2566 Rt: Register.Encoded,
2567 imm19: i19,
2568 op: Op,
2569 decoded25: u6 = 0b011010,
2570 sf: Register.IntegerSize,
2571 };
2572
2573 /// C6.2.47 CBZ
2574 pub const Cbz = packed struct {
2575 Rt: Register.Encoded,
2576 imm19: i19,
2577 op: Op = .cbz,
2578 decoded25: u6 = 0b011010,
2579 sf: Register.IntegerSize,
2580 };
2581
2582 /// C6.2.46 CBNZ
2583 pub const Cbnz = packed struct {
2584 Rt: Register.Encoded,
2585 imm19: i19,
2586 op: Op = .cbnz,
2587 decoded25: u6 = 0b011010,
2588 sf: Register.IntegerSize,
2589 };
2590
2591 pub const Op = enum(u1) {
2592 cbz = 0b0,
2593 cbnz = 0b1,
2594 };
2595 };
2596
2597 /// Test and branch (immediate)
2598 pub const TestBranchImmediate = packed union {
2599 group: @This().Group,
2600 tbz: Tbz,
2601 tbnz: Tbnz,
2602
2603 pub const Group = packed struct {
2604 Rt: Register.Encoded,
2605 imm14: i14,
2606 b40: u5,
2607 op: Op,
2608 decoded25: u6 = 0b011011,
2609 b5: u1,
2610 };
2611
2612 /// C6.2.375 TBZ
2613 pub const Tbz = packed struct {
2614 Rt: Register.Encoded,
2615 imm14: i14,
2616 b40: u5,
2617 op: Op = .tbz,
2618 decoded25: u6 = 0b011011,
2619 b5: u1,
2620 };
2621
2622 /// C6.2.374 TBNZ
2623 pub const Tbnz = packed struct {
2624 Rt: Register.Encoded,
2625 imm14: i14,
2626 b40: u5,
2627 op: Op = .tbnz,
2628 decoded25: u6 = 0b011011,
2629 b5: u1,
2630 };
2631
2632 pub const Op = enum(u1) {
2633 tbz = 0b0,
2634 tbnz = 0b1,
2635 };
2636 };
2637
2638 pub const Decoded = union(enum) {
2639 unallocated,
2640 conditional_branch_immediate: ConditionalBranchImmediate,
2641 exception_generating: ExceptionGenerating,
2642 system_register_argument: SystemRegisterArgument,
2643 hints: Hints,
2644 barriers: Barriers,
2645 pstate: Pstate,
2646 system_result: SystemResult,
2647 system: System,
2648 system_register_move: SystemRegisterMove,
2649 unconditional_branch_register: UnconditionalBranchRegister,
2650 unconditional_branch_immediate: UnconditionalBranchImmediate,
2651 compare_branch_immediate: CompareBranchImmediate,
2652 test_branch_immediate: TestBranchImmediate,
2653 };
2654 pub fn decode(inst: @This()) @This().Decoded {
2655 return switch (inst.group.op0) {
2656 0b010 => switch (inst.group.op1) {
2657 0b000000000000000...0b01111111111111 => .{ .conditional_branch_immediate = inst.conditional_branch_immediate },
2658 else => .unallocated,
2659 },
2660 0b110 => switch (inst.group.op1) {
2661 0b00000000000000...0b00111111111111 => .{ .exception_generating = inst.exception_generating },
2662 0b01000000110001 => .{ .system_register_argument = inst.system_register_argument },
2663 0b01000000110010 => switch (inst.group.op2) {
2664 0b11111 => .{ .hints = inst.hints },
2665 else => .unallocated,
2666 },
2667 0b01000000110011 => .{ .barriers = inst.barriers },
2668 0b01000000000100,
2669 0b01000000010100,
2670 0b01000000100100,
2671 0b01000000110100,
2672 0b01000001000100,
2673 0b01000001010100,
2674 0b01000001100100,
2675 0b01000001110100,
2676 => .{ .pstate = inst.pstate },
2677 0b01001000000000...0b01001001111111 => .{ .system_result = inst.system_result },
2678 0b01000010000000...0b01000011111111, 0b01001010000000...0b01001011111111 => .{ .system = inst.system },
2679 0b01000100000000...0b01000111111111, 0b01001100000000...0b01001111111111 => .{ .system_register_move = inst.system_register_move },
2680 0b10000000000000...0b11111111111111 => .{ .unconditional_branch_register = inst.unconditional_branch_register },
2681 else => .unallocated,
2682 },
2683 0b000, 0b100 => .{ .unconditional_branch_immediate = inst.unconditional_branch_immediate },
2684 0b001, 0b101 => switch (inst.group.op1) {
2685 0b00000000000000...0b01111111111111 => .{ .compare_branch_immediate = inst.compare_branch_immediate },
2686 0b10000000000000...0b11111111111111 => .{ .test_branch_immediate = inst.test_branch_immediate },
2687 },
2688 else => .unallocated,
2689 };
2690 }
2691 };
2692
2693 /// C4.1.88 Loads and Stores
2694 pub const LoadStore = packed union {
2695 group: @This().Group,
2696 register_literal: RegisterLiteral,
2697 memory: Memory,
2698 no_allocate_pair_offset: NoAllocatePairOffset,
2699 register_pair_post_indexed: RegisterPairPostIndexed,
2700 register_pair_offset: RegisterPairOffset,
2701 register_pair_pre_indexed: RegisterPairPreIndexed,
2702 register_unscaled_immediate: RegisterUnscaledImmediate,
2703 register_immediate_post_indexed: RegisterImmediatePostIndexed,
2704 register_unprivileged: RegisterUnprivileged,
2705 register_immediate_pre_indexed: RegisterImmediatePreIndexed,
2706 register_register_offset: RegisterRegisterOffset,
2707 register_unsigned_immediate: RegisterUnsignedImmediate,
2708
2709 /// Table C4-89 Encoding table for the Loads and Stores group
2710 pub const Group = packed struct {
2711 encoded0: u10,
2712 op4: u2,
2713 encoded12: u4,
2714 op3: u6,
2715 encoded22: u1,
2716 op2: u2,
2717 decoded25: u1 = 0b0,
2718 op1: bool,
2719 decoded27: u1 = 0b1,
2720 op0: u4,
2721 };
2722
2723 /// Load register (literal)
2724 pub const RegisterLiteral = packed union {
2725 group: @This().Group,
2726 integer: Integer,
2727 vector: Vector,
2728
2729 pub const Group = packed struct {
2730 Rt: Register.Encoded,
2731 imm19: i19,
2732 decoded24: u2 = 0b00,
2733 V: bool,
2734 decoded27: u3 = 0b011,
2735 opc: u2,
2736 };
2737
2738 pub const Integer = packed union {
2739 group: @This().Group,
2740 ldr: Ldr,
2741 ldrsw: Ldrsw,
2742 prfm: Prfm,
2743
2744 pub const Group = packed struct {
2745 Rt: Register.Encoded,
2746 imm19: i19,
2747 decoded24: u2 = 0b00,
2748 V: bool = false,
2749 decoded27: u3 = 0b011,
2750 opc: u2,
2751 };
2752
2753 /// C6.2.167 LDR (literal)
2754 pub const Ldr = packed struct {
2755 Rt: Register.Encoded,
2756 imm19: i19,
2757 decoded24: u2 = 0b00,
2758 V: bool = false,
2759 decoded27: u3 = 0b011,
2760 sf: Register.IntegerSize,
2761 opc1: u1 = 0b0,
2762 };
2763
2764 /// C6.2.179 LDRSW (literal)
2765 pub const Ldrsw = packed struct {
2766 Rt: Register.Encoded,
2767 imm19: i19,
2768 decoded24: u2 = 0b00,
2769 V: bool = false,
2770 decoded27: u3 = 0b011,
2771 opc: u2 = 0b10,
2772 };
2773
2774 /// C6.2.248 PRFM (literal)
2775 pub const Prfm = packed struct {
2776 prfop: PrfOp,
2777 imm19: i19,
2778 decoded24: u2 = 0b00,
2779 V: bool = false,
2780 decoded27: u3 = 0b011,
2781 opc: u2 = 0b11,
2782 };
2783 };
2784
2785 pub const Vector = packed union {
2786 group: @This().Group,
2787 ldr: Ldr,
2788
2789 pub const Group = packed struct {
2790 Rt: Register.Encoded,
2791 imm19: i19,
2792 decoded24: u2 = 0b00,
2793 V: bool = true,
2794 decoded27: u3 = 0b011,
2795 opc: VectorSize,
2796 };
2797
2798 /// C7.2.192 LDR (literal, SIMD&FP)
2799 pub const Ldr = packed struct {
2800 Rt: Register.Encoded,
2801 imm19: i19,
2802 decoded24: u2 = 0b00,
2803 V: bool = true,
2804 decoded27: u3 = 0b011,
2805 opc: VectorSize,
2806 };
2807 };
2808
2809 pub const Decoded = union(enum) {
2810 integer: Integer,
2811 vector: Vector,
2812 };
2813 pub fn decode(inst: @This()) @This().Decoded {
2814 return switch (inst.group.V) {
2815 false => .{ .integer = inst.integer },
2816 true => .{ .vector = inst.vector },
2817 };
2818 }
2819 };
2820
2821 /// Memory Copy and Memory Set
2822 pub const Memory = packed struct {
2823 Rd: Register.Encoded,
2824 Rn: Register.Encoded,
2825 decoded10: u2 = 0b01,
2826 op2: u4,
2827 Rs: Register.Encoded,
2828 decoded21: u1 = 0b0,
2829 op1: u2,
2830 decoded24: u2 = 0b01,
2831 o0: u1,
2832 decoded27: u3 = 0b011,
2833 size: IntegerSize,
2834 };
2835
2836 /// Load/store no-allocate pair (offset)
2837 pub const NoAllocatePairOffset = packed struct {
2838 Rt: Register.Encoded,
2839 Rn: Register.Encoded,
2840 Rt2: Register.Encoded,
2841 imm7: i7,
2842 L: L,
2843 decoded23: u3 = 0b000,
2844 V: bool,
2845 decoded27: u3 = 0b101,
2846 opc: u2,
2847 };
2848
2849 /// Load/store register pair (post-indexed)
2850 pub const RegisterPairPostIndexed = packed union {
2851 group: @This().Group,
2852 integer: Integer,
2853 vector: Vector,
2854
2855 pub const Group = packed struct {
2856 Rt: Register.Encoded,
2857 Rn: Register.Encoded,
2858 Rt2: Register.Encoded,
2859 imm7: i7,
2860 L: L,
2861 decoded23: u3 = 0b001,
2862 V: bool,
2863 decoded27: u3 = 0b101,
2864 opc: u2,
2865 };
2866
2867 pub const Integer = packed union {
2868 group: @This().Group,
2869 stp: Stp,
2870 ldp: Ldp,
2871 ldpsw: Ldpsw,
2872
2873 pub const Group = packed struct {
2874 Rt: Register.Encoded,
2875 Rn: Register.Encoded,
2876 Rt2: Register.Encoded,
2877 imm7: i7,
2878 L: L,
2879 decoded23: u3 = 0b001,
2880 V: bool = false,
2881 decoded27: u3 = 0b101,
2882 opc: u2,
2883 };
2884
2885 /// C6.2.321 STP
2886 pub const Stp = packed struct {
2887 Rt: Register.Encoded,
2888 Rn: Register.Encoded,
2889 Rt2: Register.Encoded,
2890 imm7: i7,
2891 L: L = .store,
2892 decoded23: u3 = 0b001,
2893 V: bool = false,
2894 decoded27: u3 = 0b101,
2895 opc0: u1 = 0b0,
2896 sf: Register.IntegerSize,
2897 };
2898
2899 /// C6.2.164 LDP
2900 pub const Ldp = packed struct {
2901 Rt: Register.Encoded,
2902 Rn: Register.Encoded,
2903 Rt2: Register.Encoded,
2904 imm7: i7,
2905 L: L = .load,
2906 decoded23: u3 = 0b001,
2907 V: bool = false,
2908 decoded27: u3 = 0b101,
2909 opc0: u1 = 0b0,
2910 sf: Register.IntegerSize,
2911 };
2912
2913 /// C6.2.165 LDPSW
2914 pub const Ldpsw = packed struct {
2915 Rt: Register.Encoded,
2916 Rn: Register.Encoded,
2917 Rt2: Register.Encoded,
2918 imm7: i7,
2919 L: L = .load,
2920 decoded23: u3 = 0b001,
2921 V: bool = false,
2922 decoded27: u3 = 0b101,
2923 opc: u2 = 0b01,
2924 };
2925
2926 pub const Decoded = union(enum) {
2927 unallocated,
2928 stp: Stp,
2929 ldp: Ldp,
2930 ldpsw: Ldpsw,
2931 };
2932 pub fn decode(inst: @This()) @This().Decoded {
2933 return switch (inst.group.opc) {
2934 0b00, 0b10 => switch (inst.group.L) {
2935 .store => .{ .stp = inst.stp },
2936 .load => .{ .ldp = inst.ldp },
2937 },
2938 0b01 => switch (inst.group.L) {
2939 else => .unallocated,
2940 .load => .{ .ldpsw = inst.ldpsw },
2941 },
2942 else => .unallocated,
2943 };
2944 }
2945 };
2946
2947 pub const Vector = packed union {
2948 group: @This().Group,
2949 stp: Stp,
2950 ldp: Ldp,
2951
2952 pub const Group = packed struct {
2953 Rt: Register.Encoded,
2954 Rn: Register.Encoded,
2955 Rt2: Register.Encoded,
2956 imm7: i7,
2957 L: L,
2958 decoded23: u3 = 0b001,
2959 V: bool = true,
2960 decoded27: u3 = 0b101,
2961 opc: VectorSize,
2962 };
2963
2964 /// C7.2.330 STP (SIMD&FP)
2965 pub const Stp = packed struct {
2966 Rt: Register.Encoded,
2967 Rn: Register.Encoded,
2968 Rt2: Register.Encoded,
2969 imm7: i7,
2970 L: L = .store,
2971 decoded23: u3 = 0b001,
2972 V: bool = true,
2973 decoded27: u3 = 0b101,
2974 opc: VectorSize,
2975 };
2976
2977 /// C7.2.190 LDP (SIMD&FP)
2978 pub const Ldp = packed struct {
2979 Rt: Register.Encoded,
2980 Rn: Register.Encoded,
2981 Rt2: Register.Encoded,
2982 imm7: i7,
2983 L: L = .load,
2984 decoded23: u3 = 0b001,
2985 V: bool = true,
2986 decoded27: u3 = 0b101,
2987 opc: VectorSize,
2988 };
2989
2990 pub const Decoded = union(enum) {
2991 unallocated,
2992 stp: Stp,
2993 ldp: Ldp,
2994 };
2995 pub fn decode(inst: @This()) @This().Decoded {
2996 return switch (inst.group.opc) {
2997 .single, .double, .quad => switch (inst.group.L) {
2998 .store => .{ .stp = inst.stp },
2999 .load => .{ .ldp = inst.ldp },
3000 },
3001 _ => .unallocated,
3002 };
3003 }
3004 };
3005
3006 pub const Decoded = union(enum) {
3007 integer: Integer,
3008 vector: Vector,
3009 };
3010 pub fn decode(inst: @This()) @This().Decoded {
3011 return switch (inst.group.V) {
3012 false => .{ .integer = inst.integer },
3013 true => .{ .vector = inst.vector },
3014 };
3015 }
3016 };
3017
3018 /// Load/store register pair (offset)
3019 pub const RegisterPairOffset = packed union {
3020 group: @This().Group,
3021 integer: Integer,
3022 vector: Vector,
3023
3024 pub const Group = packed struct {
3025 Rt: Register.Encoded,
3026 Rn: Register.Encoded,
3027 Rt2: Register.Encoded,
3028 imm7: i7,
3029 L: L,
3030 decoded23: u3 = 0b010,
3031 V: bool,
3032 decoded27: u3 = 0b101,
3033 opc: u2,
3034 };
3035
3036 pub const Integer = packed union {
3037 group: @This().Group,
3038 stp: Stp,
3039 ldp: Ldp,
3040 ldpsw: Ldpsw,
3041
3042 pub const Group = packed struct {
3043 Rt: Register.Encoded,
3044 Rn: Register.Encoded,
3045 Rt2: Register.Encoded,
3046 imm7: i7,
3047 L: L,
3048 decoded23: u3 = 0b010,
3049 V: bool = false,
3050 decoded27: u3 = 0b101,
3051 opc: u2,
3052 };
3053
3054 /// C6.2.321 STP
3055 pub const Stp = packed struct {
3056 Rt: Register.Encoded,
3057 Rn: Register.Encoded,
3058 Rt2: Register.Encoded,
3059 imm7: i7,
3060 L: L = .store,
3061 decoded23: u3 = 0b010,
3062 V: bool = false,
3063 decoded27: u3 = 0b101,
3064 opc0: u1 = 0b0,
3065 sf: Register.IntegerSize,
3066 };
3067
3068 /// C6.2.164 LDP
3069 pub const Ldp = packed struct {
3070 Rt: Register.Encoded,
3071 Rn: Register.Encoded,
3072 Rt2: Register.Encoded,
3073 imm7: i7,
3074 L: L = .load,
3075 decoded23: u3 = 0b010,
3076 V: bool = false,
3077 decoded27: u3 = 0b101,
3078 opc0: u1 = 0b0,
3079 sf: Register.IntegerSize,
3080 };
3081
3082 /// C6.2.165 LDPSW
3083 pub const Ldpsw = packed struct {
3084 Rt: Register.Encoded,
3085 Rn: Register.Encoded,
3086 Rt2: Register.Encoded,
3087 imm7: i7,
3088 L: L = .load,
3089 decoded23: u3 = 0b010,
3090 V: bool = false,
3091 decoded27: u3 = 0b101,
3092 opc: u2 = 0b01,
3093 };
3094
3095 pub const Decoded = union(enum) {
3096 unallocated,
3097 stp: Stp,
3098 ldp: Ldp,
3099 ldpsw: Ldpsw,
3100 };
3101 pub fn decode(inst: @This()) @This().Decoded {
3102 return switch (inst.group.opc) {
3103 0b00, 0b10 => switch (inst.group.L) {
3104 .store => .{ .stp = inst.stp },
3105 .load => .{ .ldp = inst.ldp },
3106 },
3107 0b01 => switch (inst.group.L) {
3108 else => .unallocated,
3109 .load => .{ .ldpsw = inst.ldpsw },
3110 },
3111 else => .unallocated,
3112 };
3113 }
3114 };
3115
3116 pub const Vector = packed union {
3117 group: @This().Group,
3118 stp: Stp,
3119 ldp: Ldp,
3120
3121 pub const Group = packed struct {
3122 Rt: Register.Encoded,
3123 Rn: Register.Encoded,
3124 Rt2: Register.Encoded,
3125 imm7: i7,
3126 L: L,
3127 decoded23: u3 = 0b010,
3128 V: bool = true,
3129 decoded27: u3 = 0b101,
3130 opc: VectorSize,
3131 };
3132
3133 /// C7.2.330 STP (SIMD&FP)
3134 pub const Stp = packed struct {
3135 Rt: Register.Encoded,
3136 Rn: Register.Encoded,
3137 Rt2: Register.Encoded,
3138 imm7: i7,
3139 L: L = .store,
3140 decoded23: u3 = 0b010,
3141 V: bool = true,
3142 decoded27: u3 = 0b101,
3143 opc: VectorSize,
3144 };
3145
3146 /// C7.2.190 LDP (SIMD&FP)
3147 pub const Ldp = packed struct {
3148 Rt: Register.Encoded,
3149 Rn: Register.Encoded,
3150 Rt2: Register.Encoded,
3151 imm7: i7,
3152 L: L = .load,
3153 decoded23: u3 = 0b010,
3154 V: bool = true,
3155 decoded27: u3 = 0b101,
3156 opc: VectorSize,
3157 };
3158
3159 pub const Decoded = union(enum) {
3160 unallocated,
3161 stp: Stp,
3162 ldp: Ldp,
3163 };
3164 pub fn decode(inst: @This()) @This().Decoded {
3165 return switch (inst.group.opc) {
3166 .single, .double, .quad => switch (inst.group.L) {
3167 .store => .{ .stp = inst.stp },
3168 .load => .{ .ldp = inst.ldp },
3169 },
3170 _ => .unallocated,
3171 };
3172 }
3173 };
3174
3175 pub const Decoded = union(enum) {
3176 integer: Integer,
3177 vector: Vector,
3178 };
3179 pub fn decode(inst: @This()) @This().Decoded {
3180 return switch (inst.group.V) {
3181 false => .{ .integer = inst.integer },
3182 true => .{ .vector = inst.vector },
3183 };
3184 }
3185 };
3186
3187 /// Load/store register pair (pre-indexed)
3188 pub const RegisterPairPreIndexed = packed union {
3189 group: @This().Group,
3190 integer: Integer,
3191 vector: Vector,
3192
3193 pub const Group = packed struct {
3194 Rt: Register.Encoded,
3195 Rn: Register.Encoded,
3196 Rt2: Register.Encoded,
3197 imm7: i7,
3198 L: L,
3199 decoded23: u3 = 0b011,
3200 V: bool,
3201 decoded27: u3 = 0b101,
3202 opc: u2,
3203 };
3204
3205 pub const Integer = packed union {
3206 group: @This().Group,
3207 stp: Stp,
3208 ldp: Ldp,
3209 ldpsw: Ldpsw,
3210
3211 pub const Group = packed struct {
3212 Rt: Register.Encoded,
3213 Rn: Register.Encoded,
3214 Rt2: Register.Encoded,
3215 imm7: i7,
3216 L: L,
3217 decoded23: u3 = 0b011,
3218 V: bool = false,
3219 decoded27: u3 = 0b101,
3220 opc: u2,
3221 };
3222
3223 /// C6.2.321 STP
3224 pub const Stp = packed struct {
3225 Rt: Register.Encoded,
3226 Rn: Register.Encoded,
3227 Rt2: Register.Encoded,
3228 imm7: i7,
3229 L: L = .store,
3230 decoded23: u3 = 0b011,
3231 V: bool = false,
3232 decoded27: u3 = 0b101,
3233 opc0: u1 = 0b0,
3234 sf: Register.IntegerSize,
3235 };
3236
3237 /// C6.2.164 LDP
3238 pub const Ldp = packed struct {
3239 Rt: Register.Encoded,
3240 Rn: Register.Encoded,
3241 Rt2: Register.Encoded,
3242 imm7: i7,
3243 L: L = .load,
3244 decoded23: u3 = 0b011,
3245 V: bool = false,
3246 decoded27: u3 = 0b101,
3247 opc0: u1 = 0b0,
3248 sf: Register.IntegerSize,
3249 };
3250
3251 /// C6.2.165 LDPSW
3252 pub const Ldpsw = packed struct {
3253 Rt: Register.Encoded,
3254 Rn: Register.Encoded,
3255 Rt2: Register.Encoded,
3256 imm7: i7,
3257 L: L = .load,
3258 decoded23: u3 = 0b011,
3259 V: bool = false,
3260 decoded27: u3 = 0b101,
3261 opc0: u2 = 0b01,
3262 };
3263
3264 pub const Decoded = union(enum) {
3265 unallocated,
3266 stp: Stp,
3267 ldp: Ldp,
3268 ldpsw: Ldpsw,
3269 };
3270 pub fn decode(inst: @This()) @This().Decoded {
3271 return switch (inst.group.opc) {
3272 0b00, 0b10 => switch (inst.group.L) {
3273 .store => .{ .stp = inst.stp },
3274 .load => .{ .ldp = inst.ldp },
3275 },
3276 0b01 => switch (inst.group.L) {
3277 else => .unallocated,
3278 .load => .{ .ldpsw = inst.ldpsw },
3279 },
3280 else => .unallocated,
3281 };
3282 }
3283 };
3284
3285 pub const Vector = packed union {
3286 group: @This().Group,
3287 stp: Stp,
3288 ldp: Ldp,
3289
3290 pub const Group = packed struct {
3291 Rt: Register.Encoded,
3292 Rn: Register.Encoded,
3293 Rt2: Register.Encoded,
3294 imm7: i7,
3295 L: L,
3296 decoded23: u3 = 0b011,
3297 V: bool = true,
3298 decoded27: u3 = 0b101,
3299 opc: VectorSize,
3300 };
3301
3302 /// C7.2.330 STP (SIMD&FP)
3303 pub const Stp = packed struct {
3304 Rt: Register.Encoded,
3305 Rn: Register.Encoded,
3306 Rt2: Register.Encoded,
3307 imm7: i7,
3308 L: L = .store,
3309 decoded23: u3 = 0b011,
3310 V: bool = true,
3311 decoded27: u3 = 0b101,
3312 opc: VectorSize,
3313 };
3314
3315 /// C7.2.190 LDP (SIMD&FP)
3316 pub const Ldp = packed struct {
3317 Rt: Register.Encoded,
3318 Rn: Register.Encoded,
3319 Rt2: Register.Encoded,
3320 imm7: i7,
3321 L: L = .load,
3322 decoded23: u3 = 0b011,
3323 V: bool = true,
3324 decoded27: u3 = 0b101,
3325 opc: VectorSize,
3326 };
3327
3328 pub const Decoded = union(enum) {
3329 unallocated,
3330 stp: Stp,
3331 ldp: Ldp,
3332 };
3333 pub fn decode(inst: @This()) @This().Decoded {
3334 return switch (inst.group.opc) {
3335 .single, .double, .quad => switch (inst.group.L) {
3336 .store => .{ .stp = inst.stp },
3337 .load => .{ .ldp = inst.ldp },
3338 },
3339 _ => .unallocated,
3340 };
3341 }
3342 };
3343
3344 pub const Decoded = union(enum) {
3345 integer: Integer,
3346 vector: Vector,
3347 };
3348 pub fn decode(inst: @This()) @This().Decoded {
3349 return switch (inst.group.V) {
3350 false => .{ .integer = inst.integer },
3351 true => .{ .vector = inst.vector },
3352 };
3353 }
3354 };
3355
3356 /// Load/store register (unscaled immediate)
3357 pub const RegisterUnscaledImmediate = packed union {
3358 group: @This().Group,
3359 integer: Integer,
3360 vector: Vector,
3361
3362 pub const Group = packed struct {
3363 Rt: Register.Encoded,
3364 Rn: Register.Encoded,
3365 decoded10: u2 = 0b00,
3366 imm9: i9,
3367 decoded21: u1 = 0b0,
3368 opc: u2,
3369 decoded24: u2 = 0b00,
3370 V: bool,
3371 decoded27: u3 = 0b111,
3372 size: u2,
3373 };
3374
3375 pub const Integer = packed union {
3376 group: @This().Group,
3377 sturb: Sturb,
3378 ldurb: Ldurb,
3379 ldursb: Ldursb,
3380 sturh: Sturh,
3381 ldurh: Ldurh,
3382 ldursh: Ldursh,
3383 stur: Stur,
3384 ldur: Ldur,
3385 ldursw: Ldursw,
3386 prfum: Prfum,
3387
3388 pub const Group = packed struct {
3389 Rt: Register.Encoded,
3390 Rn: Register.Encoded,
3391 decoded10: u2 = 0b00,
3392 imm9: i9,
3393 decoded21: u1 = 0b0,
3394 opc: u2,
3395 decoded24: u2 = 0b00,
3396 V: bool = false,
3397 decoded27: u3 = 0b111,
3398 size: IntegerSize,
3399 };
3400
3401 /// C6.2.347 STURB
3402 pub const Sturb = packed struct {
3403 Rt: Register.Encoded,
3404 Rn: Register.Encoded,
3405 decoded10: u2 = 0b00,
3406 imm9: i9,
3407 decoded21: u1 = 0b0,
3408 opc: u2 = 0b00,
3409 decoded24: u2 = 0b00,
3410 V: bool = false,
3411 decoded27: u3 = 0b111,
3412 size: IntegerSize = .byte,
3413 };
3414
3415 /// C6.2.203 LDURB
3416 pub const Ldurb = packed struct {
3417 Rt: Register.Encoded,
3418 Rn: Register.Encoded,
3419 decoded10: u2 = 0b00,
3420 imm9: i9,
3421 decoded21: u1 = 0b0,
3422 opc: u2 = 0b01,
3423 decoded24: u2 = 0b00,
3424 V: bool = false,
3425 decoded27: u3 = 0b111,
3426 size: IntegerSize = .byte,
3427 };
3428
3429 /// C6.2.205 LDURSB
3430 pub const Ldursb = packed struct {
3431 Rt: Register.Encoded,
3432 Rn: Register.Encoded,
3433 decoded10: u2 = 0b00,
3434 imm9: i9,
3435 decoded21: u1 = 0b0,
3436 opc0: u1,
3437 opc1: u1 = 0b1,
3438 decoded24: u2 = 0b00,
3439 V: bool = false,
3440 decoded27: u3 = 0b111,
3441 size: IntegerSize = .byte,
3442 };
3443
3444 /// C6.2.348 STURH
3445 pub const Sturh = packed struct {
3446 Rt: Register.Encoded,
3447 Rn: Register.Encoded,
3448 decoded10: u2 = 0b00,
3449 imm9: i9,
3450 decoded21: u1 = 0b0,
3451 opc: u2 = 0b00,
3452 decoded24: u2 = 0b00,
3453 V: bool = false,
3454 decoded27: u3 = 0b111,
3455 size: IntegerSize = .halfword,
3456 };
3457
3458 /// C6.2.204 LDURH
3459 pub const Ldurh = packed struct {
3460 Rt: Register.Encoded,
3461 Rn: Register.Encoded,
3462 decoded10: u2 = 0b00,
3463 imm9: i9,
3464 decoded21: u1 = 0b0,
3465 opc: u2 = 0b01,
3466 decoded24: u2 = 0b00,
3467 V: bool = false,
3468 decoded27: u3 = 0b111,
3469 size: IntegerSize = .halfword,
3470 };
3471
3472 /// C6.2.206 LDURSH
3473 pub const Ldursh = packed struct {
3474 Rt: Register.Encoded,
3475 Rn: Register.Encoded,
3476 decoded10: u2 = 0b00,
3477 imm9: i9,
3478 decoded21: u1 = 0b0,
3479 opc0: u1,
3480 opc1: u1 = 0b1,
3481 decoded24: u2 = 0b00,
3482 V: bool = false,
3483 decoded27: u3 = 0b111,
3484 size: IntegerSize = .halfword,
3485 };
3486
3487 /// C6.2.346 STUR
3488 pub const Stur = packed struct {
3489 Rt: Register.Encoded,
3490 Rn: Register.Encoded,
3491 decoded10: u2 = 0b00,
3492 imm9: i9,
3493 decoded21: u1 = 0b0,
3494 opc: u2 = 0b00,
3495 decoded24: u2 = 0b00,
3496 V: bool = false,
3497 decoded27: u3 = 0b111,
3498 sf: Register.IntegerSize,
3499 size1: u1 = 0b1,
3500 };
3501
3502 /// C6.2.202 LDUR
3503 pub const Ldur = packed struct {
3504 Rt: Register.Encoded,
3505 Rn: Register.Encoded,
3506 decoded10: u2 = 0b00,
3507 imm9: i9,
3508 decoded21: u1 = 0b0,
3509 opc: u2 = 0b01,
3510 decoded24: u2 = 0b00,
3511 V: bool = false,
3512 decoded27: u3 = 0b111,
3513 sf: Register.IntegerSize,
3514 size1: u1 = 0b1,
3515 };
3516
3517 /// C6.2.207 LDURSW
3518 pub const Ldursw = packed struct {
3519 Rt: Register.Encoded,
3520 Rn: Register.Encoded,
3521 decoded10: u2 = 0b00,
3522 imm9: i9,
3523 decoded21: u1 = 0b0,
3524 opc: u2 = 0b10,
3525 decoded24: u2 = 0b00,
3526 V: bool = false,
3527 decoded27: u3 = 0b111,
3528 size: IntegerSize = .word,
3529 };
3530
3531 /// C6.2.250 PRFUM
3532 pub const Prfum = packed struct {
3533 prfop: PrfOp,
3534 Rn: Register.Encoded,
3535 decoded10: u2 = 0b00,
3536 imm9: i9,
3537 decoded21: u1 = 0b0,
3538 opc: u2 = 0b10,
3539 decoded24: u2 = 0b00,
3540 V: bool = false,
3541 decoded27: u3 = 0b111,
3542 size: IntegerSize = .doubleword,
3543 };
3544
3545 pub const Decoded = union(enum) {
3546 unallocated,
3547 sturb: Sturb,
3548 ldurb: Ldurb,
3549 ldursb: Ldursb,
3550 sturh: Sturh,
3551 ldurh: Ldurh,
3552 ldursh: Ldursh,
3553 stur: Stur,
3554 ldur: Ldur,
3555 ldursw: Ldursw,
3556 prfum: Prfum,
3557 };
3558 pub fn decode(inst: @This()) @This().Decoded {
3559 return switch (inst.group.size) {
3560 .byte => switch (inst.group.V) {
3561 false => switch (inst.group.opc) {
3562 0b00 => .{ .sturb = inst.sturb },
3563 0b01 => .{ .ldurb = inst.ldurb },
3564 0b10, 0b11 => .{ .ldursb = inst.ldursb },
3565 },
3566 true => .unallocated,
3567 },
3568 .halfword => switch (inst.group.V) {
3569 false => switch (inst.group.opc) {
3570 0b00 => .{ .sturh = inst.sturh },
3571 0b01 => .{ .ldurh = inst.ldurh },
3572 0b10, 0b11 => .{ .ldursh = inst.ldursh },
3573 },
3574 true => .unallocated,
3575 },
3576 .word => switch (inst.group.V) {
3577 false => switch (inst.group.opc) {
3578 0b00 => .{ .stur = inst.stur },
3579 0b01 => .{ .ldur = inst.ldur },
3580 0b10 => .{ .ldursw = inst.ldursw },
3581 0b11 => .unallocated,
3582 },
3583 true => .unallocated,
3584 },
3585 .doubleword => switch (inst.group.V) {
3586 false => switch (inst.group.opc) {
3587 0b00 => .{ .stur = inst.stur },
3588 0b01 => .{ .ldur = inst.ldur },
3589 0b10 => .{ .prfum = inst.prfum },
3590 0b11 => .unallocated,
3591 },
3592 true => .unallocated,
3593 },
3594 };
3595 }
3596 };
3597
3598 pub const Vector = packed union {
3599 group: @This().Group,
3600 stur: Stur,
3601 ldur: Ldur,
3602
3603 pub const Group = packed struct {
3604 Rt: Register.Encoded,
3605 Rn: Register.Encoded,
3606 decoded10: u2 = 0b00,
3607 imm9: i9,
3608 decoded21: u1 = 0b0,
3609 opc0: L,
3610 opc1: Opc1,
3611 decoded24: u2 = 0b00,
3612 V: bool = true,
3613 decoded27: u3 = 0b111,
3614 size: Size,
3615 };
3616
3617 /// C7.2.333 STUR (SIMD&FP)
3618 pub const Stur = packed struct {
3619 Rt: Register.Encoded,
3620 Rn: Register.Encoded,
3621 decoded10: u2 = 0b00,
3622 imm9: i9,
3623 decoded21: u1 = 0b0,
3624 opc0: L = .store,
3625 opc1: Opc1,
3626 decoded24: u2 = 0b00,
3627 V: bool = true,
3628 decoded27: u3 = 0b111,
3629 size: Size,
3630 };
3631
3632 /// C7.2.194 LDUR (SIMD&FP)
3633 pub const Ldur = packed struct {
3634 Rt: Register.Encoded,
3635 Rn: Register.Encoded,
3636 decoded10: u2 = 0b00,
3637 imm9: i9,
3638 decoded21: u1 = 0b0,
3639 opc0: L = .load,
3640 opc1: Opc1,
3641 decoded24: u2 = 0b00,
3642 V: bool = true,
3643 decoded27: u3 = 0b111,
3644 size: Size,
3645 };
3646
3647 pub const Opc1 = packed struct {
3648 encoded: u1,
3649
3650 pub fn encode(vs: Register.VectorSize) Opc1 {
3651 return .{ .encoded = switch (vs) {
3652 .byte, .half, .single, .double => 0b0,
3653 .quad => 0b1,
3654 else => unreachable,
3655 } };
3656 }
3657
3658 pub fn decode(enc_opc1: Opc1, enc_size: Size) Register.VectorSize {
3659 return switch (enc_size.encoded) {
3660 0b00 => switch (enc_opc1.encoded) {
3661 0b0 => .byte,
3662 0b1 => .quad,
3663 },
3664 0b01 => switch (enc_opc1.encoded) {
3665 0b0 => .half,
3666 0b1 => unreachable,
3667 },
3668 0b10 => switch (enc_opc1.encoded) {
3669 0b0 => .single,
3670 0b1 => unreachable,
3671 },
3672 0b11 => switch (enc_opc1.encoded) {
3673 0b0 => .double,
3674 0b1 => unreachable,
3675 },
3676 };
3677 }
3678 };
3679
3680 pub const Size = packed struct {
3681 encoded: u2,
3682
3683 pub fn encode(vs: Register.VectorSize) Size {
3684 return .{ .encoded = switch (vs) {
3685 .byte, .quad => 0b00,
3686 .half => 0b01,
3687 .single => 0b10,
3688 .double => 0b11,
3689 else => unreachable,
3690 } };
3691 }
3692 };
3693
3694 pub const Decoded = union(enum) {
3695 unallocated,
3696 stur: Stur,
3697 ldur: Ldur,
3698 };
3699 pub fn decode(inst: @This()) @This().Decoded {
3700 return switch (inst.group.size.encoded) {
3701 0b00 => switch (inst.group.opc0) {
3702 .store => .{ .stur = inst.stur },
3703 .load => .{ .ldur = inst.ldur },
3704 },
3705 0b01, 0b10, 0b11 => switch (inst.group.opc1.encoded) {
3706 0b0 => switch (inst.group.opc0) {
3707 .store => .{ .stur = inst.stur },
3708 .load => .{ .ldur = inst.ldur },
3709 },
3710 0b1 => .unallocated,
3711 },
3712 };
3713 }
3714 };
3715
3716 pub const Decoded = union(enum) {
3717 integer: Integer,
3718 vector: Vector,
3719 };
3720 pub fn decode(inst: @This()) @This().Decoded {
3721 return switch (inst.group.V) {
3722 false => .{ .integer = inst.integer },
3723 true => .{ .vector = inst.vector },
3724 };
3725 }
3726 };
3727
3728 /// Load/store register (immediate post-indexed)
3729 pub const RegisterImmediatePostIndexed = packed union {
3730 group: @This().Group,
3731 integer: Integer,
3732 vector: Vector,
3733
3734 pub const Group = packed struct {
3735 Rt: Register.Encoded,
3736 Rn: Register.Encoded,
3737 decoded10: u2 = 0b01,
3738 imm9: i9,
3739 decoded21: u1 = 0b0,
3740 opc: u2,
3741 decoded24: u2 = 0b00,
3742 V: bool,
3743 decoded27: u3 = 0b111,
3744 size: u2,
3745 };
3746
3747 pub const Integer = packed union {
3748 group: @This().Group,
3749 strb: Strb,
3750 ldrb: Ldrb,
3751 ldrsb: Ldrsb,
3752 strh: Strh,
3753 ldrh: Ldrh,
3754 ldrsh: Ldrsh,
3755 str: Str,
3756 ldr: Ldr,
3757 ldrsw: Ldrsw,
3758
3759 pub const Group = packed struct {
3760 Rt: Register.Encoded,
3761 Rn: Register.Encoded,
3762 decoded10: u2 = 0b01,
3763 imm9: i9,
3764 decoded21: u1 = 0b0,
3765 opc: u2,
3766 decoded24: u2 = 0b00,
3767 V: bool = false,
3768 decoded27: u3 = 0b111,
3769 size: IntegerSize,
3770 };
3771
3772 /// C6.2.324 STRB (immediate)
3773 pub const Strb = packed struct {
3774 Rt: Register.Encoded,
3775 Rn: Register.Encoded,
3776 decoded10: u2 = 0b01,
3777 imm9: i9,
3778 decoded21: u1 = 0b0,
3779 opc: u2 = 0b00,
3780 decoded24: u2 = 0b00,
3781 V: bool = false,
3782 decoded27: u3 = 0b111,
3783 size: IntegerSize = .byte,
3784 };
3785
3786 /// C6.2.170 LDRB (immediate)
3787 pub const Ldrb = packed struct {
3788 Rt: Register.Encoded,
3789 Rn: Register.Encoded,
3790 decoded10: u2 = 0b01,
3791 imm9: i9,
3792 decoded21: u1 = 0b0,
3793 opc: u2 = 0b01,
3794 decoded24: u2 = 0b00,
3795 V: bool = false,
3796 decoded27: u3 = 0b111,
3797 size: IntegerSize = .byte,
3798 };
3799
3800 /// C6.2.174 LDRSB (immediate)
3801 pub const Ldrsb = packed struct {
3802 Rt: Register.Encoded,
3803 Rn: Register.Encoded,
3804 decoded10: u2 = 0b01,
3805 imm9: i9,
3806 decoded21: u1 = 0b0,
3807 opc0: u1,
3808 opc1: u1 = 0b1,
3809 decoded24: u2 = 0b00,
3810 V: bool = false,
3811 decoded27: u3 = 0b111,
3812 size: IntegerSize = .byte,
3813 };
3814
3815 /// C6.2.326 STRH (immediate)
3816 pub const Strh = packed struct {
3817 Rt: Register.Encoded,
3818 Rn: Register.Encoded,
3819 decoded10: u2 = 0b01,
3820 imm9: i9,
3821 decoded21: u1 = 0b0,
3822 opc: u2 = 0b00,
3823 decoded24: u2 = 0b00,
3824 V: bool = false,
3825 decoded27: u3 = 0b111,
3826 size: IntegerSize = .halfword,
3827 };
3828
3829 /// C6.2.172 LDRH (immediate)
3830 pub const Ldrh = packed struct {
3831 Rt: Register.Encoded,
3832 Rn: Register.Encoded,
3833 decoded10: u2 = 0b01,
3834 imm9: i9,
3835 decoded21: u1 = 0b0,
3836 opc: u2 = 0b01,
3837 decoded24: u2 = 0b00,
3838 V: bool = false,
3839 decoded27: u3 = 0b111,
3840 size: IntegerSize = .halfword,
3841 };
3842
3843 /// C6.2.176 LDRSH (immediate)
3844 pub const Ldrsh = packed struct {
3845 Rt: Register.Encoded,
3846 Rn: Register.Encoded,
3847 decoded10: u2 = 0b01,
3848 imm9: i9,
3849 decoded21: u1 = 0b0,
3850 opc0: u1,
3851 opc1: u1 = 0b1,
3852 decoded24: u2 = 0b00,
3853 V: bool = false,
3854 decoded27: u3 = 0b111,
3855 size: IntegerSize = .halfword,
3856 };
3857
3858 /// C6.2.322 STR (immediate)
3859 pub const Str = packed struct {
3860 Rt: Register.Encoded,
3861 Rn: Register.Encoded,
3862 decoded10: u2 = 0b01,
3863 imm9: i9,
3864 decoded21: u1 = 0b0,
3865 opc: u2 = 0b00,
3866 decoded24: u2 = 0b00,
3867 V: bool = false,
3868 decoded27: u3 = 0b111,
3869 sf: Register.IntegerSize,
3870 size1: u1 = 0b1,
3871 };
3872
3873 /// C6.2.166 LDR (immediate)
3874 pub const Ldr = packed struct {
3875 Rt: Register.Encoded,
3876 Rn: Register.Encoded,
3877 decoded10: u2 = 0b01,
3878 imm9: i9,
3879 decoded21: u1 = 0b0,
3880 opc: u2 = 0b01,
3881 decoded24: u2 = 0b00,
3882 V: bool = false,
3883 decoded27: u3 = 0b111,
3884 sf: Register.IntegerSize,
3885 size1: u1 = 0b1,
3886 };
3887
3888 /// C6.2.178 LDRSW (immediate)
3889 pub const Ldrsw = packed struct {
3890 Rt: Register.Encoded,
3891 Rn: Register.Encoded,
3892 decoded10: u2 = 0b01,
3893 imm9: i9,
3894 decoded21: u1 = 0b0,
3895 opc: u2 = 0b10,
3896 decoded24: u2 = 0b00,
3897 V: bool = false,
3898 decoded27: u3 = 0b111,
3899 size: IntegerSize = .word,
3900 };
3901
3902 pub const Decoded = union(enum) {
3903 unallocated,
3904 strb: Strb,
3905 ldrb: Ldrb,
3906 ldrsb: Ldrsb,
3907 strh: Strh,
3908 ldrh: Ldrh,
3909 ldrsh: Ldrsh,
3910 str: Str,
3911 ldr: Ldr,
3912 ldrsw: Ldrsw,
3913 };
3914 pub fn decode(inst: @This()) @This().Decoded {
3915 return switch (inst.group.size) {
3916 .byte => switch (inst.group.V) {
3917 false => switch (inst.group.opc) {
3918 0b00 => .{ .strb = inst.strb },
3919 0b01 => .{ .ldrb = inst.ldrb },
3920 0b10, 0b11 => .{ .ldrsb = inst.ldrsb },
3921 },
3922 true => .unallocated,
3923 },
3924 .halfword => switch (inst.group.V) {
3925 false => switch (inst.group.opc) {
3926 0b00 => .{ .strh = inst.strh },
3927 0b01 => .{ .ldrh = inst.ldrh },
3928 0b10, 0b11 => .{ .ldrsh = inst.ldrsh },
3929 },
3930 true => .unallocated,
3931 },
3932 .word => switch (inst.group.V) {
3933 false => switch (inst.group.opc) {
3934 0b00 => .{ .str = inst.str },
3935 0b01 => .{ .ldr = inst.ldr },
3936 0b10 => .{ .ldrsw = inst.ldrsw },
3937 0b11 => .unallocated,
3938 },
3939 true => .unallocated,
3940 },
3941 .doubleword => switch (inst.group.V) {
3942 false => switch (inst.group.opc) {
3943 0b00 => .{ .str = inst.str },
3944 0b01 => .{ .ldr = inst.ldr },
3945 0b10, 0b11 => .unallocated,
3946 },
3947 true => .unallocated,
3948 },
3949 };
3950 }
3951 };
3952
3953 pub const Vector = packed union {
3954 group: @This().Group,
3955 str: Str,
3956 ldr: Ldr,
3957
3958 pub const Group = packed struct {
3959 Rt: Register.Encoded,
3960 Rn: Register.Encoded,
3961 decoded10: u2 = 0b01,
3962 imm9: i9,
3963 decoded21: u1 = 0b0,
3964 opc0: L,
3965 opc1: Opc1,
3966 decoded24: u2 = 0b00,
3967 V: bool = true,
3968 decoded27: u3 = 0b111,
3969 size: Size,
3970 };
3971
3972 /// C7.2.331 STR (immediate, SIMD&FP)
3973 pub const Str = packed struct {
3974 Rt: Register.Encoded,
3975 Rn: Register.Encoded,
3976 decoded10: u2 = 0b01,
3977 imm9: i9,
3978 decoded21: u1 = 0b0,
3979 opc0: L = .store,
3980 opc1: Opc1,
3981 decoded24: u2 = 0b00,
3982 V: bool = true,
3983 decoded27: u3 = 0b111,
3984 size: Size,
3985 };
3986
3987 /// C7.2.191 LDR (immediate, SIMD&FP)
3988 pub const Ldr = packed struct {
3989 Rt: Register.Encoded,
3990 Rn: Register.Encoded,
3991 decoded10: u2 = 0b01,
3992 imm9: i9,
3993 decoded21: u1 = 0b0,
3994 opc0: L = .load,
3995 opc1: Opc1,
3996 decoded24: u2 = 0b00,
3997 V: bool = true,
3998 decoded27: u3 = 0b111,
3999 size: Size,
4000 };
4001
4002 pub const Opc1 = packed struct {
4003 encoded: u1,
4004
4005 pub fn encode(vs: Register.VectorSize) Opc1 {
4006 return .{ .encoded = switch (vs) {
4007 .byte, .half, .single, .double => 0b0,
4008 .quad => 0b1,
4009 else => unreachable,
4010 } };
4011 }
4012
4013 pub fn decode(enc_opc1: Opc1, enc_size: Size) Register.VectorSize {
4014 return switch (enc_size.encoded) {
4015 0b00 => switch (enc_opc1.encoded) {
4016 0b0 => .byte,
4017 0b1 => .quad,
4018 },
4019 0b01 => switch (enc_opc1.encoded) {
4020 0b0 => .half,
4021 0b1 => unreachable,
4022 },
4023 0b10 => switch (enc_opc1.encoded) {
4024 0b0 => .single,
4025 0b1 => unreachable,
4026 },
4027 0b11 => switch (enc_opc1.encoded) {
4028 0b0 => .double,
4029 0b1 => unreachable,
4030 },
4031 };
4032 }
4033 };
4034
4035 pub const Size = packed struct {
4036 encoded: u2,
4037
4038 pub fn encode(vs: Register.VectorSize) Size {
4039 return .{ .encoded = switch (vs) {
4040 .byte, .quad => 0b00,
4041 .half => 0b01,
4042 .single => 0b10,
4043 .double => 0b11,
4044 else => unreachable,
4045 } };
4046 }
4047 };
4048
4049 pub const Decoded = union(enum) {
4050 unallocated,
4051 str: Str,
4052 ldr: Ldr,
4053 };
4054 pub fn decode(inst: @This()) @This().Decoded {
4055 return switch (inst.group.size.encoded) {
4056 0b00 => switch (inst.group.opc0) {
4057 .store => .{ .str = inst.str },
4058 .load => .{ .ldr = inst.ldr },
4059 },
4060 0b01, 0b10, 0b11 => switch (inst.group.opc1.encoded) {
4061 0b0 => switch (inst.group.opc0) {
4062 .store => .{ .str = inst.str },
4063 .load => .{ .ldr = inst.ldr },
4064 },
4065 0b1 => .unallocated,
4066 },
4067 };
4068 }
4069 };
4070
4071 pub const Decoded = union(enum) {
4072 integer: Integer,
4073 vector: Vector,
4074 };
4075 pub fn decode(inst: @This()) @This().Decoded {
4076 return switch (inst.group.V) {
4077 false => .{ .integer = inst.integer },
4078 true => .{ .vector = inst.vector },
4079 };
4080 }
4081 };
4082
4083 /// Load/store register (unprivileged)
4084 pub const RegisterUnprivileged = packed struct {
4085 Rt: Register.Encoded,
4086 Rn: Register.Encoded,
4087 decoded10: u2 = 0b10,
4088 imm9: i9,
4089 decoded21: u1 = 0b0,
4090 opc: u2,
4091 decoded24: u2 = 0b00,
4092 V: bool,
4093 decoded27: u3 = 0b111,
4094 size: IntegerSize,
4095 };
4096
4097 /// Load/store register (immediate pre-indexed)
4098 pub const RegisterImmediatePreIndexed = packed union {
4099 group: @This().Group,
4100 integer: Integer,
4101 vector: Vector,
4102
4103 pub const Group = packed struct {
4104 Rt: Register.Encoded,
4105 Rn: Register.Encoded,
4106 decoded10: u2 = 0b11,
4107 imm9: i9,
4108 decoded21: u1 = 0b0,
4109 opc: u2,
4110 decoded24: u2 = 0b00,
4111 V: bool,
4112 decoded27: u3 = 0b111,
4113 size: u2,
4114 };
4115
4116 pub const Integer = packed union {
4117 group: @This().Group,
4118 strb: Strb,
4119 ldrb: Ldrb,
4120 ldrsb: Ldrsb,
4121 strh: Strh,
4122 ldrh: Ldrh,
4123 ldrsh: Ldrsh,
4124 str: Str,
4125 ldr: Ldr,
4126 ldrsw: Ldrsw,
4127
4128 pub const Group = packed struct {
4129 Rt: Register.Encoded,
4130 Rn: Register.Encoded,
4131 decoded10: u2 = 0b11,
4132 imm9: i9,
4133 decoded21: u1 = 0b0,
4134 opc: u2,
4135 decoded24: u2 = 0b00,
4136 V: bool = false,
4137 decoded27: u3 = 0b111,
4138 size: IntegerSize,
4139 };
4140
4141 /// C6.2.324 STRB (immediate)
4142 pub const Strb = packed struct {
4143 Rt: Register.Encoded,
4144 Rn: Register.Encoded,
4145 decoded10: u2 = 0b11,
4146 imm9: i9,
4147 decoded21: u1 = 0b0,
4148 opc: u2 = 0b00,
4149 decoded24: u2 = 0b00,
4150 V: bool = false,
4151 decoded27: u3 = 0b111,
4152 size: IntegerSize = .byte,
4153 };
4154
4155 /// C6.2.170 LDRB (immediate)
4156 pub const Ldrb = packed struct {
4157 Rt: Register.Encoded,
4158 Rn: Register.Encoded,
4159 decoded10: u2 = 0b11,
4160 imm9: i9,
4161 decoded21: u1 = 0b0,
4162 opc: u2 = 0b01,
4163 decoded24: u2 = 0b00,
4164 V: bool = false,
4165 decoded27: u3 = 0b111,
4166 size: IntegerSize = .byte,
4167 };
4168
4169 /// C6.2.174 LDRSB (immediate)
4170 pub const Ldrsb = packed struct {
4171 Rt: Register.Encoded,
4172 Rn: Register.Encoded,
4173 decoded10: u2 = 0b11,
4174 imm9: i9,
4175 decoded21: u1 = 0b0,
4176 opc0: u1,
4177 opc1: u1 = 0b1,
4178 decoded24: u2 = 0b00,
4179 V: bool = false,
4180 decoded27: u3 = 0b111,
4181 size: IntegerSize = .byte,
4182 };
4183
4184 /// C6.2.326 STRH (immediate)
4185 pub const Strh = packed struct {
4186 Rt: Register.Encoded,
4187 Rn: Register.Encoded,
4188 decoded10: u2 = 0b11,
4189 imm9: i9,
4190 decoded21: u1 = 0b0,
4191 opc: u2 = 0b00,
4192 decoded24: u2 = 0b00,
4193 V: bool = false,
4194 decoded27: u3 = 0b111,
4195 size: IntegerSize = .halfword,
4196 };
4197
4198 /// C6.2.172 LDRH (immediate)
4199 pub const Ldrh = packed struct {
4200 Rt: Register.Encoded,
4201 Rn: Register.Encoded,
4202 decoded10: u2 = 0b11,
4203 imm9: i9,
4204 decoded21: u1 = 0b0,
4205 opc: u2 = 0b01,
4206 decoded24: u2 = 0b00,
4207 V: bool = false,
4208 decoded27: u3 = 0b111,
4209 size: IntegerSize = .halfword,
4210 };
4211
4212 /// C6.2.176 LDRSH (immediate)
4213 pub const Ldrsh = packed struct {
4214 Rt: Register.Encoded,
4215 Rn: Register.Encoded,
4216 decoded10: u2 = 0b11,
4217 imm9: i9,
4218 decoded21: u1 = 0b0,
4219 opc0: u1,
4220 opc1: u1 = 0b1,
4221 decoded24: u2 = 0b00,
4222 V: bool = false,
4223 decoded27: u3 = 0b111,
4224 size: IntegerSize = .halfword,
4225 };
4226
4227 /// C6.2.322 STR (immediate)
4228 pub const Str = packed struct {
4229 Rt: Register.Encoded,
4230 Rn: Register.Encoded,
4231 decoded10: u2 = 0b11,
4232 imm9: i9,
4233 decoded21: u1 = 0b0,
4234 opc: u2 = 0b00,
4235 decoded24: u2 = 0b00,
4236 V: bool = false,
4237 decoded27: u3 = 0b111,
4238 sf: Register.IntegerSize,
4239 size1: u1 = 0b1,
4240 };
4241
4242 /// C6.2.166 LDR (immediate)
4243 pub const Ldr = packed struct {
4244 Rt: Register.Encoded,
4245 Rn: Register.Encoded,
4246 decoded10: u2 = 0b11,
4247 imm9: i9,
4248 decoded21: u1 = 0b0,
4249 opc: u2 = 0b01,
4250 decoded24: u2 = 0b00,
4251 V: bool = false,
4252 decoded27: u3 = 0b111,
4253 sf: Register.IntegerSize,
4254 size1: u1 = 0b1,
4255 };
4256
4257 /// C6.2.178 LDRSW (immediate)
4258 pub const Ldrsw = packed struct {
4259 Rt: Register.Encoded,
4260 Rn: Register.Encoded,
4261 decoded10: u2 = 0b11,
4262 imm9: i9,
4263 decoded21: u1 = 0b0,
4264 opc: u2 = 0b10,
4265 decoded24: u2 = 0b00,
4266 V: bool = false,
4267 decoded27: u3 = 0b111,
4268 size: IntegerSize = .word,
4269 };
4270
4271 pub const Decoded = union(enum) {
4272 unallocated,
4273 strb: Strb,
4274 ldrb: Ldrb,
4275 ldrsb: Ldrsb,
4276 strh: Strh,
4277 ldrh: Ldrh,
4278 ldrsh: Ldrsh,
4279 str: Str,
4280 ldr: Ldr,
4281 ldrsw: Ldrsw,
4282 };
4283 pub fn decode(inst: @This()) @This().Decoded {
4284 return switch (inst.group.size) {
4285 .byte => switch (inst.group.opc) {
4286 0b00 => .{ .strb = inst.strb },
4287 0b01 => .{ .ldrb = inst.ldrb },
4288 0b10, 0b11 => .{ .ldrsb = inst.ldrsb },
4289 },
4290 .halfword => switch (inst.group.opc) {
4291 0b00 => .{ .strh = inst.strh },
4292 0b01 => .{ .ldrh = inst.ldrh },
4293 0b10, 0b11 => .{ .ldrsh = inst.ldrsh },
4294 },
4295 .word => switch (inst.group.opc) {
4296 0b00 => .{ .str = inst.str },
4297 0b01 => .{ .ldr = inst.ldr },
4298 0b10 => .{ .ldrsw = inst.ldrsw },
4299 0b11 => .unallocated,
4300 },
4301 .doubleword => switch (inst.group.opc) {
4302 0b00 => .{ .str = inst.str },
4303 0b01 => .{ .ldr = inst.ldr },
4304 0b10, 0b11 => .unallocated,
4305 },
4306 };
4307 }
4308 };
4309
4310 pub const Vector = packed union {
4311 group: @This().Group,
4312 str: Str,
4313 ldr: Ldr,
4314
4315 pub const Group = packed struct {
4316 Rt: Register.Encoded,
4317 Rn: Register.Encoded,
4318 decoded10: u2 = 0b11,
4319 imm9: i9,
4320 decoded21: u1 = 0b0,
4321 opc0: L,
4322 opc1: Opc1,
4323 decoded24: u2 = 0b00,
4324 V: bool = true,
4325 decoded27: u3 = 0b111,
4326 size: Size,
4327 };
4328
4329 /// C7.2.331 STR (immediate, SIMD&FP)
4330 pub const Str = packed struct {
4331 Rt: Register.Encoded,
4332 Rn: Register.Encoded,
4333 decoded10: u2 = 0b11,
4334 imm9: i9,
4335 decoded21: u1 = 0b0,
4336 opc0: L = .store,
4337 opc1: Opc1,
4338 decoded24: u2 = 0b00,
4339 V: bool = true,
4340 decoded27: u3 = 0b111,
4341 size: Size,
4342 };
4343
4344 /// C7.2.191 LDR (immediate, SIMD&FP)
4345 pub const Ldr = packed struct {
4346 Rt: Register.Encoded,
4347 Rn: Register.Encoded,
4348 decoded10: u2 = 0b11,
4349 imm9: i9,
4350 decoded21: u1 = 0b0,
4351 opc0: L = .load,
4352 opc1: Opc1,
4353 decoded24: u2 = 0b00,
4354 V: bool = true,
4355 decoded27: u3 = 0b111,
4356 size: Size,
4357 };
4358
4359 pub const Opc1 = packed struct {
4360 encoded: u1,
4361
4362 pub fn encode(vs: Register.VectorSize) Opc1 {
4363 return .{ .encoded = switch (vs) {
4364 .byte, .half, .single, .double => 0b0,
4365 .quad => 0b1,
4366 else => unreachable,
4367 } };
4368 }
4369
4370 pub fn decode(enc_opc1: Opc1, enc_size: Size) Register.VectorSize {
4371 return switch (enc_size.encoded) {
4372 0b00 => switch (enc_opc1.encoded) {
4373 0b0 => .byte,
4374 0b1 => .quad,
4375 },
4376 0b01 => switch (enc_opc1.encoded) {
4377 0b0 => .half,
4378 0b1 => unreachable,
4379 },
4380 0b10 => switch (enc_opc1.encoded) {
4381 0b0 => .single,
4382 0b1 => unreachable,
4383 },
4384 0b11 => switch (enc_opc1.encoded) {
4385 0b0 => .double,
4386 0b1 => unreachable,
4387 },
4388 };
4389 }
4390 };
4391
4392 pub const Size = packed struct {
4393 encoded: u2,
4394
4395 pub fn encode(vs: Register.VectorSize) Size {
4396 return .{ .encoded = switch (vs) {
4397 .byte, .quad => 0b00,
4398 .half => 0b01,
4399 .single => 0b10,
4400 .double => 0b11,
4401 else => unreachable,
4402 } };
4403 }
4404 };
4405
4406 pub const Decoded = union(enum) {
4407 unallocated,
4408 str: Str,
4409 ldr: Ldr,
4410 };
4411 pub fn decode(inst: @This()) @This().Decoded {
4412 return switch (inst.group.size.encoded) {
4413 0b00 => switch (inst.group.opc0) {
4414 .store => .{ .str = inst.str },
4415 .load => .{ .ldr = inst.ldr },
4416 },
4417 0b01, 0b10, 0b11 => switch (inst.group.opc1.encoded) {
4418 0b0 => switch (inst.group.opc0) {
4419 .store => .{ .str = inst.str },
4420 .load => .{ .ldr = inst.ldr },
4421 },
4422 0b1 => .unallocated,
4423 },
4424 };
4425 }
4426 };
4427
4428 pub const Decoded = union(enum) {
4429 integer: Integer,
4430 vector: Vector,
4431 };
4432 pub fn decode(inst: @This()) @This().Decoded {
4433 return switch (inst.group.V) {
4434 false => .{ .integer = inst.integer },
4435 true => .{ .vector = inst.vector },
4436 };
4437 }
4438 };
4439
4440 /// Load/store register (register offset)
4441 pub const RegisterRegisterOffset = packed union {
4442 group: @This().Group,
4443 integer: Integer,
4444 vector: Vector,
4445
4446 pub const Group = packed struct {
4447 Rt: Register.Encoded,
4448 Rn: Register.Encoded,
4449 decoded10: u2 = 0b10,
4450 S: bool,
4451 option: Option,
4452 Rm: Register.Encoded,
4453 decoded21: u1 = 0b1,
4454 opc: u2,
4455 decoded24: u2 = 0b00,
4456 V: bool,
4457 decoded27: u3 = 0b111,
4458 size: u2,
4459 };
4460
4461 pub const Integer = packed union {
4462 group: @This().Group,
4463 strb: Strb,
4464 ldrb: Ldrb,
4465 ldrsb: Ldrsb,
4466 strh: Strh,
4467 ldrh: Ldrh,
4468 ldrsh: Ldrsh,
4469 str: Str,
4470 ldr: Ldr,
4471 ldrsw: Ldrsw,
4472 prfm: Prfm,
4473
4474 pub const Group = packed struct {
4475 Rt: Register.Encoded,
4476 Rn: Register.Encoded,
4477 decoded10: u2 = 0b10,
4478 S: bool,
4479 option: Option,
4480 Rm: Register.Encoded,
4481 decoded21: u1 = 0b1,
4482 opc: u2,
4483 decoded24: u2 = 0b00,
4484 V: bool = false,
4485 decoded27: u3 = 0b111,
4486 size: IntegerSize,
4487 };
4488
4489 /// C6.2.325 STRB (register)
4490 pub const Strb = packed struct {
4491 Rt: Register.Encoded,
4492 Rn: Register.Encoded,
4493 decoded10: u2 = 0b10,
4494 S: bool,
4495 option: Option,
4496 Rm: Register.Encoded,
4497 decoded21: u1 = 0b1,
4498 opc: u2 = 0b00,
4499 decoded24: u2 = 0b00,
4500 V: bool = false,
4501 decoded27: u3 = 0b111,
4502 size: IntegerSize = .byte,
4503 };
4504
4505 /// C6.2.171 LDRB (register)
4506 pub const Ldrb = packed struct {
4507 Rt: Register.Encoded,
4508 Rn: Register.Encoded,
4509 decoded10: u2 = 0b10,
4510 S: bool,
4511 option: Option,
4512 Rm: Register.Encoded,
4513 decoded21: u1 = 0b1,
4514 opc: u2 = 0b01,
4515 decoded24: u2 = 0b00,
4516 V: bool = false,
4517 decoded27: u3 = 0b111,
4518 size: IntegerSize = .byte,
4519 };
4520
4521 /// C6.2.175 LDRSB (register)
4522 pub const Ldrsb = packed struct {
4523 Rt: Register.Encoded,
4524 Rn: Register.Encoded,
4525 decoded10: u2 = 0b10,
4526 S: bool,
4527 option: Option,
4528 Rm: Register.Encoded,
4529 decoded21: u1 = 0b1,
4530 opc0: u1,
4531 opc1: u1 = 0b1,
4532 decoded24: u2 = 0b00,
4533 V: bool = false,
4534 decoded27: u3 = 0b111,
4535 size: IntegerSize = .byte,
4536 };
4537
4538 /// C6.2.327 STRH (register)
4539 pub const Strh = packed struct {
4540 Rt: Register.Encoded,
4541 Rn: Register.Encoded,
4542 decoded10: u2 = 0b10,
4543 S: bool,
4544 option: Option,
4545 Rm: Register.Encoded,
4546 decoded21: u1 = 0b1,
4547 opc: u2 = 0b00,
4548 decoded24: u2 = 0b00,
4549 V: bool = false,
4550 decoded27: u3 = 0b111,
4551 size: IntegerSize = .halfword,
4552 };
4553
4554 /// C6.2.173 LDRH (register)
4555 pub const Ldrh = packed struct {
4556 Rt: Register.Encoded,
4557 Rn: Register.Encoded,
4558 decoded10: u2 = 0b10,
4559 S: bool,
4560 option: Option,
4561 Rm: Register.Encoded,
4562 decoded21: u1 = 0b1,
4563 opc: u2 = 0b01,
4564 decoded24: u2 = 0b00,
4565 V: bool = false,
4566 decoded27: u3 = 0b111,
4567 size: IntegerSize = .halfword,
4568 };
4569
4570 /// C6.2.177 LDRSH (register)
4571 pub const Ldrsh = packed struct {
4572 Rt: Register.Encoded,
4573 Rn: Register.Encoded,
4574 decoded10: u2 = 0b10,
4575 S: bool,
4576 option: Option,
4577 Rm: Register.Encoded,
4578 decoded21: u1 = 0b1,
4579 opc0: u1,
4580 opc1: u1 = 0b1,
4581 decoded24: u2 = 0b00,
4582 V: bool = false,
4583 decoded27: u3 = 0b111,
4584 size: IntegerSize = .halfword,
4585 };
4586
4587 /// C6.2.323 STR (register)
4588 pub const Str = packed struct {
4589 Rt: Register.Encoded,
4590 Rn: Register.Encoded,
4591 decoded10: u2 = 0b10,
4592 S: bool,
4593 option: Option,
4594 Rm: Register.Encoded,
4595 decoded21: u1 = 0b1,
4596 opc: u2 = 0b00,
4597 decoded24: u2 = 0b00,
4598 V: bool = false,
4599 decoded27: u3 = 0b111,
4600 sf: Register.IntegerSize,
4601 size1: u1 = 0b1,
4602 };
4603
4604 /// C6.2.168 LDR (register)
4605 pub const Ldr = packed struct {
4606 Rt: Register.Encoded,
4607 Rn: Register.Encoded,
4608 decoded10: u2 = 0b10,
4609 S: bool,
4610 option: Option,
4611 Rm: Register.Encoded,
4612 decoded21: u1 = 0b1,
4613 opc: u2 = 0b01,
4614 decoded24: u2 = 0b00,
4615 V: bool = false,
4616 decoded27: u3 = 0b111,
4617 sf: Register.IntegerSize,
4618 size1: u1 = 0b1,
4619 };
4620
4621 /// C6.2.180 LDRSW (register)
4622 pub const Ldrsw = packed struct {
4623 Rt: Register.Encoded,
4624 Rn: Register.Encoded,
4625 decoded10: u2 = 0b10,
4626 S: bool,
4627 option: Option,
4628 Rm: Register.Encoded,
4629 decoded21: u1 = 0b1,
4630 opc: u2 = 0b10,
4631 decoded24: u2 = 0b00,
4632 V: bool = false,
4633 decoded27: u3 = 0b111,
4634 size: IntegerSize = .word,
4635 };
4636
4637 /// C6.2.249 PRFM (register)
4638 pub const Prfm = packed struct {
4639 prfop: PrfOp,
4640 Rn: Register.Encoded,
4641 decoded10: u2 = 0b10,
4642 S: bool,
4643 option: Option,
4644 Rm: Register.Encoded,
4645 decoded21: u1 = 0b1,
4646 opc: u2 = 0b10,
4647 decoded24: u2 = 0b00,
4648 V: bool = false,
4649 decoded27: u3 = 0b111,
4650 size: IntegerSize = .doubleword,
4651 };
4652
4653 pub const Decoded = union(enum) {
4654 unallocated,
4655 strb: Strb,
4656 ldrb: Ldrb,
4657 ldrsb: Ldrsb,
4658 strh: Strh,
4659 ldrh: Ldrh,
4660 ldrsh: Ldrsh,
4661 str: Str,
4662 ldr: Ldr,
4663 ldrsw: Ldrsw,
4664 prfm: Prfm,
4665 };
4666 pub fn decode(inst: @This()) @This().Decoded {
4667 return switch (inst.group.size) {
4668 .byte => switch (inst.group.V) {
4669 false => switch (inst.group.opc) {
4670 0b00 => .{ .strb = inst.strb },
4671 0b01 => .{ .ldrb = inst.ldrb },
4672 0b10, 0b11 => .{ .ldrsb = inst.ldrsb },
4673 },
4674 true => .unallocated,
4675 },
4676 .halfword => switch (inst.group.V) {
4677 false => switch (inst.group.opc) {
4678 0b00 => .{ .strh = inst.strh },
4679 0b01 => .{ .ldrh = inst.ldrh },
4680 0b10, 0b11 => .{ .ldrsh = inst.ldrsh },
4681 },
4682 true => .unallocated,
4683 },
4684 .word => switch (inst.group.V) {
4685 false => switch (inst.group.opc) {
4686 0b00 => .{ .str = inst.str },
4687 0b01 => .{ .ldr = inst.ldr },
4688 0b10 => .{ .ldrsw = inst.ldrsw },
4689 0b11 => .unallocated,
4690 },
4691 true => .unallocated,
4692 },
4693 .doubleword => switch (inst.group.V) {
4694 false => switch (inst.group.opc) {
4695 0b00 => .{ .str = inst.str },
4696 0b01 => .{ .ldr = inst.ldr },
4697 0b10 => .{ .prfm = inst.prfm },
4698 0b11 => .unallocated,
4699 },
4700 true => .unallocated,
4701 },
4702 };
4703 }
4704 };
4705
4706 pub const Vector = packed union {
4707 group: @This().Group,
4708 str: Str,
4709 ldr: Ldr,
4710
4711 pub const Group = packed struct {
4712 Rt: Register.Encoded,
4713 Rn: Register.Encoded,
4714 decoded10: u2 = 0b10,
4715 S: bool,
4716 option: Option,
4717 Rm: Register.Encoded,
4718 decoded21: u1 = 0b1,
4719 opc: u2,
4720 decoded24: u2 = 0b00,
4721 V: bool = true,
4722 decoded27: u3 = 0b111,
4723 size: Size,
4724 };
4725
4726 /// C7.2.332 STR (register, SIMD&FP)
4727 pub const Str = packed struct {
4728 Rt: Register.Encoded,
4729 Rn: Register.Encoded,
4730 decoded10: u2 = 0b10,
4731 S: bool,
4732 option: Option,
4733 Rm: Register.Encoded,
4734 decoded21: u1 = 0b1,
4735 opc0: L = .store,
4736 opc1: Opc1,
4737 decoded24: u2 = 0b00,
4738 V: bool = true,
4739 decoded27: u3 = 0b111,
4740 size: Size,
4741 };
4742
4743 /// C7.2.193 LDR (register, SIMD&FP)
4744 pub const Ldr = packed struct {
4745 Rt: Register.Encoded,
4746 Rn: Register.Encoded,
4747 decoded10: u2 = 0b10,
4748 S: bool,
4749 option: Option,
4750 Rm: Register.Encoded,
4751 decoded21: u1 = 0b1,
4752 opc0: L = .load,
4753 opc1: Opc1,
4754 decoded24: u2 = 0b00,
4755 V: bool = true,
4756 decoded27: u3 = 0b111,
4757 size: Size,
4758 };
4759
4760 pub const Opc1 = packed struct {
4761 encoded: u1,
4762
4763 pub fn encode(vs: Register.VectorSize) Opc1 {
4764 return .{ .encoded = switch (vs) {
4765 .byte, .half, .single, .double => 0b0,
4766 .quad => 0b1,
4767 else => unreachable,
4768 } };
4769 }
4770
4771 pub fn decode(enc_opc1: Opc1, enc_size: Size) Register.VectorSize {
4772 return switch (enc_size.encoded) {
4773 0b00 => switch (enc_opc1.encoded) {
4774 0b0 => .byte,
4775 0b1 => .quad,
4776 },
4777 0b01 => switch (enc_opc1.encoded) {
4778 0b0 => .half,
4779 0b1 => unreachable,
4780 },
4781 0b10 => switch (enc_opc1.encoded) {
4782 0b0 => .single,
4783 0b1 => unreachable,
4784 },
4785 0b11 => switch (enc_opc1.encoded) {
4786 0b0 => .double,
4787 0b1 => unreachable,
4788 },
4789 };
4790 }
4791 };
4792
4793 pub const Size = packed struct {
4794 encoded: u2,
4795
4796 pub fn encode(vs: Register.VectorSize) Size {
4797 return .{ .encoded = switch (vs) {
4798 .byte, .quad => 0b00,
4799 .half => 0b01,
4800 .single => 0b10,
4801 .double => 0b11,
4802 else => unreachable,
4803 } };
4804 }
4805 };
4806 };
4807
4808 pub const Option = enum(u3) {
4809 uxtw = 0b010,
4810 lsl = 0b011,
4811 sxtw = 0b110,
4812 sxtx = 0b111,
4813 _,
4814
4815 pub fn sf(option: Option) Register.IntegerSize {
4816 return switch (option) {
4817 .uxtw, .sxtw => .word,
4818 .lsl, .sxtx => .doubleword,
4819 _ => unreachable,
4820 };
4821 }
4822 };
4823
4824 pub const Extend = union(Option) {
4825 uxtw: Amount,
4826 lsl: Amount,
4827 sxtw: Amount,
4828 sxtx: Amount,
4829
4830 pub const Amount = u3;
4831 };
4832
4833 pub const Decoded = union(enum) {
4834 integer: Integer,
4835 vector: Vector,
4836 };
4837 pub fn decode(inst: @This()) @This().Decoded {
4838 return switch (inst.group.V) {
4839 false => .{ .integer = inst.integer },
4840 true => .{ .vector = inst.vector },
4841 };
4842 }
4843 };
4844
4845 /// Load/store register (unsigned immediate)
4846 pub const RegisterUnsignedImmediate = packed union {
4847 group: @This().Group,
4848 integer: Integer,
4849 vector: Vector,
4850
4851 pub const Group = packed struct {
4852 Rt: Register.Encoded,
4853 Rn: Register.Encoded,
4854 imm12: u12,
4855 opc: u2,
4856 decoded24: u2 = 0b01,
4857 V: bool,
4858 decoded27: u3 = 0b111,
4859 size: u2,
4860 };
4861
4862 pub const Integer = packed union {
4863 group: @This().Group,
4864 strb: Strb,
4865 ldrb: Ldrb,
4866 ldrsb: Ldrsb,
4867 strh: Strh,
4868 ldrh: Ldrh,
4869 ldrsh: Ldrsh,
4870 str: Str,
4871 ldr: Ldr,
4872 ldrsw: Ldrsw,
4873 prfm: Prfm,
4874
4875 pub const Group = packed struct {
4876 Rt: Register.Encoded,
4877 Rn: Register.Encoded,
4878 imm12: u12,
4879 opc: u2,
4880 decoded24: u2 = 0b01,
4881 V: bool = false,
4882 decoded27: u3 = 0b111,
4883 size: IntegerSize,
4884 };
4885
4886 /// C6.2.324 STRB (immediate)
4887 pub const Strb = packed struct {
4888 Rt: Register.Encoded,
4889 Rn: Register.Encoded,
4890 imm12: u12,
4891 opc: u2 = 0b00,
4892 decoded24: u2 = 0b01,
4893 V: bool = false,
4894 decoded27: u3 = 0b111,
4895 size: IntegerSize = .byte,
4896 };
4897
4898 /// C6.2.170 LDRB (immediate)
4899 pub const Ldrb = packed struct {
4900 Rt: Register.Encoded,
4901 Rn: Register.Encoded,
4902 imm12: u12,
4903 opc: u2 = 0b01,
4904 decoded24: u2 = 0b01,
4905 V: bool = false,
4906 decoded27: u3 = 0b111,
4907 size: IntegerSize = .byte,
4908 };
4909
4910 /// C6.2.174 LDRSB (immediate)
4911 pub const Ldrsb = packed struct {
4912 Rt: Register.Encoded,
4913 Rn: Register.Encoded,
4914 imm12: u12,
4915 opc0: u1,
4916 opc1: u1 = 0b1,
4917 decoded24: u2 = 0b01,
4918 V: bool = false,
4919 decoded27: u3 = 0b111,
4920 size: IntegerSize = .byte,
4921 };
4922
4923 /// C6.2.326 STRH (immediate)
4924 pub const Strh = packed struct {
4925 Rt: Register.Encoded,
4926 Rn: Register.Encoded,
4927 imm12: u12,
4928 opc: u2 = 0b00,
4929 decoded24: u2 = 0b01,
4930 V: bool = false,
4931 decoded27: u3 = 0b111,
4932 size: IntegerSize = .halfword,
4933 };
4934
4935 /// C6.2.172 LDRH (immediate)
4936 pub const Ldrh = packed struct {
4937 Rt: Register.Encoded,
4938 Rn: Register.Encoded,
4939 imm12: u12,
4940 opc: u2 = 0b01,
4941 decoded24: u2 = 0b01,
4942 V: bool = false,
4943 decoded27: u3 = 0b111,
4944 size: IntegerSize = .halfword,
4945 };
4946
4947 /// C6.2.176 LDRSH (immediate)
4948 pub const Ldrsh = packed struct {
4949 Rt: Register.Encoded,
4950 Rn: Register.Encoded,
4951 imm12: u12,
4952 opc0: u1,
4953 opc1: u1 = 0b1,
4954 decoded24: u2 = 0b01,
4955 V: bool = false,
4956 decoded27: u3 = 0b111,
4957 size: IntegerSize = .halfword,
4958 };
4959
4960 /// C6.2.322 STR (immediate)
4961 pub const Str = packed struct {
4962 Rt: Register.Encoded,
4963 Rn: Register.Encoded,
4964 imm12: u12,
4965 opc: u2 = 0b00,
4966 decoded24: u2 = 0b01,
4967 V: bool = false,
4968 decoded27: u3 = 0b111,
4969 sf: Register.IntegerSize,
4970 size1: u1 = 0b1,
4971 };
4972
4973 /// C6.2.166 LDR (immediate)
4974 pub const Ldr = packed struct {
4975 Rt: Register.Encoded,
4976 Rn: Register.Encoded,
4977 imm12: u12,
4978 opc: u2 = 0b01,
4979 decoded24: u2 = 0b01,
4980 V: bool = false,
4981 decoded27: u3 = 0b111,
4982 sf: Register.IntegerSize,
4983 size1: u1 = 0b1,
4984 };
4985
4986 /// C6.2.178 LDRSW (immediate)
4987 pub const Ldrsw = packed struct {
4988 Rt: Register.Encoded,
4989 Rn: Register.Encoded,
4990 imm12: u12,
4991 opc: u2 = 0b10,
4992 decoded24: u2 = 0b01,
4993 V: bool = false,
4994 decoded27: u3 = 0b111,
4995 size: IntegerSize = .word,
4996 };
4997
4998 /// C6.2.247 PRFM (immediate)
4999 pub const Prfm = packed struct {
5000 prfop: PrfOp,
5001 Rn: Register.Encoded,
5002 imm12: u12,
5003 opc: u2 = 0b10,
5004 decoded24: u2 = 0b01,
5005 V: bool = false,
5006 decoded27: u3 = 0b111,
5007 size: IntegerSize = .doubleword,
5008 };
5009
5010 pub const Decoded = union(enum) {
5011 unallocated,
5012 strb: Strb,
5013 ldrb: Ldrb,
5014 ldrsb: Ldrsb,
5015 strh: Strh,
5016 ldrh: Ldrh,
5017 ldrsh: Ldrsh,
5018 str: Str,
5019 ldr: Ldr,
5020 ldrsw: Ldrsw,
5021 prfm: Prfm,
5022 };
5023 pub fn decode(inst: @This()) @This().Decoded {
5024 return switch (inst.group.size) {
5025 .byte => switch (inst.group.V) {
5026 false => switch (inst.group.opc) {
5027 0b00 => .{ .strb = inst.strb },
5028 0b01 => .{ .ldrb = inst.ldrb },
5029 0b10, 0b11 => .{ .ldrsb = inst.ldrsb },
5030 },
5031 true => .unallocated,
5032 },
5033 .halfword => switch (inst.group.V) {
5034 false => switch (inst.group.opc) {
5035 0b00 => .{ .strh = inst.strh },
5036 0b01 => .{ .ldrh = inst.ldrh },
5037 0b10, 0b11 => .{ .ldrsh = inst.ldrsh },
5038 },
5039 true => .unallocated,
5040 },
5041 .word => switch (inst.group.V) {
5042 false => switch (inst.group.opc) {
5043 0b00 => .{ .str = inst.str },
5044 0b01 => .{ .ldr = inst.ldr },
5045 0b10 => .{ .ldrsw = inst.ldrsw },
5046 0b11 => .unallocated,
5047 },
5048 true => .unallocated,
5049 },
5050 .doubleword => switch (inst.group.V) {
5051 false => switch (inst.group.opc) {
5052 0b00 => .{ .str = inst.str },
5053 0b01 => .{ .ldr = inst.ldr },
5054 0b10 => .{ .prfm = inst.prfm },
5055 0b11 => .unallocated,
5056 },
5057 true => .unallocated,
5058 },
5059 };
5060 }
5061 };
5062
5063 pub const Vector = packed union {
5064 group: @This().Group,
5065 str: Str,
5066 ldr: Ldr,
5067
5068 pub const Group = packed struct {
5069 Rt: Register.Encoded,
5070 Rn: Register.Encoded,
5071 imm12: u12,
5072 opc0: L,
5073 opc1: Opc1,
5074 decoded24: u2 = 0b01,
5075 V: bool = true,
5076 decoded27: u3 = 0b111,
5077 size: Size,
5078 };
5079
5080 /// C7.2.331 STR (immediate, SIMD&FP)
5081 pub const Str = packed struct {
5082 Rt: Register.Encoded,
5083 Rn: Register.Encoded,
5084 imm12: u12,
5085 opc0: L = .store,
5086 opc1: Opc1,
5087 decoded24: u2 = 0b01,
5088 V: bool = true,
5089 decoded27: u3 = 0b111,
5090 size: Size,
5091 };
5092
5093 /// C7.2.191 LDR (immediate, SIMD&FP)
5094 pub const Ldr = packed struct {
5095 Rt: Register.Encoded,
5096 Rn: Register.Encoded,
5097 imm12: u12,
5098 opc0: L = .load,
5099 opc1: Opc1,
5100 decoded24: u2 = 0b01,
5101 V: bool = true,
5102 decoded27: u3 = 0b111,
5103 size: Size,
5104 };
5105
5106 pub const Opc1 = packed struct {
5107 encoded: u1,
5108
5109 pub fn encode(vs: Register.VectorSize) Opc1 {
5110 return .{ .encoded = switch (vs) {
5111 .byte, .half, .single, .double => 0b0,
5112 .quad => 0b1,
5113 else => unreachable,
5114 } };
5115 }
5116
5117 pub fn decode(enc_opc1: Opc1, enc_size: Size) Register.VectorSize {
5118 return switch (enc_size.encoded) {
5119 0b00 => switch (enc_opc1.encoded) {
5120 0b0 => .byte,
5121 0b1 => .quad,
5122 },
5123 0b01 => switch (enc_opc1.encoded) {
5124 0b0 => .half,
5125 0b1 => unreachable,
5126 },
5127 0b10 => switch (enc_opc1.encoded) {
5128 0b0 => .single,
5129 0b1 => unreachable,
5130 },
5131 0b11 => switch (enc_opc1.encoded) {
5132 0b0 => .double,
5133 0b1 => unreachable,
5134 },
5135 };
5136 }
5137 };
5138
5139 pub const Size = packed struct {
5140 encoded: u2,
5141
5142 pub fn encode(vs: Register.VectorSize) Size {
5143 return .{ .encoded = switch (vs) {
5144 .byte, .quad => 0b00,
5145 .half => 0b01,
5146 .single => 0b10,
5147 .double => 0b11,
5148 else => unreachable,
5149 } };
5150 }
5151 };
5152
5153 pub const Decoded = union(enum) {
5154 unallocated,
5155 str: Str,
5156 ldr: Ldr,
5157 };
5158 pub fn decode(inst: @This()) @This().Decoded {
5159 return switch (inst.group.size.encoded) {
5160 0b00 => switch (inst.group.opc0) {
5161 .store => .{ .str = inst.str },
5162 .load => .{ .ldr = inst.ldr },
5163 },
5164 0b01, 0b10, 0b11 => switch (inst.group.opc1.encoded) {
5165 0b0 => switch (inst.group.opc0) {
5166 .store => .{ .str = inst.str },
5167 .load => .{ .ldr = inst.ldr },
5168 },
5169 0b1 => .unallocated,
5170 },
5171 };
5172 }
5173 };
5174
5175 pub const Decoded = union(enum) {
5176 integer: Integer,
5177 vector: Vector,
5178 };
5179 pub fn decode(inst: @This()) @This().Decoded {
5180 return switch (inst.group.V) {
5181 false => .{ .integer = inst.integer },
5182 true => .{ .vector = inst.vector },
5183 };
5184 }
5185 };
5186
5187 pub const L = enum(u1) {
5188 store = 0b0,
5189 load = 0b1,
5190 };
5191
5192 pub const IntegerSize = enum(u2) {
5193 byte = 0b00,
5194 halfword = 0b01,
5195 word = 0b10,
5196 doubleword = 0b11,
5197 };
5198
5199 pub const VectorSize = enum(u2) {
5200 single = 0b00,
5201 double = 0b01,
5202 quad = 0b10,
5203 _,
5204
5205 pub fn decode(vs: VectorSize) Register.VectorSize {
5206 return switch (vs) {
5207 .single => .single,
5208 .double => .double,
5209 .quad => .quad,
5210 _ => unreachable,
5211 };
5212 }
5213
5214 pub fn encode(vs: Register.VectorSize) VectorSize {
5215 return switch (vs) {
5216 else => unreachable,
5217 .single => .single,
5218 .double => .double,
5219 .quad => .quad,
5220 };
5221 }
5222 };
5223
5224 pub const PrfOp = packed struct {
5225 policy: Policy,
5226 target: Target,
5227 type: Type,
5228
5229 pub const Policy = enum(u1) {
5230 keep = 0b0,
5231 strm = 0b1,
5232 };
5233
5234 pub const Target = enum(u2) {
5235 l1 = 0b00,
5236 l2 = 0b01,
5237 l3 = 0b10,
5238 _,
5239 };
5240
5241 pub const Type = enum(u2) {
5242 pld = 0b00,
5243 pli = 0b01,
5244 pst = 0b10,
5245 _,
5246 };
5247
5248 pub const pldl1keep: PrfOp = .{ .type = .pld, .target = .l1, .policy = .keep };
5249 pub const pldl1strm: PrfOp = .{ .type = .pld, .target = .l1, .policy = .strm };
5250 pub const pldl2keep: PrfOp = .{ .type = .pld, .target = .l2, .policy = .keep };
5251 pub const pldl2strm: PrfOp = .{ .type = .pld, .target = .l2, .policy = .strm };
5252 pub const pldl3keep: PrfOp = .{ .type = .pld, .target = .l3, .policy = .keep };
5253 pub const pldl3strm: PrfOp = .{ .type = .pld, .target = .l3, .policy = .strm };
5254 pub const plil1keep: PrfOp = .{ .type = .pli, .target = .l1, .policy = .keep };
5255 pub const plil1strm: PrfOp = .{ .type = .pli, .target = .l1, .policy = .strm };
5256 pub const plil2keep: PrfOp = .{ .type = .pli, .target = .l2, .policy = .keep };
5257 pub const plil2strm: PrfOp = .{ .type = .pli, .target = .l2, .policy = .strm };
5258 pub const plil3keep: PrfOp = .{ .type = .pli, .target = .l3, .policy = .keep };
5259 pub const plil3strm: PrfOp = .{ .type = .pli, .target = .l3, .policy = .strm };
5260 pub const pstl1keep: PrfOp = .{ .type = .pst, .target = .l1, .policy = .keep };
5261 pub const pstl1strm: PrfOp = .{ .type = .pst, .target = .l1, .policy = .strm };
5262 pub const pstl2keep: PrfOp = .{ .type = .pst, .target = .l2, .policy = .keep };
5263 pub const pstl2strm: PrfOp = .{ .type = .pst, .target = .l2, .policy = .strm };
5264 pub const pstl3keep: PrfOp = .{ .type = .pst, .target = .l3, .policy = .keep };
5265 pub const pstl3strm: PrfOp = .{ .type = .pst, .target = .l3, .policy = .strm_ };
5266 };
5267
5268 pub const Decoded = union(enum) {
5269 unallocated,
5270 register_literal: RegisterLiteral,
5271 memory: Memory,
5272 no_allocate_pair_offset: NoAllocatePairOffset,
5273 register_pair_post_indexed: RegisterPairPostIndexed,
5274 register_pair_offset: RegisterPairOffset,
5275 register_pair_pre_indexed: RegisterPairPreIndexed,
5276 register_unscaled_immediate: RegisterUnscaledImmediate,
5277 register_immediate_post_indexed: RegisterImmediatePostIndexed,
5278 register_unprivileged: RegisterUnprivileged,
5279 register_immediate_pre_indexed: RegisterImmediatePreIndexed,
5280 register_register_offset: RegisterRegisterOffset,
5281 register_unsigned_immediate: RegisterUnsignedImmediate,
5282 };
5283 pub fn decode(inst: @This()) @This().Decoded {
5284 return switch (inst.group.op0) {
5285 else => .unallocated,
5286 0b0010, 0b0110, 0b1010, 0b1110 => switch (inst.group.op2) {
5287 0b00 => .{ .no_allocate_pair_offset = inst.no_allocate_pair_offset },
5288 0b01 => .{ .register_pair_post_indexed = inst.register_pair_post_indexed },
5289 0b10 => .{ .register_pair_offset = inst.register_pair_offset },
5290 0b11 => .{ .register_pair_pre_indexed = inst.register_pair_pre_indexed },
5291 },
5292 0b0011, 0b0111, 0b1011, 0b1111 => switch (inst.group.op2) {
5293 0b00...0b01 => switch (inst.group.op3) {
5294 0b000000...0b011111 => switch (inst.group.op4) {
5295 0b00 => .{ .register_unscaled_immediate = inst.register_unscaled_immediate },
5296 0b01 => .{ .register_immediate_post_indexed = inst.register_immediate_post_indexed },
5297 0b10 => .{ .register_unprivileged = inst.register_unprivileged },
5298 0b11 => .{ .register_immediate_pre_indexed = inst.register_immediate_pre_indexed },
5299 },
5300 0b100000...0b111111 => switch (inst.group.op4) {
5301 0b00 => .unallocated,
5302 0b10 => .{ .register_register_offset = inst.register_register_offset },
5303 0b01, 0b11 => .unallocated,
5304 },
5305 },
5306 0b10...0b11 => .{ .register_unsigned_immediate = inst.register_unsigned_immediate },
5307 },
5308 };
5309 }
5310 };
5311
5312 /// C4.1.89 Data Processing -- Register
5313 pub const DataProcessingRegister = packed union {
5314 group: @This().Group,
5315 data_processing_two_source: DataProcessingTwoSource,
5316 data_processing_one_source: DataProcessingOneSource,
5317 logical_shifted_register: LogicalShiftedRegister,
5318 add_subtract_shifted_register: AddSubtractShiftedRegister,
5319 add_subtract_extended_register: AddSubtractExtendedRegister,
5320 add_subtract_with_carry: AddSubtractWithCarry,
5321 rotate_right_into_flags: RotateRightIntoFlags,
5322 evaluate_into_flags: EvaluateIntoFlags,
5323 conditional_compare_register: ConditionalCompareRegister,
5324 conditional_compare_immediate: ConditionalCompareImmediate,
5325 conditional_select: ConditionalSelect,
5326 data_processing_three_source: DataProcessingThreeSource,
5327
5328 /// Table C4-90 Encoding table for the Data Processing -- Register group
5329 pub const Group = packed struct {
5330 encoded0: u10,
5331 op3: u6,
5332 encoded16: u5,
5333 op2: u4,
5334 decoded25: u3 = 0b101,
5335 op1: u1,
5336 encoded29: u1,
5337 op0: u1,
5338 encoded31: u1,
5339 };
5340
5341 /// Data-processing (2 source)
5342 pub const DataProcessingTwoSource = packed union {
5343 group: @This().Group,
5344 udiv: Udiv,
5345 sdiv: Sdiv,
5346 lslv: Lslv,
5347 lsrv: Lsrv,
5348 asrv: Asrv,
5349 rorv: Rorv,
5350
5351 pub const Group = packed struct {
5352 Rd: Register.Encoded,
5353 Rn: Register.Encoded,
5354 opcode: u6,
5355 Rm: Register.Encoded,
5356 decoded21: u8 = 0b11010110,
5357 S: bool,
5358 decoded30: u1 = 0b0,
5359 sf: Register.IntegerSize,
5360 };
5361
5362 /// C6.2.388 UDIV
5363 pub const Udiv = packed struct {
5364 Rd: Register.Encoded,
5365 Rn: Register.Encoded,
5366 o1: DivOp = .udiv,
5367 decoded11: u5 = 0b00001,
5368 Rm: Register.Encoded,
5369 decoded21: u8 = 0b11010110,
5370 S: bool = false,
5371 decoded30: u1 = 0b0,
5372 sf: Register.IntegerSize,
5373 };
5374
5375 /// C6.2.270 SDIV
5376 pub const Sdiv = packed struct {
5377 Rd: Register.Encoded,
5378 Rn: Register.Encoded,
5379 o1: DivOp = .sdiv,
5380 decoded11: u5 = 0b00001,
5381 Rm: Register.Encoded,
5382 decoded21: u8 = 0b11010110,
5383 S: bool = false,
5384 decoded30: u1 = 0b0,
5385 sf: Register.IntegerSize,
5386 };
5387
5388 /// C6.2.214 LSLV
5389 pub const Lslv = packed struct {
5390 Rd: Register.Encoded,
5391 Rn: Register.Encoded,
5392 op2: ShiftOp = .lslv,
5393 decoded12: u4 = 0b0010,
5394 Rm: Register.Encoded,
5395 decoded21: u8 = 0b11010110,
5396 S: bool = false,
5397 decoded30: u1 = 0b0,
5398 sf: Register.IntegerSize,
5399 };
5400
5401 /// C6.2.217 LSRV
5402 pub const Lsrv = packed struct {
5403 Rd: Register.Encoded,
5404 Rn: Register.Encoded,
5405 op2: ShiftOp = .lsrv,
5406 decoded12: u4 = 0b0010,
5407 Rm: Register.Encoded,
5408 decoded21: u8 = 0b11010110,
5409 S: bool = false,
5410 decoded30: u1 = 0b0,
5411 sf: Register.IntegerSize,
5412 };
5413
5414 /// C6.2.18 ASRV
5415 pub const Asrv = packed struct {
5416 Rd: Register.Encoded,
5417 Rn: Register.Encoded,
5418 op2: ShiftOp = .asrv,
5419 decoded12: u4 = 0b0010,
5420 Rm: Register.Encoded,
5421 decoded21: u8 = 0b11010110,
5422 S: bool = false,
5423 decoded30: u1 = 0b0,
5424 sf: Register.IntegerSize,
5425 };
5426
5427 /// C6.2.263 RORV
5428 pub const Rorv = packed struct {
5429 Rd: Register.Encoded,
5430 Rn: Register.Encoded,
5431 op2: ShiftOp = .rorv,
5432 decoded12: u4 = 0b0010,
5433 Rm: Register.Encoded,
5434 decoded21: u8 = 0b11010110,
5435 S: bool = false,
5436 decoded30: u1 = 0b0,
5437 sf: Register.IntegerSize,
5438 };
5439
5440 pub const DivOp = enum(u1) {
5441 udiv = 0b0,
5442 sdiv = 0b1,
5443 };
5444
5445 pub const ShiftOp = enum(u2) {
5446 lslv = 0b00,
5447 lsrv = 0b01,
5448 asrv = 0b10,
5449 rorv = 0b11,
5450 };
5451
5452 pub const Decoded = union(enum) {
5453 unallocated,
5454 udiv: Udiv,
5455 sdiv: Sdiv,
5456 lslv: Lslv,
5457 lsrv: Lsrv,
5458 asrv: Asrv,
5459 rorv: Rorv,
5460 };
5461 pub fn decode(inst: @This()) @This().Decoded {
5462 return switch (inst.group.S) {
5463 false => switch (inst.group.opcode) {
5464 else => .unallocated,
5465 0b000010 => .{ .udiv = inst.udiv },
5466 0b000011 => .{ .sdiv = inst.sdiv },
5467 0b001000 => .{ .lslv = inst.lslv },
5468 0b001001 => .{ .lsrv = inst.lsrv },
5469 0b001010 => .{ .asrv = inst.asrv },
5470 0b001011 => .{ .rorv = inst.rorv },
5471 },
5472 true => .unallocated,
5473 };
5474 }
5475 };
5476
5477 /// Data-processing (1 source)
5478 pub const DataProcessingOneSource = packed union {
5479 group: @This().Group,
5480 rbit: Rbit,
5481 rev16: Rev16,
5482 rev32: Rev32,
5483 rev: Rev,
5484 clz: Clz,
5485 cls: Cls,
5486
5487 pub const Group = packed struct {
5488 Rd: Register.Encoded,
5489 Rn: Register.Encoded,
5490 opcode: u6,
5491 opcode2: u5,
5492 decoded21: u8 = 0b11010110,
5493 S: bool,
5494 decoded30: u1 = 0b1,
5495 sf: Register.IntegerSize,
5496 };
5497
5498 /// C6.2.253 RBIT
5499 pub const Rbit = packed struct {
5500 Rd: Register.Encoded,
5501 Rn: Register.Encoded,
5502 decoded10: u2 = 0b00,
5503 decoded12: u4 = 0b0000,
5504 decoded16: u5 = 0b00000,
5505 decoded21: u8 = 0b11010110,
5506 S: bool = false,
5507 decoded30: u1 = 0b1,
5508 sf: Register.IntegerSize,
5509 };
5510
5511 /// C6.2.257 REV16
5512 pub const Rev16 = packed struct {
5513 Rd: Register.Encoded,
5514 Rn: Register.Encoded,
5515 opc: u2 = 0b01,
5516 decoded12: u4 = 0b0000,
5517 decoded16: u5 = 0b00000,
5518 decoded21: u8 = 0b11010110,
5519 S: bool = false,
5520 decoded30: u1 = 0b1,
5521 sf: Register.IntegerSize,
5522 };
5523
5524 /// C6.2.258 REV32
5525 pub const Rev32 = packed struct {
5526 Rd: Register.Encoded,
5527 Rn: Register.Encoded,
5528 opc: u2 = 0b10,
5529 decoded12: u4 = 0b0000,
5530 decoded16: u5 = 0b00000,
5531 decoded21: u8 = 0b11010110,
5532 S: bool = false,
5533 decoded30: u1 = 0b1,
5534 sf: Register.IntegerSize = .doubleword,
5535 };
5536
5537 /// C6.2.256 REV
5538 pub const Rev = packed struct {
5539 Rd: Register.Encoded,
5540 Rn: Register.Encoded,
5541 opc0: Register.IntegerSize,
5542 opc1: u1 = 0b1,
5543 decoded12: u4 = 0b0000,
5544 decoded16: u5 = 0b00000,
5545 decoded21: u8 = 0b11010110,
5546 S: bool = false,
5547 decoded30: u1 = 0b1,
5548 sf: Register.IntegerSize,
5549 };
5550
5551 /// C6.2.58 CLZ
5552 pub const Clz = packed struct {
5553 Rd: Register.Encoded,
5554 Rn: Register.Encoded,
5555 op: u1 = 0b0,
5556 decoded11: u5 = 0b00010,
5557 decoded16: u5 = 0b00000,
5558 decoded21: u8 = 0b11010110,
5559 S: bool = false,
5560 decoded30: u1 = 0b1,
5561 sf: Register.IntegerSize,
5562 };
5563
5564 /// C6.2.57 CLS
5565 pub const Cls = packed struct {
5566 Rd: Register.Encoded,
5567 Rn: Register.Encoded,
5568 op: u1 = 0b1,
5569 decoded11: u5 = 0b00010,
5570 decoded16: u5 = 0b00000,
5571 decoded21: u8 = 0b11010110,
5572 S: bool = false,
5573 decoded30: u1 = 0b1,
5574 sf: Register.IntegerSize,
5575 };
5576
5577 pub const Decoded = union(enum) {
5578 unallocated,
5579 rbit: Rbit,
5580 rev16: Rev16,
5581 rev32: Rev32,
5582 rev: Rev,
5583 clz: Clz,
5584 cls: Cls,
5585 };
5586 pub fn decode(inst: @This()) @This().Decoded {
5587 return switch (inst.group.S) {
5588 true => .unallocated,
5589 false => switch (inst.group.opcode2) {
5590 else => .unallocated,
5591 0b00000 => switch (inst.group.opcode) {
5592 else => .unallocated,
5593 0b000000 => .{ .rbit = inst.rbit },
5594 0b000001 => .{ .rev16 = inst.rev16 },
5595 0b000010 => switch (inst.group.sf) {
5596 .word => .{ .rev = inst.rev },
5597 .doubleword => .{ .rev32 = inst.rev32 },
5598 },
5599 0b000011 => switch (inst.group.sf) {
5600 .word => .unallocated,
5601 .doubleword => .{ .rev = inst.rev },
5602 },
5603 0b000100 => .{ .clz = inst.clz },
5604 0b000101 => .{ .cls = inst.cls },
5605 },
5606 },
5607 };
5608 }
5609 };
5610
5611 /// Logical (shifted register)
5612 pub const LogicalShiftedRegister = packed union {
5613 group: @This().Group,
5614 @"and": And,
5615 bic: Bic,
5616 orr: Orr,
5617 orn: Orn,
5618 eor: Eor,
5619 eon: Eon,
5620 ands: Ands,
5621 bics: Bics,
5622
5623 pub const Group = packed struct {
5624 Rd: Register.Encoded,
5625 Rn: Register.Encoded,
5626 imm6: Shift.Amount,
5627 Rm: Register.Encoded,
5628 N: bool,
5629 shift: Shift.Op,
5630 decoded24: u5 = 0b01010,
5631 opc: LogicalOpc,
5632 sf: Register.IntegerSize,
5633 };
5634
5635 /// C6.2.13 AND (shifted register)
5636 pub const And = packed struct {
5637 Rd: Register.Encoded,
5638 Rn: Register.Encoded,
5639 imm6: Shift.Amount,
5640 Rm: Register.Encoded,
5641 N: bool = false,
5642 shift: Shift.Op,
5643 decoded24: u5 = 0b01010,
5644 opc: LogicalOpc = .@"and",
5645 sf: Register.IntegerSize,
5646 };
5647
5648 /// C6.2.32 BIC (shifted register)
5649 pub const Bic = packed struct {
5650 Rd: Register.Encoded,
5651 Rn: Register.Encoded,
5652 imm6: Shift.Amount,
5653 Rm: Register.Encoded,
5654 N: bool = true,
5655 shift: Shift.Op,
5656 decoded24: u5 = 0b01010,
5657 opc: LogicalOpc = .@"and",
5658 sf: Register.IntegerSize,
5659 };
5660
5661 /// C6.2.241 ORR (shifted register)
5662 pub const Orr = packed struct {
5663 Rd: Register.Encoded,
5664 Rn: Register.Encoded,
5665 imm6: Shift.Amount,
5666 Rm: Register.Encoded,
5667 N: bool = false,
5668 shift: Shift.Op,
5669 decoded24: u5 = 0b01010,
5670 opc: LogicalOpc = .orr,
5671 sf: Register.IntegerSize,
5672 };
5673
5674 /// C6.2.239 ORN (shifted register)
5675 pub const Orn = packed struct {
5676 Rd: Register.Encoded,
5677 Rn: Register.Encoded,
5678 imm6: Shift.Amount,
5679 Rm: Register.Encoded,
5680 N: bool = true,
5681 shift: Shift.Op,
5682 decoded24: u5 = 0b01010,
5683 opc: LogicalOpc = .orr,
5684 sf: Register.IntegerSize,
5685 };
5686
5687 /// C6.2.120 EOR (shifted register)
5688 pub const Eor = packed struct {
5689 Rd: Register.Encoded,
5690 Rn: Register.Encoded,
5691 imm6: Shift.Amount,
5692 Rm: Register.Encoded,
5693 N: bool = false,
5694 shift: Shift.Op,
5695 decoded24: u5 = 0b01010,
5696 opc: LogicalOpc = .eor,
5697 sf: Register.IntegerSize,
5698 };
5699
5700 /// C6.2.118 EON (shifted register)
5701 pub const Eon = packed struct {
5702 Rd: Register.Encoded,
5703 Rn: Register.Encoded,
5704 imm6: Shift.Amount,
5705 Rm: Register.Encoded,
5706 N: bool = true,
5707 shift: Shift.Op,
5708 decoded24: u5 = 0b01010,
5709 opc: LogicalOpc = .eor,
5710 sf: Register.IntegerSize,
5711 };
5712
5713 /// C6.2.15 ANDS (shifted register)
5714 pub const Ands = packed struct {
5715 Rd: Register.Encoded,
5716 Rn: Register.Encoded,
5717 imm6: Shift.Amount,
5718 Rm: Register.Encoded,
5719 N: bool = false,
5720 shift: Shift.Op,
5721 decoded24: u5 = 0b01010,
5722 opc: LogicalOpc = .ands,
5723 sf: Register.IntegerSize,
5724 };
5725
5726 /// C6.2.33 BICS (shifted register)
5727 pub const Bics = packed struct {
5728 Rd: Register.Encoded,
5729 Rn: Register.Encoded,
5730 imm6: Shift.Amount,
5731 Rm: Register.Encoded,
5732 N: bool = true,
5733 shift: Shift.Op,
5734 decoded24: u5 = 0b01010,
5735 opc: LogicalOpc = .ands,
5736 sf: Register.IntegerSize,
5737 };
5738
5739 pub const Decoded = union(enum) {
5740 unallocated,
5741 @"and": And,
5742 bic: Bic,
5743 orr: Orr,
5744 orn: Orn,
5745 eor: Eor,
5746 eon: Eon,
5747 ands: Ands,
5748 bics: Bics,
5749 };
5750 pub fn decode(inst: @This()) @This().Decoded {
5751 return if (inst.group.sf == .word and @as(u1, @truncate(inst.group.imm6 >> 5)) == 0b1)
5752 .unallocated
5753 else switch (inst.group.opc) {
5754 .@"and" => switch (inst.group.N) {
5755 false => .{ .@"and" = inst.@"and" },
5756 true => .{ .bic = inst.bic },
5757 },
5758 .orr => switch (inst.group.N) {
5759 false => .{ .orr = inst.orr },
5760 true => .{ .orn = inst.orn },
5761 },
5762 .eor => switch (inst.group.N) {
5763 false => .{ .eor = inst.eor },
5764 true => .{ .eon = inst.eon },
5765 },
5766 .ands => switch (inst.group.N) {
5767 false => .{ .ands = inst.ands },
5768 true => .{ .bics = inst.bics },
5769 },
5770 };
5771 }
5772 };
5773
5774 /// Add/subtract (shifted register)
5775 pub const AddSubtractShiftedRegister = packed union {
5776 group: @This().Group,
5777 add: Add,
5778 adds: Adds,
5779 sub: Sub,
5780 subs: Subs,
5781
5782 pub const Group = packed struct {
5783 Rd: Register.Encoded,
5784 Rn: Register.Encoded,
5785 imm6: Shift.Amount,
5786 Rm: Register.Encoded,
5787 decoded21: u1 = 0b0,
5788 shift: Shift.Op,
5789 decoded24: u5 = 0b01011,
5790 S: bool,
5791 op: AddSubtractOp,
5792 sf: Register.IntegerSize,
5793 };
5794
5795 /// C6.2.5 ADD (shifted register)
5796 pub const Add = packed struct {
5797 Rd: Register.Encoded,
5798 Rn: Register.Encoded,
5799 imm6: Shift.Amount,
5800 Rm: Register.Encoded,
5801 decoded21: u1 = 0b0,
5802 shift: Shift.Op,
5803 decoded24: u5 = 0b01011,
5804 S: bool = false,
5805 op: AddSubtractOp = .add,
5806 sf: Register.IntegerSize,
5807 };
5808
5809 /// C6.2.9 ADDS (shifted register)
5810 pub const Adds = packed struct {
5811 Rd: Register.Encoded,
5812 Rn: Register.Encoded,
5813 imm6: Shift.Amount,
5814 Rm: Register.Encoded,
5815 decoded21: u1 = 0b0,
5816 shift: Shift.Op,
5817 decoded24: u5 = 0b01011,
5818 S: bool = true,
5819 op: AddSubtractOp = .add,
5820 sf: Register.IntegerSize,
5821 };
5822
5823 /// C6.2.5 SUB (shifted register)
5824 pub const Sub = packed struct {
5825 Rd: Register.Encoded,
5826 Rn: Register.Encoded,
5827 imm6: Shift.Amount,
5828 Rm: Register.Encoded,
5829 decoded21: u1 = 0b0,
5830 shift: Shift.Op,
5831 decoded24: u5 = 0b01011,
5832 S: bool = false,
5833 op: AddSubtractOp = .sub,
5834 sf: Register.IntegerSize,
5835 };
5836
5837 /// C6.2.9 SUBS (shifted register)
5838 pub const Subs = packed struct {
5839 Rd: Register.Encoded,
5840 Rn: Register.Encoded,
5841 imm6: Shift.Amount,
5842 Rm: Register.Encoded,
5843 decoded21: u1 = 0b0,
5844 shift: Shift.Op,
5845 decoded24: u5 = 0b01011,
5846 S: bool = true,
5847 op: AddSubtractOp = .sub,
5848 sf: Register.IntegerSize,
5849 };
5850
5851 pub const Decoded = union(enum) {
5852 unallocated,
5853 add: Add,
5854 adds: Adds,
5855 sub: Sub,
5856 subs: Subs,
5857 };
5858 pub fn decode(inst: @This()) @This().Decoded {
5859 return switch (inst.group.shift) {
5860 .ror => .unallocated,
5861 .lsl, .lsr, .asr => if (inst.group.sf == .word and @as(u1, @truncate(inst.group.imm6 >> 5)) == 0b1)
5862 .unallocated
5863 else switch (inst.group.op) {
5864 .add => switch (inst.group.S) {
5865 false => .{ .add = inst.add },
5866 true => .{ .adds = inst.adds },
5867 },
5868 .sub => switch (inst.group.S) {
5869 false => .{ .sub = inst.sub },
5870 true => .{ .subs = inst.subs },
5871 },
5872 },
5873 };
5874 }
5875 };
5876
5877 /// Add/subtract (extended register)
5878 pub const AddSubtractExtendedRegister = packed union {
5879 group: @This().Group,
5880 add: Add,
5881 adds: Adds,
5882 sub: Sub,
5883 subs: Subs,
5884
5885 pub const Group = packed struct {
5886 Rd: Register.Encoded,
5887 Rn: Register.Encoded,
5888 imm3: Extend.Amount,
5889 option: Option,
5890 Rm: Register.Encoded,
5891 decoded21: u1 = 0b1,
5892 opt: u2,
5893 decoded24: u5 = 0b01011,
5894 S: bool,
5895 op: AddSubtractOp,
5896 sf: Register.IntegerSize,
5897 };
5898
5899 /// C6.2.3 ADD (extended register)
5900 pub const Add = packed struct {
5901 Rd: Register.Encoded,
5902 Rn: Register.Encoded,
5903 imm3: Extend.Amount,
5904 option: Option,
5905 Rm: Register.Encoded,
5906 decoded21: u1 = 0b1,
5907 opt: u2 = 0b00,
5908 decoded24: u5 = 0b01011,
5909 S: bool = false,
5910 op: AddSubtractOp = .add,
5911 sf: Register.IntegerSize,
5912 };
5913
5914 /// C6.2.7 ADDS (extended register)
5915 pub const Adds = packed struct {
5916 Rd: Register.Encoded,
5917 Rn: Register.Encoded,
5918 imm3: Extend.Amount,
5919 option: Option,
5920 Rm: Register.Encoded,
5921 decoded21: u1 = 0b1,
5922 opt: u2 = 0b00,
5923 decoded24: u5 = 0b01011,
5924 S: bool = true,
5925 op: AddSubtractOp = .add,
5926 sf: Register.IntegerSize,
5927 };
5928
5929 /// C6.2.356 SUB (extended register)
5930 pub const Sub = packed struct {
5931 Rd: Register.Encoded,
5932 Rn: Register.Encoded,
5933 imm3: Extend.Amount,
5934 option: Option,
5935 Rm: Register.Encoded,
5936 decoded21: u1 = 0b1,
5937 opt: u2 = 0b00,
5938 decoded24: u5 = 0b01011,
5939 S: bool = false,
5940 op: AddSubtractOp = .sub,
5941 sf: Register.IntegerSize,
5942 };
5943
5944 /// C6.2.362 SUBS (extended register)
5945 pub const Subs = packed struct {
5946 Rd: Register.Encoded,
5947 Rn: Register.Encoded,
5948 imm3: Extend.Amount,
5949 option: Option,
5950 Rm: Register.Encoded,
5951 decoded21: u1 = 0b1,
5952 opt: u2 = 0b00,
5953 decoded24: u5 = 0b01011,
5954 S: bool = true,
5955 op: AddSubtractOp = .sub,
5956 sf: Register.IntegerSize,
5957 };
5958
5959 pub const Option = enum(u3) {
5960 uxtb = 0b000,
5961 uxth = 0b001,
5962 uxtw = 0b010,
5963 uxtx = 0b011,
5964 sxtb = 0b100,
5965 sxth = 0b101,
5966 sxtw = 0b110,
5967 sxtx = 0b111,
5968
5969 pub fn sf(option: Option) Register.IntegerSize {
5970 return switch (option) {
5971 .uxtb, .uxth, .uxtw, .sxtb, .sxth, .sxtw => .word,
5972 .uxtx, .sxtx => .doubleword,
5973 };
5974 }
5975 };
5976
5977 pub const Extend = union(Option) {
5978 uxtb: Amount,
5979 uxth: Amount,
5980 uxtw: Amount,
5981 uxtx: Amount,
5982 sxtb: Amount,
5983 sxth: Amount,
5984 sxtw: Amount,
5985 sxtx: Amount,
5986
5987 pub const Amount = u3;
5988 };
5989
5990 pub const Decoded = union(enum) {
5991 unallocated,
5992 add: Add,
5993 adds: Adds,
5994 sub: Sub,
5995 subs: Subs,
5996 };
5997 pub fn decode(inst: @This()) @This().Decoded {
5998 return switch (inst.group.imm3) {
5999 0b101 => .unallocated,
6000 0b110...0b111 => .unallocated,
6001 0b000...0b100 => switch (inst.group.opt) {
6002 0b01 => .unallocated,
6003 0b10...0b11 => .unallocated,
6004 0b00 => switch (inst.group.op) {
6005 .add => switch (inst.group.S) {
6006 false => .{ .add = inst.add },
6007 true => .{ .adds = inst.adds },
6008 },
6009 .sub => switch (inst.group.S) {
6010 false => .{ .sub = inst.sub },
6011 true => .{ .subs = inst.subs },
6012 },
6013 },
6014 },
6015 };
6016 }
6017 };
6018
6019 /// Add/subtract (with carry)
6020 pub const AddSubtractWithCarry = packed union {
6021 group: @This().Group,
6022 adc: Adc,
6023 adcs: Adcs,
6024 sbc: Sbc,
6025 sbcs: Sbcs,
6026
6027 pub const Group = packed struct {
6028 Rd: Register.Encoded,
6029 Rn: Register.Encoded,
6030 decoded10: u6 = 0b000000,
6031 Rm: Register.Encoded,
6032 decoded21: u8 = 0b11010000,
6033 S: bool,
6034 op: Op,
6035 sf: Register.IntegerSize,
6036 };
6037
6038 /// C6.2.1 ADC
6039 pub const Adc = packed struct {
6040 Rd: Register.Encoded,
6041 Rn: Register.Encoded,
6042 decoded10: u6 = 0b000000,
6043 Rm: Register.Encoded,
6044 decoded21: u8 = 0b11010000,
6045 S: bool = false,
6046 op: Op = .adc,
6047 sf: Register.IntegerSize,
6048 };
6049
6050 /// C6.2.2 ADCS
6051 pub const Adcs = packed struct {
6052 Rd: Register.Encoded,
6053 Rn: Register.Encoded,
6054 decoded10: u6 = 0b000000,
6055 Rm: Register.Encoded,
6056 decoded21: u8 = 0b11010000,
6057 S: bool = true,
6058 op: Op = .adc,
6059 sf: Register.IntegerSize,
6060 };
6061
6062 /// C6.2.265 SBC
6063 pub const Sbc = packed struct {
6064 Rd: Register.Encoded,
6065 Rn: Register.Encoded,
6066 decoded10: u6 = 0b000000,
6067 Rm: Register.Encoded,
6068 decoded21: u8 = 0b11010000,
6069 S: bool = false,
6070 op: Op = .sbc,
6071 sf: Register.IntegerSize,
6072 };
6073
6074 /// C6.2.266 SBCS
6075 pub const Sbcs = packed struct {
6076 Rd: Register.Encoded,
6077 Rn: Register.Encoded,
6078 decoded10: u6 = 0b000000,
6079 Rm: Register.Encoded,
6080 decoded21: u8 = 0b11010000,
6081 S: bool = true,
6082 op: Op = .sbc,
6083 sf: Register.IntegerSize,
6084 };
6085
6086 pub const Op = enum(u1) {
6087 adc = 0b0,
6088 sbc = 0b1,
6089 };
6090
6091 pub const Decoded = union(enum) {
6092 adc: Adc,
6093 adcs: Adcs,
6094 sbc: Sbc,
6095 sbcs: Sbcs,
6096 };
6097 pub fn decode(inst: @This()) @This().Decoded {
6098 return switch (inst.group.op) {
6099 .adc => switch (inst.group.S) {
6100 false => .{ .adc = inst.adc },
6101 true => .{ .adcs = inst.adcs },
6102 },
6103 .sbc => switch (inst.group.S) {
6104 false => .{ .sbc = inst.sbc },
6105 true => .{ .sbcs = inst.sbcs },
6106 },
6107 };
6108 }
6109 };
6110
6111 /// Rotate right into flags
6112 pub const RotateRightIntoFlags = packed union {
6113 group: @This().Group,
6114
6115 pub const Group = packed struct {
6116 mask: Nzcv,
6117 o2: u1,
6118 Rn: Register.Encoded,
6119 decoded10: u5 = 0b0001,
6120 imm6: u6,
6121 decoded21: u8 = 0b11010000,
6122 S: bool,
6123 op: u1,
6124 sf: Register.IntegerSize,
6125 };
6126 };
6127
6128 /// Evaluate into flags
6129 pub const EvaluateIntoFlags = packed union {
6130 group: @This().Group,
6131
6132 pub const Group = packed struct {
6133 mask: Nzcv,
6134 o3: u1,
6135 Rn: Register.Encoded,
6136 decoded10: u4 = 0b0010,
6137 sz: enum(u1) {
6138 byte = 0b0,
6139 word = 0b1,
6140 },
6141 opcode2: u6,
6142 decoded21: u8 = 0b11010000,
6143 S: bool,
6144 op: u1,
6145 sf: Register.IntegerSize,
6146 };
6147 };
6148
6149 /// Conditional compare (register)
6150 pub const ConditionalCompareRegister = packed union {
6151 group: @This().Group,
6152 ccmn: Ccmn,
6153 ccmp: Ccmp,
6154
6155 pub const Group = packed struct {
6156 nzcv: Nzcv,
6157 o3: u1,
6158 Rn: Register.Encoded,
6159 o2: u1,
6160 decoded11: u1 = 0b0,
6161 cond: ConditionCode,
6162 Rm: Register.Encoded,
6163 decoded21: u8 = 0b11010010,
6164 S: bool,
6165 op: Op,
6166 sf: Register.IntegerSize,
6167 };
6168
6169 /// C6.2.49 CCMN (register)
6170 pub const Ccmn = packed struct {
6171 nzcv: Nzcv,
6172 o3: u1 = 0b0,
6173 Rn: Register.Encoded,
6174 o2: u1 = 0b0,
6175 decoded11: u1 = 0b0,
6176 cond: ConditionCode,
6177 Rm: Register.Encoded,
6178 decoded21: u8 = 0b11010010,
6179 S: bool = true,
6180 op: Op = .ccmn,
6181 sf: Register.IntegerSize,
6182 };
6183
6184 /// C6.2.51 CCMP (register)
6185 pub const Ccmp = packed struct {
6186 nzcv: Nzcv,
6187 o3: u1 = 0b0,
6188 Rn: Register.Encoded,
6189 o2: u1 = 0b0,
6190 decoded11: u1 = 0b0,
6191 cond: ConditionCode,
6192 Rm: Register.Encoded,
6193 decoded21: u8 = 0b11010010,
6194 S: bool = true,
6195 op: Op = .ccmp,
6196 sf: Register.IntegerSize,
6197 };
6198
6199 pub const Op = enum(u1) {
6200 ccmn = 0b0,
6201 ccmp = 0b1,
6202 };
6203 };
6204
6205 /// Conditional compare (immediate)
6206 pub const ConditionalCompareImmediate = packed union {
6207 group: @This().Group,
6208 ccmn: Ccmn,
6209 ccmp: Ccmp,
6210
6211 pub const Group = packed struct {
6212 nzcv: Nzcv,
6213 o3: u1,
6214 Rn: Register.Encoded,
6215 o2: u1,
6216 decoded11: u1 = 0b1,
6217 cond: ConditionCode,
6218 imm5: u5,
6219 decoded21: u8 = 0b11010010,
6220 S: bool,
6221 op: Op,
6222 sf: Register.IntegerSize,
6223 };
6224
6225 /// C6.2.48 CCMN (immediate)
6226 pub const Ccmn = packed struct {
6227 nzcv: Nzcv,
6228 o3: u1 = 0b0,
6229 Rn: Register.Encoded,
6230 o2: u1 = 0b0,
6231 decoded11: u1 = 0b1,
6232 cond: ConditionCode,
6233 imm5: u5,
6234 decoded21: u8 = 0b11010010,
6235 S: bool = true,
6236 op: Op = .ccmn,
6237 sf: Register.IntegerSize,
6238 };
6239
6240 /// C6.2.50 CCMP (immediate)
6241 pub const Ccmp = packed struct {
6242 nzcv: Nzcv,
6243 o3: u1 = 0b0,
6244 Rn: Register.Encoded,
6245 o2: u1 = 0b0,
6246 decoded11: u1 = 0b1,
6247 cond: ConditionCode,
6248 imm5: u5,
6249 decoded21: u8 = 0b11010010,
6250 S: bool = true,
6251 op: Op = .ccmp,
6252 sf: Register.IntegerSize,
6253 };
6254
6255 pub const Op = enum(u1) {
6256 ccmn = 0b0,
6257 ccmp = 0b1,
6258 };
6259 };
6260
6261 /// Conditional select
6262 pub const ConditionalSelect = packed union {
6263 group: @This().Group,
6264 csel: Csel,
6265 csinc: Csinc,
6266 csinv: Csinv,
6267 csneg: Csneg,
6268
6269 pub const Group = packed struct {
6270 Rd: Register.Encoded,
6271 Rn: Register.Encoded,
6272 op2: u2,
6273 cond: ConditionCode,
6274 Rm: Register.Encoded,
6275 decoded21: u8 = 0b11010100,
6276 S: bool,
6277 op: u1,
6278 sf: Register.IntegerSize,
6279 };
6280
6281 /// C6.2.103 CSEL
6282 pub const Csel = packed struct {
6283 Rd: Register.Encoded,
6284 Rn: Register.Encoded,
6285 op2: u2 = 0b00,
6286 cond: ConditionCode,
6287 Rm: Register.Encoded,
6288 decoded21: u8 = 0b11010100,
6289 S: bool = false,
6290 op: u1 = 0b0,
6291 sf: Register.IntegerSize,
6292 };
6293
6294 /// C6.2.106 CSINC
6295 pub const Csinc = packed struct {
6296 Rd: Register.Encoded,
6297 Rn: Register.Encoded,
6298 op2: u2 = 0b01,
6299 cond: ConditionCode,
6300 Rm: Register.Encoded,
6301 decoded21: u8 = 0b11010100,
6302 S: bool = false,
6303 op: u1 = 0b0,
6304 sf: Register.IntegerSize,
6305 };
6306
6307 /// C6.2.107 CSINV
6308 pub const Csinv = packed struct {
6309 Rd: Register.Encoded,
6310 Rn: Register.Encoded,
6311 op2: u2 = 0b00,
6312 cond: ConditionCode,
6313 Rm: Register.Encoded,
6314 decoded21: u8 = 0b11010100,
6315 S: bool = false,
6316 op: u1 = 0b1,
6317 sf: Register.IntegerSize,
6318 };
6319
6320 /// C6.2.108 CSNEG
6321 pub const Csneg = packed struct {
6322 Rd: Register.Encoded,
6323 Rn: Register.Encoded,
6324 op2: u2 = 0b01,
6325 cond: ConditionCode,
6326 Rm: Register.Encoded,
6327 decoded21: u8 = 0b11010100,
6328 S: bool = false,
6329 op: u1 = 0b1,
6330 sf: Register.IntegerSize,
6331 };
6332
6333 pub const Decoded = union(enum) {
6334 unallocated,
6335 csel: Csel,
6336 csinc: Csinc,
6337 csinv: Csinv,
6338 csneg: Csneg,
6339 };
6340 pub fn decode(inst: @This()) @This().Decoded {
6341 return switch (inst.group.S) {
6342 true => .unallocated,
6343 false => switch (inst.group.op) {
6344 0b0 => switch (inst.group.op2) {
6345 0b10...0b11 => .unallocated,
6346 0b00 => .{ .csel = inst.csel },
6347 0b01 => .{ .csinc = inst.csinc },
6348 },
6349 0b1 => switch (inst.group.op2) {
6350 0b10...0b11 => .unallocated,
6351 0b00 => .{ .csinv = inst.csinv },
6352 0b01 => .{ .csneg = inst.csneg },
6353 },
6354 },
6355 };
6356 }
6357 };
6358
6359 /// Data-processing (3 source)
6360 pub const DataProcessingThreeSource = packed union {
6361 group: @This().Group,
6362 madd: Madd,
6363 msub: Msub,
6364 smaddl: Smaddl,
6365 smsubl: Smsubl,
6366 smulh: Smulh,
6367 umaddl: Umaddl,
6368 umsubl: Umsubl,
6369 umulh: Umulh,
6370
6371 pub const Group = packed struct {
6372 Rd: Register.Encoded,
6373 Rn: Register.Encoded,
6374 Ra: Register.Encoded,
6375 o0: AddSubtractOp,
6376 Rm: Register.Encoded,
6377 op31: u3,
6378 decoded24: u5 = 0b11011,
6379 op54: u2,
6380 sf: Register.IntegerSize,
6381 };
6382
6383 /// C6.2.218 MADD
6384 pub const Madd = packed struct {
6385 Rd: Register.Encoded,
6386 Rn: Register.Encoded,
6387 Ra: Register.Encoded,
6388 o0: AddSubtractOp = .add,
6389 Rm: Register.Encoded,
6390 op31: u3 = 0b000,
6391 decoded24: u5 = 0b11011,
6392 op54: u2 = 0b00,
6393 sf: Register.IntegerSize,
6394 };
6395
6396 /// C6.2.231 MSUB
6397 pub const Msub = packed struct {
6398 Rd: Register.Encoded,
6399 Rn: Register.Encoded,
6400 Ra: Register.Encoded,
6401 o0: AddSubtractOp = .sub,
6402 Rm: Register.Encoded,
6403 op31: u3 = 0b000,
6404 decoded24: u5 = 0b11011,
6405 op54: u2 = 0b00,
6406 sf: Register.IntegerSize,
6407 };
6408
6409 /// C6.2.282 SMADDL
6410 pub const Smaddl = packed struct {
6411 Rd: Register.Encoded,
6412 Rn: Register.Encoded,
6413 Ra: Register.Encoded,
6414 o0: AddSubtractOp = .add,
6415 Rm: Register.Encoded,
6416 op21: u2 = 0b01,
6417 U: bool = false,
6418 decoded24: u5 = 0b11011,
6419 op54: u2 = 0b00,
6420 sf: Register.IntegerSize = .doubleword,
6421 };
6422
6423 /// C6.2.287 SMSUBL
6424 pub const Smsubl = packed struct {
6425 Rd: Register.Encoded,
6426 Rn: Register.Encoded,
6427 Ra: Register.Encoded,
6428 o0: AddSubtractOp = .sub,
6429 Rm: Register.Encoded,
6430 op21: u2 = 0b01,
6431 U: bool = false,
6432 decoded24: u5 = 0b11011,
6433 op54: u2 = 0b00,
6434 sf: Register.IntegerSize = .doubleword,
6435 };
6436
6437 /// C6.2.288 SMULH
6438 pub const Smulh = packed struct {
6439 Rd: Register.Encoded,
6440 Rn: Register.Encoded,
6441 Ra: Register.Encoded = @enumFromInt(0b11111),
6442 o0: AddSubtractOp = .add,
6443 Rm: Register.Encoded,
6444 op21: u2 = 0b10,
6445 U: bool = false,
6446 decoded24: u5 = 0b11011,
6447 op54: u2 = 0b00,
6448 sf: Register.IntegerSize = .doubleword,
6449 };
6450
6451 /// C6.2.389 UMADDL
6452 pub const Umaddl = packed struct {
6453 Rd: Register.Encoded,
6454 Rn: Register.Encoded,
6455 Ra: Register.Encoded,
6456 o0: AddSubtractOp = .add,
6457 Rm: Register.Encoded,
6458 op21: u2 = 0b01,
6459 U: bool = true,
6460 decoded24: u5 = 0b11011,
6461 op54: u2 = 0b00,
6462 sf: Register.IntegerSize = .doubleword,
6463 };
6464
6465 /// C6.2.391 UMSUBL
6466 pub const Umsubl = packed struct {
6467 Rd: Register.Encoded,
6468 Rn: Register.Encoded,
6469 Ra: Register.Encoded,
6470 o0: AddSubtractOp = .sub,
6471 Rm: Register.Encoded,
6472 op21: u2 = 0b01,
6473 U: bool = true,
6474 decoded24: u5 = 0b11011,
6475 op54: u2 = 0b00,
6476 sf: Register.IntegerSize = .doubleword,
6477 };
6478
6479 /// C6.2.392 UMULH
6480 pub const Umulh = packed struct {
6481 Rd: Register.Encoded,
6482 Rn: Register.Encoded,
6483 Ra: Register.Encoded = @enumFromInt(0b11111),
6484 o0: AddSubtractOp = .add,
6485 Rm: Register.Encoded,
6486 op21: u2 = 0b10,
6487 U: bool = true,
6488 decoded24: u5 = 0b11011,
6489 op54: u2 = 0b00,
6490 sf: Register.IntegerSize = .doubleword,
6491 };
6492
6493 pub const Decoded = union(enum) {
6494 unallocated,
6495 madd: Madd,
6496 msub: Msub,
6497 smaddl: Smaddl,
6498 smsubl: Smsubl,
6499 smulh: Smulh,
6500 umaddl: Umaddl,
6501 umsubl: Umsubl,
6502 umulh: Umulh,
6503 };
6504 pub fn decode(inst: @This()) @This().Decoded {
6505 return switch (inst.group.op54) {
6506 0b01, 0b10...0b11 => .unallocated,
6507 0b00 => switch (inst.group.op31) {
6508 0b011, 0b100, 0b111 => .unallocated,
6509 0b000 => switch (inst.group.o0) {
6510 .add => .{ .madd = inst.madd },
6511 .sub => .{ .msub = inst.msub },
6512 },
6513 0b001 => switch (inst.group.sf) {
6514 .word => .unallocated,
6515 .doubleword => switch (inst.group.o0) {
6516 .add => .{ .smaddl = inst.smaddl },
6517 .sub => .{ .smsubl = inst.smsubl },
6518 },
6519 },
6520 0b010 => switch (inst.group.sf) {
6521 .word => .unallocated,
6522 .doubleword => switch (inst.group.o0) {
6523 .add => .{ .smulh = inst.smulh },
6524 .sub => .unallocated,
6525 },
6526 },
6527 0b101 => switch (inst.group.sf) {
6528 .word => .unallocated,
6529 .doubleword => switch (inst.group.o0) {
6530 .add => .{ .umaddl = inst.umaddl },
6531 .sub => .{ .umsubl = inst.umsubl },
6532 },
6533 },
6534 0b110 => switch (inst.group.sf) {
6535 .word => .unallocated,
6536 .doubleword => switch (inst.group.o0) {
6537 .add => .{ .umulh = inst.umulh },
6538 .sub => .unallocated,
6539 },
6540 },
6541 },
6542 };
6543 }
6544 };
6545
6546 pub const Shift = union(enum(u2)) {
6547 lsl: Amount = 0b00,
6548 lsr: Amount = 0b01,
6549 asr: Amount = 0b10,
6550 ror: Amount = 0b11,
6551
6552 pub const Op = @typeInfo(Shift).@"union".tag_type.?;
6553 pub const Amount = u6;
6554 pub const none: Shift = .{ .lsl = 0 };
6555 };
6556
6557 pub const Nzcv = packed struct { v: bool, c: bool, z: bool, n: bool };
6558
6559 pub const Decoded = union(enum) {
6560 unallocated,
6561 data_processing_two_source: DataProcessingTwoSource,
6562 data_processing_one_source: DataProcessingOneSource,
6563 logical_shifted_register: LogicalShiftedRegister,
6564 add_subtract_shifted_register: AddSubtractShiftedRegister,
6565 add_subtract_extended_register: AddSubtractExtendedRegister,
6566 add_subtract_with_carry: AddSubtractWithCarry,
6567 rotate_right_into_flags: RotateRightIntoFlags,
6568 evaluate_into_flags: EvaluateIntoFlags,
6569 conditional_compare_register: ConditionalCompareRegister,
6570 conditional_compare_immediate: ConditionalCompareImmediate,
6571 conditional_select: ConditionalSelect,
6572 data_processing_three_source: DataProcessingThreeSource,
6573 };
6574 pub fn decode(inst: @This()) @This().Decoded {
6575 return switch (inst.group.op1) {
6576 0b0 => switch (@as(u1, @truncate(inst.group.op2 >> 3))) {
6577 0b0 => .{ .logical_shifted_register = inst.logical_shifted_register },
6578 0b1 => switch (@as(u1, @truncate(inst.group.op2 >> 0))) {
6579 0b0 => .{ .add_subtract_shifted_register = inst.add_subtract_shifted_register },
6580 0b1 => .{ .add_subtract_extended_register = inst.add_subtract_extended_register },
6581 },
6582 },
6583 0b1 => switch (inst.group.op2) {
6584 0b0000 => switch (inst.group.op3) {
6585 0b000000 => .{ .add_subtract_with_carry = inst.add_subtract_with_carry },
6586 0b000001, 0b100001 => .{ .rotate_right_into_flags = inst.rotate_right_into_flags },
6587 0b000010, 0b010010, 0b100010, 0b110010 => .{ .evaluate_into_flags = inst.evaluate_into_flags },
6588 else => .unallocated,
6589 },
6590 0b0010 => switch (@as(u1, @truncate(inst.group.op3 >> 1))) {
6591 0b0 => .{ .conditional_compare_register = inst.conditional_compare_register },
6592 0b1 => .{ .conditional_compare_immediate = inst.conditional_compare_immediate },
6593 },
6594 0b0100 => .{ .conditional_select = inst.conditional_select },
6595 0b0110 => switch (inst.group.op0) {
6596 0b0 => .{ .data_processing_two_source = inst.data_processing_two_source },
6597 0b1 => .{ .data_processing_one_source = inst.data_processing_one_source },
6598 },
6599 0b1000...0b1111 => .{ .data_processing_three_source = inst.data_processing_three_source },
6600 else => .unallocated,
6601 },
6602 };
6603 }
6604 };
6605
6606 /// C4.1.90 Data Processing -- Scalar Floating-Point and Advanced SIMD
6607 pub const DataProcessingVector = packed union {
6608 group: @This().Group,
6609 simd_scalar_pairwise: SimdScalarPairwise,
6610 simd_copy: SimdCopy,
6611 simd_two_register_miscellaneous: SimdTwoRegisterMiscellaneous,
6612 simd_across_lanes: SimdAcrossLanes,
6613 simd_three_same: SimdThreeSame,
6614 simd_modified_immediate: SimdModifiedImmediate,
6615 convert_float_integer: ConvertFloatInteger,
6616 float_data_processing_one_source: FloatDataProcessingOneSource,
6617 float_compare: FloatCompare,
6618 float_immediate: FloatImmediate,
6619 float_data_processing_two_source: FloatDataProcessingTwoSource,
6620 float_data_processing_three_source: FloatDataProcessingThreeSource,
6621
6622 /// Table C4-91 Encoding table for the Data Processing -- Scalar Floating-Point and Advanced SIMD group
6623 pub const Group = packed struct {
6624 encoded0: u10,
6625 op3: u9,
6626 op2: u4,
6627 op1: u2,
6628 decoded25: u3 = 0b111,
6629 op0: u4,
6630 };
6631
6632 /// Advanced SIMD scalar pairwise
6633 pub const SimdScalarPairwise = packed union {
6634 group: @This().Group,
6635 addp: Addp,
6636
6637 pub const Group = packed struct {
6638 Rd: Register.Encoded,
6639 Rn: Register.Encoded,
6640 decoded10: u2 = 0b10,
6641 opcode: u5,
6642 decoded17: u5 = 0b11000,
6643 size: Size,
6644 decoded24: u5 = 0b11110,
6645 U: u1,
6646 decoded30: u2 = 0b01,
6647 };
6648
6649 /// C7.2.4 ADDP (scalar)
6650 pub const Addp = packed struct {
6651 Rd: Register.Encoded,
6652 Rn: Register.Encoded,
6653 decoded10: u2 = 0b10,
6654 opcode: u5 = 0b11011,
6655 decoded17: u5 = 0b11000,
6656 size: Size,
6657 decoded24: u5 = 0b11110,
6658 U: u1 = 0b0,
6659 decoded30: u2 = 0b01,
6660 };
6661 };
6662
6663 /// Advanced SIMD copy
6664 pub const SimdCopy = packed union {
6665 group: @This().Group,
6666 smov: Smov,
6667 umov: Umov,
6668
6669 pub const Group = packed struct {
6670 Rd: Register.Encoded,
6671 Rn: Register.Encoded,
6672 decoded10: u1 = 0b1,
6673 imm4: u4,
6674 decoded15: u1 = 0b0,
6675 imm5: u5,
6676 decoded21: u8 = 0b01110000,
6677 op: u1,
6678 Q: Register.IntegerSize,
6679 decoded31: u1 = 0b0,
6680 };
6681
6682 /// C7.2.279 SMOV
6683 pub const Smov = packed struct {
6684 Rd: Register.Encoded,
6685 Rn: Register.Encoded,
6686 decoded10: u1 = 0b1,
6687 decoded11: u1 = 0b1,
6688 decoded12: u1 = 0b0,
6689 decoded13: u2 = 0b01,
6690 decoded15: u1 = 0b0,
6691 imm5: u5,
6692 decoded21: u8 = 0b01110000,
6693 decoded29: u1 = 0b0,
6694 Q: Register.IntegerSize,
6695 decoded31: u1 = 0b0,
6696 };
6697
6698 /// C7.2.371 UMOV
6699 pub const Umov = packed struct {
6700 Rd: Register.Encoded,
6701 Rn: Register.Encoded,
6702 decoded10: u1 = 0b1,
6703 decoded11: u1 = 0b1,
6704 decoded12: u1 = 0b1,
6705 decoded13: u2 = 0b01,
6706 decoded15: u1 = 0b0,
6707 imm5: u5,
6708 decoded21: u8 = 0b01110000,
6709 decoded29: u1 = 0b0,
6710 Q: Register.IntegerSize,
6711 decoded31: u1 = 0b0,
6712 };
6713 };
6714
6715 /// Advanced SIMD two-register miscellaneous
6716 pub const SimdTwoRegisterMiscellaneous = packed union {
6717 group: @This().Group,
6718 cnt: Cnt,
6719
6720 pub const Group = packed struct {
6721 Rd: Register.Encoded,
6722 Rn: Register.Encoded,
6723 decoded10: u2 = 0b10,
6724 opcode: u5,
6725 decoded17: u5 = 0b10000,
6726 size: Size,
6727 decoded24: u5 = 0b01110,
6728 U: u1,
6729 Q: Q,
6730 decoded31: u1 = 0b0,
6731 };
6732
6733 /// C7.2.38 CNT
6734 pub const Cnt = packed struct {
6735 Rd: Register.Encoded,
6736 Rn: Register.Encoded,
6737 decoded10: u2 = 0b10,
6738 opcode: u5 = 0b00101,
6739 decoded17: u5 = 0b10000,
6740 size: Size,
6741 decoded24: u5 = 0b01110,
6742 U: u1 = 0b0,
6743 Q: Q,
6744 decoded31: u1 = 0b0,
6745 };
6746 };
6747
6748 /// Advanced SIMD across lanes
6749 pub const SimdAcrossLanes = packed union {
6750 group: @This().Group,
6751 addv: Addv,
6752
6753 pub const Group = packed struct {
6754 Rd: Register.Encoded,
6755 Rn: Register.Encoded,
6756 decoded10: u2 = 0b10,
6757 opcode: u5,
6758 decoded17: u5 = 0b11000,
6759 size: Size,
6760 decoded24: u5 = 0b01110,
6761 U: u1,
6762 Q: Q,
6763 decoded31: u1 = 0b0,
6764 };
6765
6766 /// C7.2.6 ADDV
6767 pub const Addv = packed struct {
6768 Rd: Register.Encoded,
6769 Rn: Register.Encoded,
6770 decoded10: u2 = 0b10,
6771 opcode: u5 = 0b11011,
6772 decoded17: u5 = 0b11000,
6773 size: Size,
6774 decoded24: u5 = 0b01110,
6775 U: u1 = 0b0,
6776 Q: Q,
6777 decoded31: u1 = 0b0,
6778 };
6779 };
6780
6781 /// Advanced SIMD three same
6782 pub const SimdThreeSame = packed union {
6783 group: @This().Group,
6784 addp: Addp,
6785 @"and": And,
6786 bic: Bic,
6787 orr: Orr,
6788 orn: Orn,
6789 eor: Eor,
6790
6791 pub const Group = packed struct {
6792 Rd: Register.Encoded,
6793 Rn: Register.Encoded,
6794 decoded10: u1 = 0b1,
6795 opcode: u5,
6796 Rm: Register.Encoded,
6797 decoded21: u1 = 0b1,
6798 size: Size,
6799 decoded24: u5 = 0b01110,
6800 U: u1,
6801 Q: Q,
6802 decoded31: u1 = 0b0,
6803 };
6804
6805 /// C7.2.5 ADDP (vector)
6806 pub const Addp = packed struct {
6807 Rd: Register.Encoded,
6808 Rn: Register.Encoded,
6809 decoded10: u1 = 0b1,
6810 opcode: u5 = 0b10111,
6811 Rm: Register.Encoded,
6812 decoded21: u1 = 0b1,
6813 size: Size,
6814 decoded24: u5 = 0b01110,
6815 U: u1 = 0b0,
6816 Q: Q,
6817 decoded31: u1 = 0b0,
6818 };
6819
6820 /// C7.2.11 AND (vector)
6821 pub const And = packed struct {
6822 Rd: Register.Encoded,
6823 Rn: Register.Encoded,
6824 decoded10: u1 = 0b1,
6825 opcode: u5 = 0b00011,
6826 Rm: Register.Encoded,
6827 decoded21: u1 = 0b1,
6828 size: Size = .byte,
6829 decoded24: u5 = 0b01110,
6830 U: u1 = 0b0,
6831 Q: Q,
6832 decoded31: u1 = 0b0,
6833 };
6834
6835 /// C7.2.21 BIC (vector, register)
6836 pub const Bic = packed struct {
6837 Rd: Register.Encoded,
6838 Rn: Register.Encoded,
6839 decoded10: u1 = 0b1,
6840 opcode: u5 = 0b00011,
6841 Rm: Register.Encoded,
6842 decoded21: u1 = 0b1,
6843 size: Size = .half,
6844 decoded24: u5 = 0b01110,
6845 U: u1 = 0b0,
6846 Q: Q,
6847 decoded31: u1 = 0b0,
6848 };
6849
6850 /// C7.2.213 ORR (vector, register)
6851 pub const Orr = packed struct {
6852 Rd: Register.Encoded,
6853 Rn: Register.Encoded,
6854 decoded10: u1 = 0b1,
6855 opcode: u5 = 0b00011,
6856 Rm: Register.Encoded,
6857 decoded21: u1 = 0b1,
6858 size: Size = .single,
6859 decoded24: u5 = 0b01110,
6860 U: u1 = 0b0,
6861 Q: Q,
6862 decoded31: u1 = 0b0,
6863 };
6864
6865 /// C7.2.211 ORN (vector)
6866 pub const Orn = packed struct {
6867 Rd: Register.Encoded,
6868 Rn: Register.Encoded,
6869 decoded10: u1 = 0b1,
6870 opcode: u5 = 0b00011,
6871 Rm: Register.Encoded,
6872 decoded21: u1 = 0b1,
6873 size: Size = .double,
6874 decoded24: u5 = 0b01110,
6875 U: u1 = 0b0,
6876 Q: Q,
6877 decoded31: u1 = 0b0,
6878 };
6879
6880 /// C7.2.41 EOR (vector)
6881 pub const Eor = packed struct {
6882 Rd: Register.Encoded,
6883 Rn: Register.Encoded,
6884 decoded10: u1 = 0b1,
6885 opcode: u5 = 0b00011,
6886 Rm: Register.Encoded,
6887 decoded21: u1 = 0b1,
6888 size: Size = .byte,
6889 decoded24: u5 = 0b01110,
6890 U: u1 = 0b1,
6891 Q: Q,
6892 decoded31: u1 = 0b0,
6893 };
6894 };
6895
6896 /// Advanced SIMD modified immediate
6897 pub const SimdModifiedImmediate = packed union {
6898 group: @This().Group,
6899 movi: Movi,
6900 orr: Orr,
6901 fmov: Fmov,
6902 mvni: Mvni,
6903 bic: Bic,
6904
6905 pub const Group = packed struct {
6906 Rd: Register.Encoded,
6907 imm5: u5,
6908 decoded10: u1 = 0b1,
6909 o2: u1,
6910 cmode: u4,
6911 imm3: u3,
6912 decoded19: u10 = 0b0111100000,
6913 op: u1,
6914 Q: Q,
6915 decoded31: u1 = 0b0,
6916 };
6917
6918 /// C7.2.204 MOVI
6919 pub const Movi = packed struct {
6920 Rd: Register.Encoded,
6921 imm5: u5,
6922 decoded10: u1 = 0b1,
6923 o2: u1 = 0b0,
6924 cmode: u4,
6925 imm3: u3,
6926 decoded19: u10 = 0b0111100000,
6927 op: u1,
6928 Q: Q,
6929 decoded31: u1 = 0b0,
6930 };
6931
6932 /// C7.2.212 ORR (vector, immediate)
6933 pub const Orr = packed struct {
6934 Rd: Register.Encoded,
6935 imm5: u5,
6936 decoded10: u1 = 0b1,
6937 o2: u1 = 0b0,
6938 cmode0: u1 = 0b1,
6939 cmode: u3,
6940 imm3: u3,
6941 decoded19: u10 = 0b0111100000,
6942 op: u1 = 0b0,
6943 Q: Q,
6944 decoded31: u1 = 0b0,
6945 };
6946
6947 /// C7.2.129 FMOV (vector, immediate)
6948 pub const Fmov = packed struct {
6949 Rd: Register.Encoded,
6950 imm5: u5,
6951 decoded10: u1 = 0b1,
6952 o2: u1 = 0b1,
6953 cmode: u4 = 0b1111,
6954 imm3: u3,
6955 decoded19: u10 = 0b0111100000,
6956 op: u1 = 0b0,
6957 Q: Q,
6958 decoded31: u1 = 0b0,
6959 };
6960
6961 /// C7.2.208 MVNI
6962 pub const Mvni = packed struct {
6963 Rd: Register.Encoded,
6964 imm5: u5,
6965 decoded10: u1 = 0b1,
6966 o2: u1 = 0b0,
6967 cmode: u4,
6968 imm3: u3,
6969 decoded19: u10 = 0b0111100000,
6970 op: u1 = 0b1,
6971 Q: Q,
6972 decoded31: u1 = 0b0,
6973 };
6974
6975 /// C7.2.20 BIC (vector, immediate)
6976 pub const Bic = packed struct {
6977 Rd: Register.Encoded,
6978 imm5: u5,
6979 decoded10: u1 = 0b1,
6980 o2: u1 = 0b0,
6981 cmode0: u1 = 0b1,
6982 cmode: u3,
6983 imm3: u3,
6984 decoded19: u10 = 0b0111100000,
6985 op: u1 = 0b1,
6986 Q: Q,
6987 decoded31: u1 = 0b0,
6988 };
6989 };
6990
6991 /// Conversion between floating-point and integer
6992 pub const ConvertFloatInteger = packed union {
6993 group: @This().Group,
6994 fcvtns: Fcvtns,
6995 fcvtnu: Fcvtnu,
6996 scvtf: Scvtf,
6997 ucvtf: Ucvtf,
6998 fcvtas: Fcvtas,
6999 fcvtau: Fcvtau,
7000 fmov: Fmov,
7001 fcvtps: Fcvtps,
7002 fcvtpu: Fcvtpu,
7003 fcvtms: Fcvtms,
7004 fcvtmu: Fcvtmu,
7005 fcvtzs: Fcvtzs,
7006 fcvtzu: Fcvtzu,
7007 fjcvtzs: Fjcvtzs,
7008
7009 pub const Group = packed struct {
7010 Rd: Register.Encoded,
7011 Rn: Register.Encoded,
7012 decoded10: u6 = 0b000000,
7013 opcode: u3,
7014 rmode: u2,
7015 decoded21: u1 = 0b1,
7016 ptype: Ftype,
7017 decoded24: u5 = 0b11110,
7018 S: bool,
7019 decoded30: u1 = 0b0,
7020 sf: Register.IntegerSize,
7021 };
7022
7023 /// C7.2.81 FCVTNS (scalar)
7024 pub const Fcvtns = packed struct {
7025 Rd: Register.Encoded,
7026 Rn: Register.Encoded,
7027 decoded10: u6 = 0b000000,
7028 opcode: u3 = 0b000,
7029 rmode: Rmode = .n,
7030 decoded21: u1 = 0b1,
7031 ftype: Ftype,
7032 decoded24: u5 = 0b11110,
7033 S: bool = false,
7034 decoded30: u1 = 0b0,
7035 sf: Register.IntegerSize,
7036 };
7037
7038 /// C7.2.83 FCVTNU (scalar)
7039 pub const Fcvtnu = packed struct {
7040 Rd: Register.Encoded,
7041 Rn: Register.Encoded,
7042 decoded10: u6 = 0b000000,
7043 opcode: u3 = 0b001,
7044 rmode: Rmode = .n,
7045 decoded21: u1 = 0b1,
7046 ftype: Ftype,
7047 decoded24: u5 = 0b11110,
7048 S: bool = false,
7049 decoded30: u1 = 0b0,
7050 sf: Register.IntegerSize,
7051 };
7052
7053 /// C7.2.236 SCVTF (scalar, integer)
7054 pub const Scvtf = packed struct {
7055 Rd: Register.Encoded,
7056 Rn: Register.Encoded,
7057 decoded10: u6 = 0b000000,
7058 opcode: u3 = 0b010,
7059 rmode: Rmode = .n,
7060 decoded21: u1 = 0b1,
7061 ftype: Ftype,
7062 decoded24: u5 = 0b11110,
7063 S: bool = false,
7064 decoded30: u1 = 0b0,
7065 sf: Register.IntegerSize,
7066 };
7067
7068 /// C7.2.355 UCVTF (scalar, integer)
7069 pub const Ucvtf = packed struct {
7070 Rd: Register.Encoded,
7071 Rn: Register.Encoded,
7072 decoded10: u6 = 0b000000,
7073 opcode: u3 = 0b011,
7074 rmode: Rmode = .n,
7075 decoded21: u1 = 0b1,
7076 ftype: Ftype,
7077 decoded24: u5 = 0b11110,
7078 S: bool = false,
7079 decoded30: u1 = 0b0,
7080 sf: Register.IntegerSize,
7081 };
7082
7083 /// C7.2.71 FCVTAS (scalar)
7084 pub const Fcvtas = packed struct {
7085 Rd: Register.Encoded,
7086 Rn: Register.Encoded,
7087 decoded10: u6 = 0b000000,
7088 opcode: u3 = 0b100,
7089 rmode: Rmode = .n,
7090 decoded21: u1 = 0b1,
7091 ftype: Ftype,
7092 decoded24: u5 = 0b11110,
7093 S: bool = false,
7094 decoded30: u1 = 0b0,
7095 sf: Register.IntegerSize,
7096 };
7097
7098 /// C7.2.73 FCVTAU (scalar)
7099 pub const Fcvtau = packed struct {
7100 Rd: Register.Encoded,
7101 Rn: Register.Encoded,
7102 decoded10: u6 = 0b000000,
7103 opcode: u3 = 0b101,
7104 rmode: Rmode = .n,
7105 decoded21: u1 = 0b1,
7106 ftype: Ftype,
7107 decoded24: u5 = 0b11110,
7108 S: bool = false,
7109 decoded30: u1 = 0b0,
7110 sf: Register.IntegerSize,
7111 };
7112
7113 /// C7.2.131 FMOV (general)
7114 pub const Fmov = packed struct {
7115 Rd: Register.Encoded,
7116 Rn: Register.Encoded,
7117 decoded10: u6 = 0b000000,
7118 opcode: Opcode,
7119 rmode: Fmov.Rmode,
7120 decoded21: u1 = 0b1,
7121 ftype: Ftype,
7122 decoded24: u5 = 0b11110,
7123 S: bool = false,
7124 decoded30: u1 = 0b0,
7125 sf: Register.IntegerSize,
7126
7127 pub const Opcode = enum(u3) {
7128 float_to_integer = 0b110,
7129 integer_to_float = 0b111,
7130 _,
7131 };
7132
7133 pub const Rmode = enum(u2) {
7134 @"0" = 0b00,
7135 @"1" = 0b01,
7136 _,
7137 };
7138 };
7139
7140 /// C7.2.85 FCVTPS (scalar)
7141 pub const Fcvtps = packed struct {
7142 Rd: Register.Encoded,
7143 Rn: Register.Encoded,
7144 decoded10: u6 = 0b000000,
7145 opcode: u3 = 0b000,
7146 rmode: Rmode = .p,
7147 decoded21: u1 = 0b1,
7148 ftype: Ftype,
7149 decoded24: u5 = 0b11110,
7150 S: bool = false,
7151 decoded30: u1 = 0b0,
7152 sf: Register.IntegerSize,
7153 };
7154
7155 /// C7.2.87 FCVTPU (scalar)
7156 pub const Fcvtpu = packed struct {
7157 Rd: Register.Encoded,
7158 Rn: Register.Encoded,
7159 decoded10: u6 = 0b000000,
7160 opcode: u3 = 0b001,
7161 rmode: Rmode = .p,
7162 decoded21: u1 = 0b1,
7163 ftype: Ftype,
7164 decoded24: u5 = 0b11110,
7165 S: bool = false,
7166 decoded30: u1 = 0b0,
7167 sf: Register.IntegerSize,
7168 };
7169
7170 /// C7.2.76 FCVTMS (scalar)
7171 pub const Fcvtms = packed struct {
7172 Rd: Register.Encoded,
7173 Rn: Register.Encoded,
7174 decoded10: u6 = 0b000000,
7175 opcode: u3 = 0b000,
7176 rmode: Rmode = .m,
7177 decoded21: u1 = 0b1,
7178 ftype: Ftype,
7179 decoded24: u5 = 0b11110,
7180 S: bool = false,
7181 decoded30: u1 = 0b0,
7182 sf: Register.IntegerSize,
7183 };
7184
7185 /// C7.2.78 FCVTMU (scalar)
7186 pub const Fcvtmu = packed struct {
7187 Rd: Register.Encoded,
7188 Rn: Register.Encoded,
7189 decoded10: u6 = 0b000000,
7190 opcode: u3 = 0b001,
7191 rmode: Rmode = .m,
7192 decoded21: u1 = 0b1,
7193 ftype: Ftype,
7194 decoded24: u5 = 0b11110,
7195 S: bool = false,
7196 decoded30: u1 = 0b0,
7197 sf: Register.IntegerSize,
7198 };
7199
7200 /// C7.2.92 FCVTZS (scalar, integer)
7201 pub const Fcvtzs = packed struct {
7202 Rd: Register.Encoded,
7203 Rn: Register.Encoded,
7204 decoded10: u6 = 0b000000,
7205 opcode: u3 = 0b000,
7206 rmode: Rmode = .z,
7207 decoded21: u1 = 0b1,
7208 ftype: Ftype,
7209 decoded24: u5 = 0b11110,
7210 S: bool = false,
7211 decoded30: u1 = 0b0,
7212 sf: Register.IntegerSize,
7213 };
7214
7215 /// C7.2.96 FCVTZU (scalar, integer)
7216 pub const Fcvtzu = packed struct {
7217 Rd: Register.Encoded,
7218 Rn: Register.Encoded,
7219 decoded10: u6 = 0b000000,
7220 opcode: u3 = 0b001,
7221 rmode: Rmode = .z,
7222 decoded21: u1 = 0b1,
7223 ftype: Ftype,
7224 decoded24: u5 = 0b11110,
7225 S: bool = false,
7226 decoded30: u1 = 0b0,
7227 sf: Register.IntegerSize,
7228 };
7229
7230 /// C7.2.99 FJCVTZS
7231 pub const Fjcvtzs = packed struct {
7232 Rd: Register.Encoded,
7233 Rn: Register.Encoded,
7234 decoded10: u6 = 0b000000,
7235 opcode: u3 = 0b110,
7236 rmode: Rmode = .z,
7237 decoded21: u1 = 0b1,
7238 ftype: Ftype = .double,
7239 decoded24: u5 = 0b11110,
7240 S: bool = false,
7241 decoded30: u1 = 0b0,
7242 sf: Register.IntegerSize = .word,
7243 };
7244
7245 pub const Rmode = enum(u2) {
7246 /// to nearest
7247 n = 0b00,
7248 /// toward plus infinity
7249 p = 0b01,
7250 /// toward minus infinity
7251 m = 0b10,
7252 /// toward zero
7253 z = 0b11,
7254 };
7255 };
7256
7257 /// Floating-point data-processing (1 source)
7258 pub const FloatDataProcessingOneSource = packed union {
7259 group: @This().Group,
7260 fmov: Fmov,
7261 fabs: Fabs,
7262 fneg: Fneg,
7263 fsqrt: Fsqrt,
7264 fcvt: Fcvt,
7265 frintn: Frintn,
7266 frintp: Frintp,
7267 frintm: Frintm,
7268 frintz: Frintz,
7269 frinta: Frinta,
7270 frintx: Frintx,
7271 frinti: Frinti,
7272
7273 pub const Group = packed struct {
7274 Rd: Register.Encoded,
7275 Rn: Register.Encoded,
7276 decoded10: u5 = 0b10000,
7277 opcode: u6,
7278 decoded21: u1 = 0b1,
7279 ptype: Ftype,
7280 decoded24: u5 = 0b11110,
7281 S: bool,
7282 decoded30: u1 = 0b0,
7283 M: u1,
7284 };
7285
7286 /// C7.2.130 FMOV (register)
7287 pub const Fmov = packed struct {
7288 Rd: Register.Encoded,
7289 Rn: Register.Encoded,
7290 decoded10: u5 = 0b10000,
7291 opc: u2 = 0b00,
7292 decoded17: u4 = 0b0000,
7293 decoded21: u1 = 0b1,
7294 ftype: Ftype,
7295 decoded24: u5 = 0b11110,
7296 S: bool = false,
7297 decoded30: u1 = 0b0,
7298 M: u1 = 0b0,
7299 };
7300
7301 /// C7.2.46 FABS (scalar)
7302 pub const Fabs = packed struct {
7303 Rd: Register.Encoded,
7304 Rn: Register.Encoded,
7305 decoded10: u5 = 0b10000,
7306 opc: u2 = 0b01,
7307 decoded17: u4 = 0b0000,
7308 decoded21: u1 = 0b1,
7309 ftype: Ftype,
7310 decoded24: u5 = 0b11110,
7311 S: bool = false,
7312 decoded30: u1 = 0b0,
7313 M: u1 = 0b0,
7314 };
7315
7316 /// C7.2.140 FNEG (scalar)
7317 pub const Fneg = packed struct {
7318 Rd: Register.Encoded,
7319 Rn: Register.Encoded,
7320 decoded10: u5 = 0b10000,
7321 opc: u2 = 0b10,
7322 decoded17: u4 = 0b0000,
7323 decoded21: u1 = 0b1,
7324 ftype: Ftype,
7325 decoded24: u5 = 0b11110,
7326 S: bool = false,
7327 decoded30: u1 = 0b0,
7328 M: u1 = 0b0,
7329 };
7330
7331 /// C7.2.172 FSQRT (scalar)
7332 pub const Fsqrt = packed struct {
7333 Rd: Register.Encoded,
7334 Rn: Register.Encoded,
7335 decoded10: u5 = 0b10000,
7336 opc: u2 = 0b11,
7337 decoded17: u4 = 0b0000,
7338 decoded21: u1 = 0b1,
7339 ftype: Ftype,
7340 decoded24: u5 = 0b11110,
7341 S: bool = false,
7342 decoded30: u1 = 0b0,
7343 M: u1 = 0b0,
7344 };
7345
7346 /// C7.2.69 FCVT
7347 pub const Fcvt = packed struct {
7348 Rd: Register.Encoded,
7349 Rn: Register.Encoded,
7350 decoded10: u5 = 0b10000,
7351 opc: Ftype,
7352 decoded17: u4 = 0b0001,
7353 decoded21: u1 = 0b1,
7354 ftype: Ftype,
7355 decoded24: u5 = 0b11110,
7356 S: bool = false,
7357 decoded30: u1 = 0b0,
7358 M: u1 = 0b0,
7359 };
7360
7361 /// C7.2.162 FRINTN (scalar)
7362 pub const Frintn = packed struct {
7363 Rd: Register.Encoded,
7364 Rn: Register.Encoded,
7365 decoded10: u5 = 0b10000,
7366 rmode: Rmode = .n,
7367 decoded18: u3 = 0b001,
7368 decoded21: u1 = 0b1,
7369 ftype: Ftype,
7370 decoded24: u5 = 0b11110,
7371 S: bool = false,
7372 decoded30: u1 = 0b0,
7373 M: u1 = 0b0,
7374 };
7375
7376 /// C7.2.164 FRINTP (scalar)
7377 pub const Frintp = packed struct {
7378 Rd: Register.Encoded,
7379 Rn: Register.Encoded,
7380 decoded10: u5 = 0b10000,
7381 rmode: Rmode = .p,
7382 decoded18: u3 = 0b001,
7383 decoded21: u1 = 0b1,
7384 ftype: Ftype,
7385 decoded24: u5 = 0b11110,
7386 S: bool = false,
7387 decoded30: u1 = 0b0,
7388 M: u1 = 0b0,
7389 };
7390
7391 /// C7.2.160 FRINTM (scalar)
7392 pub const Frintm = packed struct {
7393 Rd: Register.Encoded,
7394 Rn: Register.Encoded,
7395 decoded10: u5 = 0b10000,
7396 rmode: Rmode = .m,
7397 decoded18: u3 = 0b001,
7398 decoded21: u1 = 0b1,
7399 ftype: Ftype,
7400 decoded24: u5 = 0b11110,
7401 S: bool = false,
7402 decoded30: u1 = 0b0,
7403 M: u1 = 0b0,
7404 };
7405
7406 /// C7.2.168 FRINTZ (scalar)
7407 pub const Frintz = packed struct {
7408 Rd: Register.Encoded,
7409 Rn: Register.Encoded,
7410 decoded10: u5 = 0b10000,
7411 rmode: Rmode = .z,
7412 decoded18: u3 = 0b001,
7413 decoded21: u1 = 0b1,
7414 ftype: Ftype,
7415 decoded24: u5 = 0b11110,
7416 S: bool = false,
7417 decoded30: u1 = 0b0,
7418 M: u1 = 0b0,
7419 };
7420
7421 /// C7.2.156 FRINTA (scalar)
7422 pub const Frinta = packed struct {
7423 Rd: Register.Encoded,
7424 Rn: Register.Encoded,
7425 decoded10: u5 = 0b10000,
7426 rmode: Rmode = .a,
7427 decoded18: u3 = 0b001,
7428 decoded21: u1 = 0b1,
7429 ftype: Ftype,
7430 decoded24: u5 = 0b11110,
7431 S: bool = false,
7432 decoded30: u1 = 0b0,
7433 M: u1 = 0b0,
7434 };
7435
7436 /// C7.2.166 FRINTX (scalar)
7437 pub const Frintx = packed struct {
7438 Rd: Register.Encoded,
7439 Rn: Register.Encoded,
7440 decoded10: u5 = 0b10000,
7441 rmode: Rmode = .x,
7442 decoded18: u3 = 0b001,
7443 decoded21: u1 = 0b1,
7444 ftype: Ftype,
7445 decoded24: u5 = 0b11110,
7446 S: bool = false,
7447 decoded30: u1 = 0b0,
7448 M: u1 = 0b0,
7449 };
7450
7451 /// C7.2.158 FRINTI (scalar)
7452 pub const Frinti = packed struct {
7453 Rd: Register.Encoded,
7454 Rn: Register.Encoded,
7455 decoded10: u5 = 0b10000,
7456 rmode: Rmode = .i,
7457 decoded18: u3 = 0b001,
7458 decoded21: u1 = 0b1,
7459 ftype: Ftype,
7460 decoded24: u5 = 0b11110,
7461 S: bool = false,
7462 decoded30: u1 = 0b0,
7463 M: u1 = 0b0,
7464 };
7465
7466 pub const Rmode = enum(u3) {
7467 /// to nearest with ties to even
7468 n = 0b000,
7469 /// toward plus infinity
7470 p = 0b001,
7471 /// toward minus infinity
7472 m = 0b010,
7473 /// toward zero
7474 z = 0b011,
7475 /// to nearest with ties to away
7476 a = 0b100,
7477 /// exact, using current rounding mode
7478 x = 0b110,
7479 /// using current rounding mode
7480 i = 0b111,
7481 _,
7482 };
7483 };
7484
7485 /// Floating-point compare
7486 pub const FloatCompare = packed union {
7487 group: @This().Group,
7488 fcmp: Fcmp,
7489 fcmpe: Fcmpe,
7490
7491 pub const Group = packed struct {
7492 opcode2: u5,
7493 Rn: Register.Encoded,
7494 decoded10: u4 = 0b1000,
7495 op: u2,
7496 Rm: Register.Encoded,
7497 decoded21: u1 = 0b1,
7498 ptype: Ftype,
7499 decoded24: u5 = 0b11110,
7500 S: bool,
7501 decoded30: u1 = 0b0,
7502 M: u1,
7503 };
7504
7505 /// C7.2.66 FCMP
7506 pub const Fcmp = packed struct {
7507 decoded0: u3 = 0b000,
7508 opc0: Opc0,
7509 opc1: u1 = 0b0,
7510 Rn: Register.Encoded,
7511 decoded10: u4 = 0b1000,
7512 op: u2 = 0b00,
7513 Rm: Register.Encoded,
7514 decoded21: u1 = 0b1,
7515 ftype: Ftype,
7516 decoded24: u5 = 0b11110,
7517 S: bool = false,
7518 decoded30: u1 = 0b0,
7519 M: u1 = 0b0,
7520 };
7521
7522 /// C7.2.67 FCMPE
7523 pub const Fcmpe = packed struct {
7524 decoded0: u3 = 0b000,
7525 opc0: Opc0,
7526 opc1: u1 = 0b1,
7527 Rn: Register.Encoded,
7528 decoded10: u4 = 0b1000,
7529 op: u2 = 0b00,
7530 Rm: Register.Encoded,
7531 decoded21: u1 = 0b1,
7532 ftype: Ftype,
7533 decoded24: u5 = 0b11110,
7534 S: bool = false,
7535 decoded30: u1 = 0b0,
7536 M: u1 = 0b0,
7537 };
7538
7539 pub const Opc0 = enum(u1) {
7540 register = 0b00,
7541 zero = 0b01,
7542 };
7543 };
7544
7545 /// Floating-point immediate
7546 pub const FloatImmediate = packed union {
7547 group: @This().Group,
7548 fmov: Fmov,
7549
7550 pub const Group = packed struct {
7551 Rd: Register.Encoded,
7552 imm5: u5,
7553 decoded10: u3 = 0b100,
7554 imm8: u8,
7555 decoded21: u1 = 0b1,
7556 ptype: Ftype,
7557 decoded24: u5 = 0b11110,
7558 S: bool,
7559 decoded30: u1 = 0b0,
7560 M: u1,
7561 };
7562
7563 /// C7.2.132 FMOV (scalar, immediate)
7564 pub const Fmov = packed struct {
7565 Rd: Register.Encoded,
7566 imm5: u5 = 0b00000,
7567 decoded10: u3 = 0b100,
7568 imm8: u8,
7569 decoded21: u1 = 0b1,
7570 ftype: Ftype,
7571 decoded24: u5 = 0b11110,
7572 S: bool = false,
7573 decoded30: u1 = 0b0,
7574 M: u1 = 0b0,
7575 };
7576 };
7577
7578 /// Floating-point data-processing (2 source)
7579 pub const FloatDataProcessingTwoSource = packed union {
7580 group: @This().Group,
7581 fmul: Fmul,
7582 fdiv: Fdiv,
7583 fadd: Fadd,
7584 fsub: Fsub,
7585 fmax: Fmax,
7586 fmin: Fmin,
7587 fmaxnm: Fmaxnm,
7588 fminnm: Fminnm,
7589 fnmul: Fnmul,
7590
7591 pub const Group = packed struct {
7592 Rd: Register.Encoded,
7593 Rn: Register.Encoded,
7594 decoded10: u2 = 0b10,
7595 opcode: Opcode,
7596 Rm: Register.Encoded,
7597 decoded21: u1 = 0b1,
7598 ptype: Ftype,
7599 decoded24: u5 = 0b11110,
7600 S: bool,
7601 decoded30: u1 = 0b0,
7602 M: u1,
7603 };
7604
7605 /// C7.2.136 FMUL (scalar)
7606 pub const Fmul = packed struct {
7607 Rd: Register.Encoded,
7608 Rn: Register.Encoded,
7609 decoded10: u2 = 0b10,
7610 opcode: Opcode = .fmul,
7611 Rm: Register.Encoded,
7612 decoded21: u1 = 0b1,
7613 ftype: Ftype,
7614 decoded24: u5 = 0b11110,
7615 S: bool = false,
7616 decoded30: u1 = 0b0,
7617 M: u1 = 0b0,
7618 };
7619
7620 /// C7.2.98 FDIV (scalar)
7621 pub const Fdiv = packed struct {
7622 Rd: Register.Encoded,
7623 Rn: Register.Encoded,
7624 decoded10: u2 = 0b10,
7625 opcode: Opcode = .fdiv,
7626 Rm: Register.Encoded,
7627 decoded21: u1 = 0b1,
7628 ftype: Ftype,
7629 decoded24: u5 = 0b11110,
7630 S: bool = false,
7631 decoded30: u1 = 0b0,
7632 M: u1 = 0b0,
7633 };
7634
7635 /// C7.2.50 FADD (scalar)
7636 pub const Fadd = packed struct {
7637 Rd: Register.Encoded,
7638 Rn: Register.Encoded,
7639 decoded10: u2 = 0b10,
7640 opcode: Opcode = .fadd,
7641 Rm: Register.Encoded,
7642 decoded21: u1 = 0b1,
7643 ftype: Ftype,
7644 decoded24: u5 = 0b11110,
7645 S: bool = false,
7646 decoded30: u1 = 0b0,
7647 M: u1 = 0b0,
7648 };
7649
7650 /// C7.2.174 FSUB (scalar)
7651 pub const Fsub = packed struct {
7652 Rd: Register.Encoded,
7653 Rn: Register.Encoded,
7654 decoded10: u2 = 0b10,
7655 opcode: Opcode = .fsub,
7656 Rm: Register.Encoded,
7657 decoded21: u1 = 0b1,
7658 ftype: Ftype,
7659 decoded24: u5 = 0b11110,
7660 S: bool = false,
7661 decoded30: u1 = 0b0,
7662 M: u1 = 0b0,
7663 };
7664
7665 /// C7.2.102 FMAX (scalar)
7666 pub const Fmax = packed struct {
7667 Rd: Register.Encoded,
7668 Rn: Register.Encoded,
7669 decoded10: u2 = 0b10,
7670 opcode: Opcode = .fmax,
7671 Rm: Register.Encoded,
7672 decoded21: u1 = 0b1,
7673 ftype: Ftype,
7674 decoded24: u5 = 0b11110,
7675 S: bool = false,
7676 decoded30: u1 = 0b0,
7677 M: u1 = 0b0,
7678 };
7679
7680 /// C7.2.112 FMIN (scalar)
7681 pub const Fmin = packed struct {
7682 Rd: Register.Encoded,
7683 Rn: Register.Encoded,
7684 decoded10: u2 = 0b10,
7685 opcode: Opcode = .fmin,
7686 Rm: Register.Encoded,
7687 decoded21: u1 = 0b1,
7688 ftype: Ftype,
7689 decoded24: u5 = 0b11110,
7690 S: bool = false,
7691 decoded30: u1 = 0b0,
7692 M: u1 = 0b0,
7693 };
7694
7695 /// C7.2.104 FMAXNM (scalar)
7696 pub const Fmaxnm = packed struct {
7697 Rd: Register.Encoded,
7698 Rn: Register.Encoded,
7699 decoded10: u2 = 0b10,
7700 opcode: Opcode = .fmaxnm,
7701 Rm: Register.Encoded,
7702 decoded21: u1 = 0b1,
7703 ftype: Ftype,
7704 decoded24: u5 = 0b11110,
7705 S: bool = false,
7706 decoded30: u1 = 0b0,
7707 M: u1 = 0b0,
7708 };
7709
7710 /// C7.2.114 FMINNM (scalar)
7711 pub const Fminnm = packed struct {
7712 Rd: Register.Encoded,
7713 Rn: Register.Encoded,
7714 decoded10: u2 = 0b10,
7715 opcode: Opcode = .fminnm,
7716 Rm: Register.Encoded,
7717 decoded21: u1 = 0b1,
7718 ftype: Ftype,
7719 decoded24: u5 = 0b11110,
7720 S: bool = false,
7721 decoded30: u1 = 0b0,
7722 M: u1 = 0b0,
7723 };
7724
7725 /// C7.2.143 FNMUL (scalar)
7726 pub const Fnmul = packed struct {
7727 Rd: Register.Encoded,
7728 Rn: Register.Encoded,
7729 decoded10: u2 = 0b10,
7730 opcode: Opcode = .fnmul,
7731 Rm: Register.Encoded,
7732 decoded21: u1 = 0b1,
7733 ftype: Ftype,
7734 decoded24: u5 = 0b11110,
7735 S: bool = false,
7736 decoded30: u1 = 0b0,
7737 M: u1 = 0b0,
7738 };
7739
7740 pub const Opcode = enum(u4) {
7741 fmul = 0b0000,
7742 fdiv = 0b0001,
7743 fadd = 0b0010,
7744 fsub = 0b0011,
7745 fmax = 0b0100,
7746 fmin = 0b0101,
7747 fmaxnm = 0b0110,
7748 fminnm = 0b0111,
7749 fnmul = 0b1000,
7750 _,
7751 };
7752 };
7753
7754 /// Floating-point data-processing (3 source)
7755 pub const FloatDataProcessingThreeSource = packed union {
7756 group: @This().Group,
7757 fmadd: Fmadd,
7758 fmsub: Fmsub,
7759 fnmadd: Fnmadd,
7760 fnmsub: Fnmsub,
7761
7762 pub const Group = packed struct {
7763 Rd: Register.Encoded,
7764 Rn: Register.Encoded,
7765 Ra: Register.Encoded,
7766 o0: AddSubtractOp,
7767 Rm: Register.Encoded,
7768 o1: u1,
7769 ptype: Ftype,
7770 decoded24: u5 = 0b11111,
7771 S: bool,
7772 decoded30: u1 = 0b0,
7773 M: u1,
7774 };
7775
7776 /// C7.2.100 FMADD
7777 pub const Fmadd = packed struct {
7778 Rd: Register.Encoded,
7779 Rn: Register.Encoded,
7780 Ra: Register.Encoded,
7781 o0: AddSubtractOp = .add,
7782 Rm: Register.Encoded,
7783 o1: O1 = .fm,
7784 ftype: Ftype,
7785 decoded24: u5 = 0b11111,
7786 S: bool = false,
7787 decoded30: u1 = 0b0,
7788 M: u1 = 0b0,
7789 };
7790
7791 /// C7.2.133 FMSUB
7792 pub const Fmsub = packed struct {
7793 Rd: Register.Encoded,
7794 Rn: Register.Encoded,
7795 Ra: Register.Encoded,
7796 o0: AddSubtractOp = .sub,
7797 Rm: Register.Encoded,
7798 o1: O1 = .fm,
7799 ftype: Ftype,
7800 decoded24: u5 = 0b11111,
7801 S: bool = false,
7802 decoded30: u1 = 0b0,
7803 M: u1 = 0b0,
7804 };
7805
7806 /// C7.2.141 FNMADD
7807 pub const Fnmadd = packed struct {
7808 Rd: Register.Encoded,
7809 Rn: Register.Encoded,
7810 Ra: Register.Encoded,
7811 o0: AddSubtractOp = .add,
7812 Rm: Register.Encoded,
7813 o1: O1 = .fnm,
7814 ftype: Ftype,
7815 decoded24: u5 = 0b11111,
7816 S: bool = false,
7817 decoded30: u1 = 0b0,
7818 M: u1 = 0b0,
7819 };
7820
7821 /// C7.2.142 FNMSUB
7822 pub const Fnmsub = packed struct {
7823 Rd: Register.Encoded,
7824 Rn: Register.Encoded,
7825 Ra: Register.Encoded,
7826 o0: AddSubtractOp = .sub,
7827 Rm: Register.Encoded,
7828 o1: O1 = .fnm,
7829 ftype: Ftype,
7830 decoded24: u5 = 0b11111,
7831 S: bool = false,
7832 decoded30: u1 = 0b0,
7833 M: u1 = 0b0,
7834 };
7835
7836 pub const O1 = enum(u1) {
7837 fm = 0b0,
7838 fnm = 0b1,
7839 };
7840 };
7841
7842 pub const Q = enum(u1) {
7843 double = 0b0,
7844 quad = 0b1,
7845 };
7846
7847 pub const Size = enum(u2) {
7848 byte = 0b00,
7849 half = 0b01,
7850 single = 0b10,
7851 double = 0b11,
7852
7853 pub fn toVectorSize(s: Size) Register.VectorSize {
7854 return switch (s) {
7855 .byte => .byte,
7856 .half => .half,
7857 .single => .single,
7858 .double => .double,
7859 };
7860 }
7861
7862 pub fn fromVectorSize(vs: Register.VectorSize) Size {
7863 return switch (vs) {
7864 .byte => .byte,
7865 .half => .half,
7866 .single => .single,
7867 .double => .double,
7868 };
7869 }
7870 };
7871
7872 pub const Ftype = enum(u2) {
7873 single = 0b00,
7874 double = 0b01,
7875 quad = 0b10,
7876 half = 0b11,
7877 };
7878 };
7879
7880 pub const AddSubtractOp = enum(u1) {
7881 add = 0b0,
7882 sub = 0b1,
7883 };
7884
7885 pub const LogicalOpc = enum(u2) {
7886 @"and" = 0b00,
7887 orr = 0b01,
7888 eor = 0b10,
7889 ands = 0b11,
7890 };
7891
7892 pub const Decoded = union(enum) {
7893 unallocated,
7894 reserved: Reserved,
7895 sme: Sme,
7896 sve: Sve,
7897 data_processing_immediate: DataProcessingImmediate,
7898 branch_exception_generating_system: BranchExceptionGeneratingSystem,
7899 load_store: LoadStore,
7900 data_processing_register: DataProcessingRegister,
7901 data_processing_vector: DataProcessingVector,
7902 };
7903 pub fn decode(inst: @This()) @This().Decoded {
7904 return switch (inst.group.op1) {
7905 0b0000 => switch (inst.group.op0) {
7906 0b0 => .{ .reserved = inst.reserved },
7907 0b1 => .{ .sme = inst.sme },
7908 },
7909 0b0001 => .unallocated,
7910 0b0010 => .{ .sve = inst.sve },
7911 0b0011 => .unallocated,
7912 0b1000, 0b1001 => .{ .data_processing_immediate = inst.data_processing_immediate },
7913 0b1010, 0b1011 => .{ .branch_exception_generating_system = inst.branch_exception_generating_system },
7914 0b0100, 0b0110, 0b1100, 0b1110 => .{ .load_store = inst.load_store },
7915 0b0101, 0b1101 => .{ .data_processing_register = inst.data_processing_register },
7916 0b0111, 0b1111 => .{ .data_processing_vector = inst.data_processing_vector },
7917 };
7918 }
7919
7920 /// C6.2.1 ADC
7921 pub fn adc(d: Register, n: Register, m: Register) Instruction {
7922 const sf = d.format.integer;
7923 assert(n.format.integer == sf and m.format.integer == sf);
7924 return .{ .data_processing_register = .{ .add_subtract_with_carry = .{
7925 .adc = .{
7926 .Rd = d.alias.encode(.{}),
7927 .Rn = n.alias.encode(.{}),
7928 .Rm = m.alias.encode(.{}),
7929 .sf = sf,
7930 },
7931 } } };
7932 }
7933 /// C6.2.2 ADCS
7934 pub fn adcs(d: Register, n: Register, m: Register) Instruction {
7935 const sf = d.format.integer;
7936 assert(n.format.integer == sf and m.format.integer == sf);
7937 return .{ .data_processing_register = .{ .add_subtract_with_carry = .{
7938 .adcs = .{
7939 .Rd = d.alias.encode(.{}),
7940 .Rn = n.alias.encode(.{}),
7941 .Rm = m.alias.encode(.{}),
7942 .sf = sf,
7943 },
7944 } } };
7945 }
7946 /// C6.2.3 ADD (extended register)
7947 /// C6.2.4 ADD (immediate)
7948 /// C6.2.5 ADD (shifted register)
7949 pub fn add(d: Register, n: Register, form: union(enum) {
7950 extended_register_explicit: struct {
7951 register: Register,
7952 option: DataProcessingRegister.AddSubtractExtendedRegister.Option,
7953 amount: DataProcessingRegister.AddSubtractExtendedRegister.Extend.Amount,
7954 },
7955 extended_register: struct { register: Register, extend: DataProcessingRegister.AddSubtractExtendedRegister.Extend },
7956 immediate: u12,
7957 shifted_immediate: struct { immediate: u12, lsl: DataProcessingImmediate.AddSubtractImmediate.Shift = .@"0" },
7958 register: Register,
7959 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
7960 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
7961 }) Instruction {
7962 const sf = d.format.integer;
7963 assert(n.format.integer == sf);
7964 form: switch (form) {
7965 .extended_register_explicit => |extended_register_explicit| {
7966 assert(extended_register_explicit.register.format.integer == extended_register_explicit.option.sf());
7967 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
7968 .add = .{
7969 .Rd = d.alias.encode(.{ .sp = true }),
7970 .Rn = n.alias.encode(.{ .sp = true }),
7971 .imm3 = switch (extended_register_explicit.amount) {
7972 0...4 => |amount| amount,
7973 else => unreachable,
7974 },
7975 .option = extended_register_explicit.option,
7976 .Rm = extended_register_explicit.register.alias.encode(.{}),
7977 .sf = sf,
7978 },
7979 } } };
7980 },
7981 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
7982 .register = extended_register.register,
7983 .option = extended_register.extend,
7984 .amount = switch (extended_register.extend) {
7985 .uxtb, .uxth, .uxtw, .uxtx, .sxtb, .sxth, .sxtw, .sxtx => |amount| amount,
7986 },
7987 } },
7988 .immediate => |immediate| continue :form .{ .shifted_immediate = .{ .immediate = immediate } },
7989 .shifted_immediate => |shifted_immediate| {
7990 return .{ .data_processing_immediate = .{ .add_subtract_immediate = .{
7991 .add = .{
7992 .Rd = d.alias.encode(.{ .sp = true }),
7993 .Rn = n.alias.encode(.{ .sp = true }),
7994 .imm12 = shifted_immediate.immediate,
7995 .sh = shifted_immediate.lsl,
7996 .sf = sf,
7997 },
7998 } } };
7999 },
8000 .register => |register| continue :form if (d.alias == .sp or n.alias == .sp or register.alias == .sp)
8001 .{ .extended_register = .{ .register = register, .extend = switch (sf) {
8002 .word => .{ .uxtw = 0 },
8003 .doubleword => .{ .uxtx = 0 },
8004 } } }
8005 else
8006 .{ .shifted_register = .{ .register = register } },
8007 .shifted_register_explicit => |shifted_register_explicit| {
8008 assert(shifted_register_explicit.register.format.integer == sf);
8009 return .{ .data_processing_register = .{ .add_subtract_shifted_register = .{
8010 .add = .{
8011 .Rd = d.alias.encode(.{}),
8012 .Rn = n.alias.encode(.{}),
8013 .imm6 = switch (sf) {
8014 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
8015 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
8016 },
8017 .Rm = shifted_register_explicit.register.alias.encode(.{}),
8018 .shift = switch (shifted_register_explicit.shift) {
8019 .lsl, .lsr, .asr => |shift| shift,
8020 .ror => unreachable,
8021 },
8022 .sf = sf,
8023 },
8024 } } };
8025 },
8026 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
8027 .register = shifted_register.register,
8028 .shift = shifted_register.shift,
8029 .amount = switch (shifted_register.shift) {
8030 .lsl, .lsr, .asr => |amount| amount,
8031 .ror => unreachable,
8032 },
8033 } },
8034 }
8035 }
8036 /// C7.2.4 ADDP (scalar)
8037 /// C7.2.5 ADDP (vector)
8038 pub fn addp(d: Register, n: Register, form: union(enum) {
8039 scalar,
8040 vector: Register,
8041 }) Instruction {
8042 switch (form) {
8043 .scalar => {
8044 assert(d.format.scalar == .double and n.format.vector == .@"2d");
8045 return .{ .data_processing_vector = .{ .simd_scalar_pairwise = .{
8046 .addp = .{
8047 .Rd = d.alias.encode(.{ .V = true }),
8048 .Rn = n.alias.encode(.{ .V = true }),
8049 .size = .double,
8050 },
8051 } } };
8052 },
8053 .vector => |m| {
8054 const arrangement = d.format.vector;
8055 assert(arrangement != .@"1d" and n.format.vector == arrangement and m.format.vector == arrangement);
8056 return .{ .data_processing_vector = .{ .simd_three_same = .{
8057 .addp = .{
8058 .Rd = d.alias.encode(.{ .V = true }),
8059 .Rn = n.alias.encode(.{ .V = true }),
8060 .Rm = m.alias.encode(.{ .V = true }),
8061 .size = arrangement.elemSize(),
8062 .Q = arrangement.size(),
8063 },
8064 } } };
8065 },
8066 }
8067 }
8068 /// C6.2.7 ADDS (extended register)
8069 /// C6.2.8 ADDS (immediate)
8070 /// C6.2.9 ADDS (shifted register)
8071 pub fn adds(d: Register, n: Register, form: union(enum) {
8072 extended_register_explicit: struct {
8073 register: Register,
8074 option: DataProcessingRegister.AddSubtractExtendedRegister.Option,
8075 amount: DataProcessingRegister.AddSubtractExtendedRegister.Extend.Amount,
8076 },
8077 extended_register: struct { register: Register, extend: DataProcessingRegister.AddSubtractExtendedRegister.Extend },
8078 immediate: u12,
8079 shifted_immediate: struct { immediate: u12, lsl: DataProcessingImmediate.AddSubtractImmediate.Shift = .@"0" },
8080 register: Register,
8081 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
8082 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
8083 }) Instruction {
8084 const sf = d.format.integer;
8085 assert(n.format.integer == sf);
8086 form: switch (form) {
8087 .extended_register_explicit => |extended_register_explicit| {
8088 assert(extended_register_explicit.register.format.integer == extended_register_explicit.option.sf());
8089 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
8090 .adds = .{
8091 .Rd = d.alias.encode(.{}),
8092 .Rn = n.alias.encode(.{ .sp = true }),
8093 .imm3 = switch (extended_register_explicit.amount) {
8094 0...4 => |amount| amount,
8095 else => unreachable,
8096 },
8097 .option = extended_register_explicit.option,
8098 .Rm = extended_register_explicit.register.alias.encode(.{}),
8099 .sf = sf,
8100 },
8101 } } };
8102 },
8103 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
8104 .register = extended_register.register,
8105 .option = extended_register.extend,
8106 .amount = switch (extended_register.extend) {
8107 .uxtb, .uxth, .uxtw, .uxtx, .sxtb, .sxth, .sxtw, .sxtx => |amount| amount,
8108 },
8109 } },
8110 .immediate => |immediate| continue :form .{ .shifted_immediate = .{ .immediate = immediate } },
8111 .shifted_immediate => |shifted_immediate| {
8112 return .{ .data_processing_immediate = .{ .add_subtract_immediate = .{
8113 .adds = .{
8114 .Rd = d.alias.encode(.{}),
8115 .Rn = n.alias.encode(.{ .sp = true }),
8116 .imm12 = shifted_immediate.immediate,
8117 .sh = shifted_immediate.lsl,
8118 .sf = sf,
8119 },
8120 } } };
8121 },
8122 .register => |register| continue :form if (d.alias == .sp or n.alias == .sp or register.alias == .sp)
8123 .{ .extended_register = .{ .register = register, .extend = switch (sf) {
8124 .word => .{ .uxtw = 0 },
8125 .doubleword => .{ .uxtx = 0 },
8126 } } }
8127 else
8128 .{ .shifted_register = .{ .register = register } },
8129 .shifted_register_explicit => |shifted_register_explicit| {
8130 assert(shifted_register_explicit.register.format.integer == sf);
8131 return .{ .data_processing_register = .{ .add_subtract_shifted_register = .{
8132 .adds = .{
8133 .Rd = d.alias.encode(.{}),
8134 .Rn = n.alias.encode(.{}),
8135 .imm6 = switch (sf) {
8136 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
8137 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
8138 },
8139 .Rm = shifted_register_explicit.register.alias.encode(.{}),
8140 .shift = switch (shifted_register_explicit.shift) {
8141 .lsl, .lsr, .asr => |shift| shift,
8142 .ror => unreachable,
8143 },
8144 .sf = sf,
8145 },
8146 } } };
8147 },
8148 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
8149 .register = shifted_register.register,
8150 .shift = shifted_register.shift,
8151 .amount = switch (shifted_register.shift) {
8152 .lsl, .lsr, .asr => |amount| amount,
8153 .ror => unreachable,
8154 },
8155 } },
8156 }
8157 }
8158 /// C7.2.6 ADDV
8159 pub fn addv(d: Register, n: Register) Instruction {
8160 const arrangement = n.format.vector;
8161 assert(arrangement.len() > 2 and d.format.scalar == arrangement.elemSize().toVectorSize());
8162 return .{ .data_processing_vector = .{ .simd_across_lanes = .{
8163 .addv = .{
8164 .Rd = d.alias.encode(.{ .V = true }),
8165 .Rn = n.alias.encode(.{ .V = true }),
8166 .size = arrangement.elemSize(),
8167 .Q = arrangement.size(),
8168 },
8169 } } };
8170 }
8171 /// C6.2.10 ADR
8172 pub fn adr(d: Register, label: i21) Instruction {
8173 assert(d.format.integer == .doubleword);
8174 return .{ .data_processing_immediate = .{ .pc_relative_addressing = .{
8175 .adr = .{
8176 .Rd = d.alias.encode(.{}),
8177 .immhi = @intCast(label >> 2),
8178 .immlo = @truncate(@as(u21, @bitCast(label))),
8179 },
8180 } } };
8181 }
8182 /// C6.2.11 ADRP
8183 pub fn adrp(d: Register, label: i33) Instruction {
8184 assert(d.format.integer == .doubleword);
8185 const imm: i21 = @intCast(@shrExact(label, 12));
8186 return .{ .data_processing_immediate = .{ .pc_relative_addressing = .{
8187 .adrp = .{
8188 .Rd = d.alias.encode(.{}),
8189 .immhi = @intCast(imm >> 2),
8190 .immlo = @truncate(@as(u21, @bitCast(imm))),
8191 },
8192 } } };
8193 }
8194 /// C6.2.12 AND (immediate)
8195 /// C6.2.13 AND (shifted register)
8196 /// C7.2.11 AND (vector)
8197 pub fn @"and"(d: Register, n: Register, form: union(enum) {
8198 immediate: DataProcessingImmediate.Bitmask,
8199 register: Register,
8200 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
8201 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
8202 }) Instruction {
8203 switch (d.format) {
8204 else => unreachable,
8205 .integer => |sf| {
8206 assert(n.format.integer == sf);
8207 form: switch (form) {
8208 .immediate => |bitmask| {
8209 assert(bitmask.validImmediate(sf));
8210 return .{ .data_processing_immediate = .{ .logical_immediate = .{
8211 .@"and" = .{
8212 .Rd = d.alias.encode(.{ .sp = true }),
8213 .Rn = n.alias.encode(.{}),
8214 .imm = bitmask,
8215 .sf = sf,
8216 },
8217 } } };
8218 },
8219 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
8220 .shifted_register_explicit => |shifted_register_explicit| {
8221 assert(shifted_register_explicit.register.format.integer == sf);
8222 return .{ .data_processing_register = .{ .logical_shifted_register = .{
8223 .@"and" = .{
8224 .Rd = d.alias.encode(.{}),
8225 .Rn = n.alias.encode(.{}),
8226 .imm6 = switch (sf) {
8227 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
8228 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
8229 },
8230 .Rm = shifted_register_explicit.register.alias.encode(.{}),
8231 .shift = shifted_register_explicit.shift,
8232 .sf = sf,
8233 },
8234 } } };
8235 },
8236 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
8237 .register = shifted_register.register,
8238 .shift = shifted_register.shift,
8239 .amount = switch (shifted_register.shift) {
8240 .lsl, .lsr, .asr, .ror => |amount| amount,
8241 },
8242 } },
8243 }
8244 },
8245 .vector => |arrangement| {
8246 const m = form.register;
8247 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
8248 return .{ .data_processing_vector = .{ .simd_three_same = .{
8249 .@"and" = .{
8250 .Rd = d.alias.encode(.{ .V = true }),
8251 .Rn = n.alias.encode(.{ .V = true }),
8252 .Rm = m.alias.encode(.{ .V = true }),
8253 .Q = arrangement.size(),
8254 },
8255 } } };
8256 },
8257 }
8258 }
8259 /// C6.2.14 ANDS (immediate)
8260 /// C6.2.15 ANDS (shifted register)
8261 pub fn ands(d: Register, n: Register, form: union(enum) {
8262 immediate: DataProcessingImmediate.Bitmask,
8263 register: Register,
8264 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
8265 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
8266 }) Instruction {
8267 const sf = d.format.integer;
8268 assert(n.format.integer == sf);
8269 form: switch (form) {
8270 .immediate => |bitmask| {
8271 assert(bitmask.validImmediate(sf));
8272 return .{ .data_processing_immediate = .{ .logical_immediate = .{
8273 .ands = .{
8274 .Rd = d.alias.encode(.{}),
8275 .Rn = n.alias.encode(.{}),
8276 .imm = bitmask,
8277 .sf = sf,
8278 },
8279 } } };
8280 },
8281 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
8282 .shifted_register_explicit => |shifted_register_explicit| {
8283 assert(shifted_register_explicit.register.format.integer == sf);
8284 return .{ .data_processing_register = .{ .logical_shifted_register = .{
8285 .ands = .{
8286 .Rd = d.alias.encode(.{}),
8287 .Rn = n.alias.encode(.{}),
8288 .imm6 = switch (sf) {
8289 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
8290 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
8291 },
8292 .Rm = shifted_register_explicit.register.alias.encode(.{}),
8293 .shift = shifted_register_explicit.shift,
8294 .sf = sf,
8295 },
8296 } } };
8297 },
8298 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
8299 .register = shifted_register.register,
8300 .shift = shifted_register.shift,
8301 .amount = switch (shifted_register.shift) {
8302 .lsl, .lsr, .asr, .ror => |amount| amount,
8303 },
8304 } },
8305 }
8306 }
8307 /// C6.2.18 ASRV
8308 pub fn asrv(d: Register, n: Register, m: Register) Instruction {
8309 const sf = d.format.integer;
8310 assert(n.format.integer == sf and m.format.integer == sf);
8311 return .{ .data_processing_register = .{ .data_processing_two_source = .{
8312 .asrv = .{
8313 .Rd = d.alias.encode(.{}),
8314 .Rn = n.alias.encode(.{}),
8315 .Rm = m.alias.encode(.{}),
8316 .sf = sf,
8317 },
8318 } } };
8319 }
8320 /// C6.2.25 B
8321 pub fn b(label: i28) Instruction {
8322 return .{ .branch_exception_generating_system = .{ .unconditional_branch_immediate = .{
8323 .b = .{ .imm26 = @intCast(@shrExact(label, 2)) },
8324 } } };
8325 }
8326 /// C6.2.26 B.cond
8327 pub fn @"b."(cond: ConditionCode, label: i21) Instruction {
8328 return .{ .branch_exception_generating_system = .{ .conditional_branch_immediate = .{
8329 .b = .{
8330 .cond = cond,
8331 .imm19 = @intCast(@shrExact(label, 2)),
8332 },
8333 } } };
8334 }
8335 /// C6.2.27 BC.cond
8336 pub fn @"bc."(cond: ConditionCode, label: i21) Instruction {
8337 return .{ .branch_exception_generating_system = .{ .conditional_branch_immediate = .{
8338 .bc = .{
8339 .cond = cond,
8340 .imm19 = @intCast(@shrExact(label, 2)),
8341 },
8342 } } };
8343 }
8344 /// C6.2.30 BFM
8345 pub fn bfm(d: Register, n: Register, bitmask: DataProcessingImmediate.Bitmask) Instruction {
8346 const sf = d.format.integer;
8347 assert(n.format.integer == sf and bitmask.validBitfield(sf));
8348 return .{ .data_processing_immediate = .{ .bitfield = .{
8349 .bfm = .{
8350 .Rd = d.alias.encode(.{}),
8351 .Rn = n.alias.encode(.{}),
8352 .imm = bitmask,
8353 .sf = sf,
8354 },
8355 } } };
8356 }
8357 /// C6.2.32 BIC (shifted register)
8358 /// C7.2.20 BIC (vector, immediate)
8359 /// C7.2.21 BIC (vector, register)
8360 pub fn bic(d: Register, n: Register, form: union(enum) {
8361 shifted_immediate: struct { immediate: u8, lsl: u5 = 0 },
8362 register: Register,
8363 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
8364 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
8365 }) Instruction {
8366 switch (d.format) {
8367 else => unreachable,
8368 .integer => |sf| {
8369 assert(n.format.integer == sf);
8370 form: switch (form) {
8371 else => unreachable,
8372 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
8373 .shifted_register_explicit => |shifted_register_explicit| {
8374 assert(shifted_register_explicit.register.format.integer == sf);
8375 return .{ .data_processing_register = .{ .logical_shifted_register = .{
8376 .bic = .{
8377 .Rd = d.alias.encode(.{}),
8378 .Rn = n.alias.encode(.{}),
8379 .imm6 = switch (sf) {
8380 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
8381 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
8382 },
8383 .Rm = shifted_register_explicit.register.alias.encode(.{}),
8384 .shift = shifted_register_explicit.shift,
8385 .sf = sf,
8386 },
8387 } } };
8388 },
8389 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
8390 .register = shifted_register.register,
8391 .shift = shifted_register.shift,
8392 .amount = switch (shifted_register.shift) {
8393 .lsl, .lsr, .asr, .ror => |amount| amount,
8394 },
8395 } },
8396 }
8397 },
8398 .vector => |arrangement| switch (form) {
8399 else => unreachable,
8400 .shifted_immediate => |shifted_immediate| {
8401 assert(n.alias == d.alias and n.format.vector == arrangement);
8402 return .{ .data_processing_vector = .{ .simd_modified_immediate = .{
8403 .bic = .{
8404 .Rd = d.alias.encode(.{ .V = true }),
8405 .imm5 = @truncate(shifted_immediate.immediate >> 0),
8406 .cmode = switch (arrangement) {
8407 else => unreachable,
8408 .@"4h", .@"8h" => @as(u3, 0b100) |
8409 @as(u3, @as(u1, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0,
8410 .@"2s", .@"4s" => @as(u3, 0b000) |
8411 @as(u3, @as(u2, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0,
8412 },
8413 .imm3 = @intCast(shifted_immediate.immediate >> 5),
8414 .Q = arrangement.size(),
8415 },
8416 } } };
8417 },
8418 .register => |m| {
8419 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
8420 return .{ .data_processing_vector = .{ .simd_three_same = .{
8421 .bic = .{
8422 .Rd = d.alias.encode(.{ .V = true }),
8423 .Rn = n.alias.encode(.{ .V = true }),
8424 .Rm = m.alias.encode(.{ .V = true }),
8425 .Q = arrangement.size(),
8426 },
8427 } } };
8428 },
8429 },
8430 }
8431 }
8432 /// C6.2.33 BICS (shifted register)
8433 pub fn bics(d: Register, n: Register, form: union(enum) {
8434 register: Register,
8435 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
8436 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
8437 }) Instruction {
8438 const sf = d.format.integer;
8439 assert(n.format.integer == sf);
8440 form: switch (form) {
8441 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
8442 .shifted_register_explicit => |shifted_register_explicit| {
8443 assert(shifted_register_explicit.register.format.integer == sf);
8444 return .{ .data_processing_register = .{ .logical_shifted_register = .{
8445 .bics = .{
8446 .Rd = d.alias.encode(.{}),
8447 .Rn = n.alias.encode(.{}),
8448 .imm6 = switch (sf) {
8449 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
8450 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
8451 },
8452 .Rm = shifted_register_explicit.register.alias.encode(.{}),
8453 .shift = shifted_register_explicit.shift,
8454 .sf = sf,
8455 },
8456 } } };
8457 },
8458 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
8459 .register = shifted_register.register,
8460 .shift = shifted_register.shift,
8461 .amount = switch (shifted_register.shift) {
8462 .lsl, .lsr, .asr, .ror => |amount| amount,
8463 },
8464 } },
8465 }
8466 }
8467 /// C6.2.34 BL
8468 pub fn bl(label: i28) Instruction {
8469 return .{ .branch_exception_generating_system = .{ .unconditional_branch_immediate = .{
8470 .bl = .{ .imm26 = @intCast(@shrExact(label, 2)) },
8471 } } };
8472 }
8473 /// C6.2.35 BLR
8474 pub fn blr(n: Register) Instruction {
8475 assert(n.format.integer == .doubleword);
8476 return .{ .branch_exception_generating_system = .{ .unconditional_branch_register = .{
8477 .blr = .{ .Rn = n.alias.encode(.{}) },
8478 } } };
8479 }
8480 /// C6.2.37 BR
8481 pub fn br(n: Register) Instruction {
8482 assert(n.format.integer == .doubleword);
8483 return .{ .branch_exception_generating_system = .{ .unconditional_branch_register = .{
8484 .br = .{ .Rn = n.alias.encode(.{}) },
8485 } } };
8486 }
8487 /// C6.2.40 BRK
8488 pub fn brk(imm: u16) Instruction {
8489 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
8490 .brk = .{ .imm16 = imm },
8491 } } };
8492 }
8493 /// C6.2.46 CBNZ
8494 pub fn cbnz(t: Register, label: i21) Instruction {
8495 return .{ .branch_exception_generating_system = .{ .compare_branch_immediate = .{
8496 .cbnz = .{
8497 .Rt = t.alias.encode(.{}),
8498 .imm19 = @intCast(@shrExact(label, 2)),
8499 .sf = t.format.integer,
8500 },
8501 } } };
8502 }
8503 /// C6.2.47 CBZ
8504 pub fn cbz(t: Register, label: i21) Instruction {
8505 return .{ .branch_exception_generating_system = .{ .compare_branch_immediate = .{
8506 .cbz = .{
8507 .Rt = t.alias.encode(.{}),
8508 .imm19 = @intCast(@shrExact(label, 2)),
8509 .sf = t.format.integer,
8510 },
8511 } } };
8512 }
8513 /// C6.2.48 CCMN (immediate)
8514 /// C6.2.49 CCMN (register)
8515 pub fn ccmn(
8516 n: Register,
8517 form: union(enum) { register: Register, immediate: u5 },
8518 nzcv: DataProcessingRegister.Nzcv,
8519 cond: ConditionCode,
8520 ) Instruction {
8521 const sf = n.format.integer;
8522 switch (form) {
8523 .register => |m| {
8524 assert(m.format.integer == sf);
8525 return .{ .data_processing_register = .{ .conditional_compare_register = .{
8526 .ccmn = .{
8527 .nzcv = nzcv,
8528 .Rn = n.alias.encode(.{}),
8529 .cond = cond,
8530 .Rm = m.alias.encode(.{}),
8531 .sf = sf,
8532 },
8533 } } };
8534 },
8535 .immediate => |imm| return .{ .data_processing_register = .{ .conditional_compare_immediate = .{
8536 .ccmn = .{
8537 .nzcv = nzcv,
8538 .Rn = n.alias.encode(.{}),
8539 .cond = cond,
8540 .imm5 = imm,
8541 .sf = sf,
8542 },
8543 } } },
8544 }
8545 }
8546 /// C6.2.50 CCMP (immediate)
8547 /// C6.2.51 CCMP (register)
8548 pub fn ccmp(
8549 n: Register,
8550 form: union(enum) { register: Register, immediate: u5 },
8551 nzcv: DataProcessingRegister.Nzcv,
8552 cond: ConditionCode,
8553 ) Instruction {
8554 const sf = n.format.integer;
8555 switch (form) {
8556 .register => |m| {
8557 assert(m.format.integer == sf);
8558 return .{ .data_processing_register = .{ .conditional_compare_register = .{
8559 .ccmp = .{
8560 .nzcv = nzcv,
8561 .Rn = n.alias.encode(.{}),
8562 .cond = cond,
8563 .Rm = m.alias.encode(.{}),
8564 .sf = sf,
8565 },
8566 } } };
8567 },
8568 .immediate => |imm| return .{ .data_processing_register = .{ .conditional_compare_immediate = .{
8569 .ccmp = .{
8570 .nzcv = nzcv,
8571 .Rn = n.alias.encode(.{}),
8572 .cond = cond,
8573 .imm5 = imm,
8574 .sf = sf,
8575 },
8576 } } },
8577 }
8578 }
8579 /// C6.2.56 CLREX
8580 pub fn clrex(imm: u4) Instruction {
8581 return .{ .branch_exception_generating_system = .{ .barriers = .{
8582 .clrex = .{
8583 .CRm = imm,
8584 },
8585 } } };
8586 }
8587 /// C6.2.58 CLZ
8588 pub fn clz(d: Register, n: Register) Instruction {
8589 const sf = d.format.integer;
8590 assert(n.format.integer == sf);
8591 return .{ .data_processing_register = .{ .data_processing_one_source = .{
8592 .clz = .{
8593 .Rd = d.alias.encode(.{}),
8594 .Rn = n.alias.encode(.{}),
8595 .sf = sf,
8596 },
8597 } } };
8598 }
8599 /// C7.2.38 CNT
8600 pub fn cnt(d: Register, n: Register) Instruction {
8601 const arrangement = d.format.vector;
8602 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement);
8603 return .{ .data_processing_vector = .{ .simd_two_register_miscellaneous = .{
8604 .cnt = .{
8605 .Rd = d.alias.encode(.{ .V = true }),
8606 .Rn = n.alias.encode(.{ .V = true }),
8607 .size = arrangement.elemSize(),
8608 .Q = arrangement.size(),
8609 },
8610 } } };
8611 }
8612 /// C6.2.103 CSEL
8613 pub fn csel(d: Register, n: Register, m: Register, cond: ConditionCode) Instruction {
8614 const sf = d.format.integer;
8615 assert(n.format.integer == sf and m.format.integer == sf);
8616 return .{ .data_processing_register = .{ .conditional_select = .{
8617 .csel = .{
8618 .Rd = d.alias.encode(.{}),
8619 .Rn = n.alias.encode(.{}),
8620 .cond = cond,
8621 .Rm = m.alias.encode(.{}),
8622 .sf = sf,
8623 },
8624 } } };
8625 }
8626 /// C6.2.106 CSINC
8627 pub fn csinc(d: Register, n: Register, m: Register, cond: ConditionCode) Instruction {
8628 const sf = d.format.integer;
8629 assert(n.format.integer == sf and m.format.integer == sf);
8630 return .{ .data_processing_register = .{ .conditional_select = .{
8631 .csinc = .{
8632 .Rd = d.alias.encode(.{}),
8633 .Rn = n.alias.encode(.{}),
8634 .cond = cond,
8635 .Rm = m.alias.encode(.{}),
8636 .sf = sf,
8637 },
8638 } } };
8639 }
8640 /// C6.2.107 CSINV
8641 pub fn csinv(d: Register, n: Register, m: Register, cond: ConditionCode) Instruction {
8642 const sf = d.format.integer;
8643 assert(n.format.integer == sf and m.format.integer == sf);
8644 return .{ .data_processing_register = .{ .conditional_select = .{
8645 .csinv = .{
8646 .Rd = d.alias.encode(.{}),
8647 .Rn = n.alias.encode(.{}),
8648 .cond = cond,
8649 .Rm = m.alias.encode(.{}),
8650 .sf = sf,
8651 },
8652 } } };
8653 }
8654 /// C6.2.108 CSNEG
8655 pub fn csneg(d: Register, n: Register, m: Register, cond: ConditionCode) Instruction {
8656 const sf = d.format.integer;
8657 assert(n.format.integer == sf and m.format.integer == sf);
8658 return .{ .data_processing_register = .{ .conditional_select = .{
8659 .csneg = .{
8660 .Rd = d.alias.encode(.{}),
8661 .Rn = n.alias.encode(.{}),
8662 .cond = cond,
8663 .Rm = m.alias.encode(.{}),
8664 .sf = sf,
8665 },
8666 } } };
8667 }
8668 /// C6.2.110 DCPS1
8669 pub fn dcps1(imm: u16) Instruction {
8670 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
8671 .dcps1 = .{ .imm16 = imm },
8672 } } };
8673 }
8674 /// C6.2.111 DCPS2
8675 pub fn dcps2(imm: u16) Instruction {
8676 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
8677 .dcps2 = .{ .imm16 = imm },
8678 } } };
8679 }
8680 /// C6.2.112 DCPS3
8681 pub fn dcps3(imm: u16) Instruction {
8682 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
8683 .dcps3 = .{ .imm16 = imm },
8684 } } };
8685 }
8686 /// C6.2.116 DSB
8687 pub fn dsb(option: BranchExceptionGeneratingSystem.Barriers.Option) Instruction {
8688 return .{ .branch_exception_generating_system = .{ .barriers = .{
8689 .dsb = .{
8690 .CRm = option,
8691 },
8692 } } };
8693 }
8694 /// C6.2.118 EON (shifted register)
8695 pub fn eon(d: Register, n: Register, form: union(enum) {
8696 register: Register,
8697 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
8698 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
8699 }) Instruction {
8700 const sf = d.format.integer;
8701 assert(n.format.integer == sf);
8702 form: switch (form) {
8703 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
8704 .shifted_register_explicit => |shifted_register_explicit| {
8705 assert(shifted_register_explicit.register.format.integer == sf);
8706 return .{ .data_processing_register = .{ .logical_shifted_register = .{
8707 .eon = .{
8708 .Rd = d.alias.encode(.{}),
8709 .Rn = n.alias.encode(.{}),
8710 .imm6 = switch (sf) {
8711 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
8712 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
8713 },
8714 .Rm = shifted_register_explicit.register.alias.encode(.{}),
8715 .shift = shifted_register_explicit.shift,
8716 .sf = sf,
8717 },
8718 } } };
8719 },
8720 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
8721 .register = shifted_register.register,
8722 .shift = shifted_register.shift,
8723 .amount = switch (shifted_register.shift) {
8724 .lsl, .lsr, .asr, .ror => |amount| amount,
8725 },
8726 } },
8727 }
8728 }
8729 /// C6.2.119 EOR (immediate)
8730 /// C6.2.120 EOR (shifted register)
8731 /// C7.2.41 EOR (vector)
8732 pub fn eor(d: Register, n: Register, form: union(enum) {
8733 immediate: DataProcessingImmediate.Bitmask,
8734 register: Register,
8735 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
8736 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
8737 }) Instruction {
8738 switch (d.format) {
8739 else => unreachable,
8740 .integer => |sf| {
8741 assert(n.format.integer == sf);
8742 form: switch (form) {
8743 .immediate => |bitmask| {
8744 assert(bitmask.validImmediate(sf));
8745 return .{ .data_processing_immediate = .{ .logical_immediate = .{
8746 .eor = .{
8747 .Rd = d.alias.encode(.{ .sp = true }),
8748 .Rn = n.alias.encode(.{}),
8749 .imm = bitmask,
8750 .sf = sf,
8751 },
8752 } } };
8753 },
8754 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
8755 .shifted_register_explicit => |shifted_register_explicit| {
8756 assert(shifted_register_explicit.register.format.integer == sf);
8757 return .{ .data_processing_register = .{ .logical_shifted_register = .{
8758 .eor = .{
8759 .Rd = d.alias.encode(.{}),
8760 .Rn = n.alias.encode(.{}),
8761 .imm6 = switch (sf) {
8762 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
8763 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
8764 },
8765 .Rm = shifted_register_explicit.register.alias.encode(.{}),
8766 .shift = shifted_register_explicit.shift,
8767 .sf = sf,
8768 },
8769 } } };
8770 },
8771 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
8772 .register = shifted_register.register,
8773 .shift = shifted_register.shift,
8774 .amount = switch (shifted_register.shift) {
8775 .lsl, .lsr, .asr, .ror => |amount| amount,
8776 },
8777 } },
8778 }
8779 },
8780 .vector => |arrangement| {
8781 const m = form.register;
8782 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
8783 return .{ .data_processing_vector = .{ .simd_three_same = .{
8784 .eor = .{
8785 .Rd = d.alias.encode(.{ .V = true }),
8786 .Rn = n.alias.encode(.{ .V = true }),
8787 .Rm = m.alias.encode(.{ .V = true }),
8788 .Q = arrangement.size(),
8789 },
8790 } } };
8791 },
8792 }
8793 }
8794 /// C6.2.124 EXTR
8795 pub fn extr(d: Register, n: Register, m: Register, lsb: u6) Instruction {
8796 const sf = d.format.integer;
8797 assert(n.format.integer == sf and m.format.integer == sf);
8798 return .{ .data_processing_immediate = .{ .extract = .{
8799 .extr = .{
8800 .Rd = d.alias.encode(.{}),
8801 .Rn = n.alias.encode(.{}),
8802 .imms = switch (sf) {
8803 .word => @as(u5, @intCast(lsb)),
8804 .doubleword => @as(u6, @intCast(lsb)),
8805 },
8806 .Rm = m.alias.encode(.{}),
8807 .N = sf,
8808 .sf = sf,
8809 },
8810 } } };
8811 }
8812 /// C7.2.46 FABS (scalar)
8813 pub fn fabs(d: Register, n: Register) Instruction {
8814 const ftype = d.format.scalar;
8815 assert(n.format.scalar == ftype);
8816 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
8817 .fabs = .{
8818 .Rd = d.alias.encode(.{ .V = true }),
8819 .Rn = n.alias.encode(.{ .V = true }),
8820 .ftype = switch (ftype) {
8821 else => unreachable,
8822 .single => .single,
8823 .double => .double,
8824 .half => .half,
8825 },
8826 },
8827 } } };
8828 }
8829 /// C7.2.50 FADD (scalar)
8830 pub fn fadd(d: Register, n: Register, m: Register) Instruction {
8831 const ftype = d.format.scalar;
8832 assert(n.format.scalar == ftype and m.format.scalar == ftype);
8833 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
8834 .fadd = .{
8835 .Rd = d.alias.encode(.{ .V = true }),
8836 .Rn = n.alias.encode(.{ .V = true }),
8837 .Rm = m.alias.encode(.{ .V = true }),
8838 .ftype = switch (ftype) {
8839 else => unreachable,
8840 .single => .single,
8841 .double => .double,
8842 .half => .half,
8843 },
8844 },
8845 } } };
8846 }
8847 /// C7.2.66 FCMP
8848 pub fn fcmp(n: Register, form: union(enum) { register: Register, zero }) Instruction {
8849 const ftype = n.format.scalar;
8850 switch (form) {
8851 .register => |m| {
8852 assert(m.format.scalar == ftype);
8853 return .{ .data_processing_vector = .{ .float_compare = .{
8854 .fcmp = .{
8855 .opc0 = .register,
8856 .Rn = n.alias.encode(.{ .V = true }),
8857 .Rm = m.alias.encode(.{ .V = true }),
8858 .ftype = switch (ftype) {
8859 else => unreachable,
8860 .single => .single,
8861 .double => .double,
8862 .half => .half,
8863 },
8864 },
8865 } } };
8866 },
8867 .zero => return .{ .data_processing_vector = .{ .float_compare = .{
8868 .fcmp = .{
8869 .opc0 = .register,
8870 .Rn = n.alias.encode(.{ .V = true }),
8871 .Rm = @enumFromInt(0b00000),
8872 .ftype = switch (ftype) {
8873 else => unreachable,
8874 .single => .single,
8875 .double => .double,
8876 .half => .half,
8877 },
8878 },
8879 } } },
8880 }
8881 }
8882 /// C7.2.67 FCMPE
8883 pub fn fcmpe(n: Register, form: union(enum) { register: Register, zero }) Instruction {
8884 const ftype = n.format.scalar;
8885 switch (form) {
8886 .register => |m| {
8887 assert(m.format.scalar == ftype);
8888 return .{ .data_processing_vector = .{ .float_compare = .{
8889 .fcmpe = .{
8890 .opc0 = .zero,
8891 .Rn = n.alias.encode(.{ .V = true }),
8892 .Rm = m.alias.encode(.{ .V = true }),
8893 .ftype = switch (ftype) {
8894 else => unreachable,
8895 .single => .single,
8896 .double => .double,
8897 .half => .half,
8898 },
8899 },
8900 } } };
8901 },
8902 .zero => return .{ .data_processing_vector = .{ .float_compare = .{
8903 .fcmpe = .{
8904 .opc0 = .zero,
8905 .Rn = n.alias.encode(.{ .V = true }),
8906 .Rm = @enumFromInt(0b00000),
8907 .ftype = switch (ftype) {
8908 else => unreachable,
8909 .single => .single,
8910 .double => .double,
8911 .half => .half,
8912 },
8913 },
8914 } } },
8915 }
8916 }
8917 /// C7.2.69 FCVT
8918 pub fn fcvt(d: Register, n: Register) Instruction {
8919 assert(d.format.scalar != n.format.scalar);
8920 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
8921 .fcvt = .{
8922 .Rd = d.alias.encode(.{ .V = true }),
8923 .Rn = n.alias.encode(.{ .V = true }),
8924 .opc = switch (d.format.scalar) {
8925 else => unreachable,
8926 .single => .single,
8927 .double => .double,
8928 .half => .half,
8929 },
8930 .ftype = switch (n.format.scalar) {
8931 else => unreachable,
8932 .single => .single,
8933 .double => .double,
8934 .half => .half,
8935 },
8936 },
8937 } } };
8938 }
8939 /// C7.2.71 FCVTAS (scalar)
8940 pub fn fcvtas(d: Register, n: Register) Instruction {
8941 return .{ .data_processing_vector = .{ .convert_float_integer = .{
8942 .fcvtas = .{
8943 .Rd = d.alias.encode(.{}),
8944 .Rn = n.alias.encode(.{ .V = true }),
8945 .ftype = switch (n.format.scalar) {
8946 else => unreachable,
8947 .single => .single,
8948 .double => .double,
8949 .half => .half,
8950 },
8951 .sf = d.format.integer,
8952 },
8953 } } };
8954 }
8955 /// C7.2.73 FCVTAU (scalar)
8956 pub fn fcvtau(d: Register, n: Register) Instruction {
8957 return .{ .data_processing_vector = .{ .convert_float_integer = .{
8958 .fcvtau = .{
8959 .Rd = d.alias.encode(.{}),
8960 .Rn = n.alias.encode(.{ .V = true }),
8961 .ftype = switch (n.format.scalar) {
8962 else => unreachable,
8963 .single => .single,
8964 .double => .double,
8965 .half => .half,
8966 },
8967 .sf = d.format.integer,
8968 },
8969 } } };
8970 }
8971 /// C7.2.76 FCVTMS (scalar)
8972 pub fn fcvtms(d: Register, n: Register) Instruction {
8973 return .{ .data_processing_vector = .{ .convert_float_integer = .{
8974 .fcvtms = .{
8975 .Rd = d.alias.encode(.{}),
8976 .Rn = n.alias.encode(.{ .V = true }),
8977 .ftype = switch (n.format.scalar) {
8978 else => unreachable,
8979 .single => .single,
8980 .double => .double,
8981 .half => .half,
8982 },
8983 .sf = d.format.integer,
8984 },
8985 } } };
8986 }
8987 /// C7.2.78 FCVTMU (scalar)
8988 pub fn fcvtmu(d: Register, n: Register) Instruction {
8989 return .{ .data_processing_vector = .{ .convert_float_integer = .{
8990 .fcvtmu = .{
8991 .Rd = d.alias.encode(.{}),
8992 .Rn = n.alias.encode(.{ .V = true }),
8993 .ftype = switch (n.format.scalar) {
8994 else => unreachable,
8995 .single => .single,
8996 .double => .double,
8997 .half => .half,
8998 },
8999 .sf = d.format.integer,
9000 },
9001 } } };
9002 }
9003 /// C7.2.81 FCVTNS (scalar)
9004 pub fn fcvtns(d: Register, n: Register) Instruction {
9005 return .{ .data_processing_vector = .{ .convert_float_integer = .{
9006 .fcvtns = .{
9007 .Rd = d.alias.encode(.{}),
9008 .Rn = n.alias.encode(.{ .V = true }),
9009 .ftype = switch (n.format.scalar) {
9010 else => unreachable,
9011 .single => .single,
9012 .double => .double,
9013 .half => .half,
9014 },
9015 .sf = d.format.integer,
9016 },
9017 } } };
9018 }
9019 /// C7.2.83 FCVTNU (scalar)
9020 pub fn fcvtnu(d: Register, n: Register) Instruction {
9021 return .{ .data_processing_vector = .{ .convert_float_integer = .{
9022 .fcvtnu = .{
9023 .Rd = d.alias.encode(.{}),
9024 .Rn = n.alias.encode(.{ .V = true }),
9025 .ftype = switch (n.format.scalar) {
9026 else => unreachable,
9027 .single => .single,
9028 .double => .double,
9029 .half => .half,
9030 },
9031 .sf = d.format.integer,
9032 },
9033 } } };
9034 }
9035 /// C7.2.85 FCVTPS (scalar)
9036 pub fn fcvtps(d: Register, n: Register) Instruction {
9037 return .{ .data_processing_vector = .{ .convert_float_integer = .{
9038 .fcvtps = .{
9039 .Rd = d.alias.encode(.{}),
9040 .Rn = n.alias.encode(.{ .V = true }),
9041 .ftype = switch (n.format.scalar) {
9042 else => unreachable,
9043 .single => .single,
9044 .double => .double,
9045 .half => .half,
9046 },
9047 .sf = d.format.integer,
9048 },
9049 } } };
9050 }
9051 /// C7.2.87 FCVTPU (scalar)
9052 pub fn fcvtpu(d: Register, n: Register) Instruction {
9053 return .{ .data_processing_vector = .{ .convert_float_integer = .{
9054 .fcvtpu = .{
9055 .Rd = d.alias.encode(.{}),
9056 .Rn = n.alias.encode(.{ .V = true }),
9057 .ftype = switch (n.format.scalar) {
9058 else => unreachable,
9059 .single => .single,
9060 .double => .double,
9061 .half => .half,
9062 },
9063 .sf = d.format.integer,
9064 },
9065 } } };
9066 }
9067 /// C7.2.92 FCVTZS (scalar, integer)
9068 pub fn fcvtzs(d: Register, n: Register) Instruction {
9069 return .{ .data_processing_vector = .{ .convert_float_integer = .{
9070 .fcvtzs = .{
9071 .Rd = d.alias.encode(.{}),
9072 .Rn = n.alias.encode(.{ .V = true }),
9073 .ftype = switch (n.format.scalar) {
9074 else => unreachable,
9075 .single => .single,
9076 .double => .double,
9077 .half => .half,
9078 },
9079 .sf = d.format.integer,
9080 },
9081 } } };
9082 }
9083 /// C7.2.96 FCVTZU (scalar, integer)
9084 pub fn fcvtzu(d: Register, n: Register) Instruction {
9085 return .{ .data_processing_vector = .{ .convert_float_integer = .{
9086 .fcvtzu = .{
9087 .Rd = d.alias.encode(.{}),
9088 .Rn = n.alias.encode(.{ .V = true }),
9089 .ftype = switch (n.format.scalar) {
9090 else => unreachable,
9091 .single => .single,
9092 .double => .double,
9093 .half => .half,
9094 },
9095 .sf = d.format.integer,
9096 },
9097 } } };
9098 }
9099 /// C7.2.98 FDIV (scalar)
9100 pub fn fdiv(d: Register, n: Register, m: Register) Instruction {
9101 const ftype = d.format.scalar;
9102 assert(n.format.scalar == ftype and m.format.scalar == ftype);
9103 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
9104 .fdiv = .{
9105 .Rd = d.alias.encode(.{ .V = true }),
9106 .Rn = n.alias.encode(.{ .V = true }),
9107 .Rm = m.alias.encode(.{ .V = true }),
9108 .ftype = switch (ftype) {
9109 else => unreachable,
9110 .single => .single,
9111 .double => .double,
9112 .half => .half,
9113 },
9114 },
9115 } } };
9116 }
9117 /// C7.2.99 FJCVTZS
9118 pub fn fjcvtzs(d: Register, n: Register) Instruction {
9119 assert(d.format.integer == .word);
9120 assert(n.format.scalar == .double);
9121 return .{ .data_processing_vector = .{ .convert_float_integer = .{
9122 .fjcvtzs = .{
9123 .Rd = d.alias.encode(.{}),
9124 .Rn = n.alias.encode(.{ .V = true }),
9125 },
9126 } } };
9127 }
9128 /// C7.2.100 FMADD
9129 pub fn fmadd(d: Register, n: Register, m: Register, a: Register) Instruction {
9130 const ftype = d.format.scalar;
9131 assert(n.format.scalar == ftype and m.format.scalar == ftype and a.format.scalar == ftype);
9132 return .{ .data_processing_vector = .{ .float_data_processing_three_source = .{
9133 .fmadd = .{
9134 .Rd = d.alias.encode(.{ .V = true }),
9135 .Rn = n.alias.encode(.{ .V = true }),
9136 .Rm = m.alias.encode(.{ .V = true }),
9137 .Ra = a.alias.encode(.{ .V = true }),
9138 .ftype = switch (ftype) {
9139 else => unreachable,
9140 .single => .single,
9141 .double => .double,
9142 .half => .half,
9143 },
9144 },
9145 } } };
9146 }
9147 /// C7.2.102 FMAX (scalar)
9148 pub fn fmax(d: Register, n: Register, m: Register) Instruction {
9149 const ftype = d.format.scalar;
9150 assert(n.format.scalar == ftype and m.format.scalar == ftype);
9151 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
9152 .fmax = .{
9153 .Rd = d.alias.encode(.{ .V = true }),
9154 .Rn = n.alias.encode(.{ .V = true }),
9155 .Rm = m.alias.encode(.{ .V = true }),
9156 .ftype = switch (ftype) {
9157 else => unreachable,
9158 .single => .single,
9159 .double => .double,
9160 .half => .half,
9161 },
9162 },
9163 } } };
9164 }
9165 /// C7.2.104 FMAXNM (scalar)
9166 pub fn fmaxnm(d: Register, n: Register, m: Register) Instruction {
9167 const ftype = d.format.scalar;
9168 assert(n.format.scalar == ftype and m.format.scalar == ftype);
9169 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
9170 .fmaxnm = .{
9171 .Rd = d.alias.encode(.{ .V = true }),
9172 .Rn = n.alias.encode(.{ .V = true }),
9173 .Rm = m.alias.encode(.{ .V = true }),
9174 .ftype = switch (ftype) {
9175 else => unreachable,
9176 .single => .single,
9177 .double => .double,
9178 .half => .half,
9179 },
9180 },
9181 } } };
9182 }
9183 /// C7.2.112 FMIN (scalar)
9184 pub fn fmin(d: Register, n: Register, m: Register) Instruction {
9185 const ftype = d.format.scalar;
9186 assert(n.format.scalar == ftype and m.format.scalar == ftype);
9187 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
9188 .fmin = .{
9189 .Rd = d.alias.encode(.{ .V = true }),
9190 .Rn = n.alias.encode(.{ .V = true }),
9191 .Rm = m.alias.encode(.{ .V = true }),
9192 .ftype = switch (ftype) {
9193 else => unreachable,
9194 .single => .single,
9195 .double => .double,
9196 .half => .half,
9197 },
9198 },
9199 } } };
9200 }
9201 /// C7.2.114 FMINNM (scalar)
9202 pub fn fminnm(d: Register, n: Register, m: Register) Instruction {
9203 const ftype = d.format.scalar;
9204 assert(n.format.scalar == ftype and m.format.scalar == ftype);
9205 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
9206 .fminnm = .{
9207 .Rd = d.alias.encode(.{ .V = true }),
9208 .Rn = n.alias.encode(.{ .V = true }),
9209 .Rm = m.alias.encode(.{ .V = true }),
9210 .ftype = switch (ftype) {
9211 else => unreachable,
9212 .single => .single,
9213 .double => .double,
9214 .half => .half,
9215 },
9216 },
9217 } } };
9218 }
9219 /// C7.2.129 FMOV (vector, immediate)
9220 /// C7.2.130 FMOV (register)
9221 /// C7.2.131 FMOV (general)
9222 /// C7.2.132 FMOV (scalar, immediate)
9223 pub fn fmov(d: Register, form: union(enum) { immediate: f16, register: Register }) Instruction {
9224 switch (form) {
9225 .immediate => |immediate| {
9226 const repr: std.math.FloatRepr(f16) = @bitCast(immediate);
9227 const imm: u8 = @bitCast(@as(packed struct(u8) {
9228 mantissa: u4,
9229 exponent: i3,
9230 sign: std.math.Sign,
9231 }, .{
9232 .mantissa = @intCast(@shrExact(repr.mantissa, 6)),
9233 .exponent = @intCast(repr.exponent.unbias() - 1),
9234 .sign = repr.sign,
9235 }));
9236 switch (d.format) {
9237 else => unreachable,
9238 .scalar => |ftype| return .{ .data_processing_vector = .{ .float_immediate = .{
9239 .fmov = .{
9240 .Rd = d.alias.encode(.{ .V = true }),
9241 .imm8 = imm,
9242 .ftype = switch (ftype) {
9243 else => unreachable,
9244 .single => .single,
9245 .double => .double,
9246 .half => .half,
9247 },
9248 },
9249 } } },
9250 .vector => |arrangement| {
9251 assert(arrangement.len() > 1 and arrangement.elemSize() != .byte);
9252 return .{ .data_processing_vector = .{ .simd_modified_immediate = .{
9253 .fmov = .{
9254 .Rd = d.alias.encode(.{ .V = true }),
9255 .imm5 = @truncate(imm >> 0),
9256 .imm3 = @intCast(imm >> 5),
9257 .Q = arrangement.size(),
9258 },
9259 } } };
9260 },
9261 }
9262 },
9263 .register => |n| switch (d.format) {
9264 else => unreachable,
9265 .integer => |sf| switch (n.format) {
9266 else => unreachable,
9267 .scalar => |ftype| {
9268 switch (ftype) {
9269 else => unreachable,
9270 .half => {},
9271 .single => assert(sf == .word),
9272 .double => assert(sf == .doubleword),
9273 }
9274 return .{ .data_processing_vector = .{ .convert_float_integer = .{
9275 .fmov = .{
9276 .Rd = d.alias.encode(.{}),
9277 .Rn = n.alias.encode(.{ .V = true }),
9278 .opcode = .float_to_integer,
9279 .rmode = .@"0",
9280 .ftype = switch (ftype) {
9281 else => unreachable,
9282 .single => .single,
9283 .double => .double,
9284 .half => .half,
9285 },
9286 .sf = sf,
9287 },
9288 } } };
9289 },
9290 .element => |element| return .{ .data_processing_vector = .{ .convert_float_integer = .{
9291 .fmov = .{
9292 .Rd = d.alias.encode(.{}),
9293 .Rn = n.alias.encode(.{ .V = true }),
9294 .opcode = .float_to_integer,
9295 .rmode = switch (element.index) {
9296 else => unreachable,
9297 1 => .@"1",
9298 },
9299 .ftype = switch (element.size) {
9300 else => unreachable,
9301 .double => .quad,
9302 },
9303 .sf = sf,
9304 },
9305 } } },
9306 },
9307 .scalar => |ftype| switch (n.format) {
9308 else => unreachable,
9309 .integer => {
9310 const sf = n.format.integer;
9311 switch (ftype) {
9312 else => unreachable,
9313 .half => {},
9314 .single => assert(sf == .word),
9315 .double => assert(sf == .doubleword),
9316 }
9317 return .{ .data_processing_vector = .{ .convert_float_integer = .{
9318 .fmov = .{
9319 .Rd = d.alias.encode(.{ .V = true }),
9320 .Rn = n.alias.encode(.{}),
9321 .opcode = .integer_to_float,
9322 .rmode = .@"0",
9323 .ftype = switch (ftype) {
9324 else => unreachable,
9325 .single => .single,
9326 .double => .double,
9327 .half => .half,
9328 },
9329 .sf = sf,
9330 },
9331 } } };
9332 },
9333 .scalar => {
9334 assert(n.format.scalar == ftype);
9335 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9336 .fmov = .{
9337 .Rd = d.alias.encode(.{ .V = true }),
9338 .Rn = n.alias.encode(.{ .V = true }),
9339 .ftype = switch (ftype) {
9340 else => unreachable,
9341 .single => .single,
9342 .double => .double,
9343 .half => .half,
9344 },
9345 },
9346 } } };
9347 },
9348 },
9349 .element => |element| switch (n.format) {
9350 else => unreachable,
9351 .integer => |sf| return .{ .data_processing_vector = .{ .convert_float_integer = .{
9352 .fmov = .{
9353 .Rd = d.alias.encode(.{ .V = true }),
9354 .Rn = n.alias.encode(.{}),
9355 .opcode = .integer_to_float,
9356 .rmode = switch (element.index) {
9357 else => unreachable,
9358 1 => .@"1",
9359 },
9360 .ftype = switch (element.size) {
9361 else => unreachable,
9362 .double => .quad,
9363 },
9364 .sf = sf,
9365 },
9366 } } },
9367 },
9368 },
9369 }
9370 }
9371 /// C7.2.133 FMSUB
9372 pub fn fmsub(d: Register, n: Register, m: Register, a: Register) Instruction {
9373 const ftype = d.format.scalar;
9374 assert(n.format.scalar == ftype and m.format.scalar == ftype and a.format.scalar == ftype);
9375 return .{ .data_processing_vector = .{ .float_data_processing_three_source = .{
9376 .fmsub = .{
9377 .Rd = d.alias.encode(.{ .V = true }),
9378 .Rn = n.alias.encode(.{ .V = true }),
9379 .Rm = m.alias.encode(.{ .V = true }),
9380 .Ra = a.alias.encode(.{ .V = true }),
9381 .ftype = switch (ftype) {
9382 else => unreachable,
9383 .single => .single,
9384 .double => .double,
9385 .half => .half,
9386 },
9387 },
9388 } } };
9389 }
9390 /// C7.2.136 FMUL (scalar)
9391 pub fn fmul(d: Register, n: Register, m: Register) Instruction {
9392 const ftype = d.format.scalar;
9393 assert(n.format.scalar == ftype and m.format.scalar == ftype);
9394 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
9395 .fmul = .{
9396 .Rd = d.alias.encode(.{ .V = true }),
9397 .Rn = n.alias.encode(.{ .V = true }),
9398 .Rm = m.alias.encode(.{ .V = true }),
9399 .ftype = switch (ftype) {
9400 else => unreachable,
9401 .single => .single,
9402 .double => .double,
9403 .half => .half,
9404 },
9405 },
9406 } } };
9407 }
9408 /// C7.2.140 FNEG (scalar)
9409 pub fn fneg(d: Register, n: Register) Instruction {
9410 const ftype = d.format.scalar;
9411 assert(n.format.scalar == ftype);
9412 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9413 .fneg = .{
9414 .Rd = d.alias.encode(.{ .V = true }),
9415 .Rn = n.alias.encode(.{ .V = true }),
9416 .ftype = switch (ftype) {
9417 else => unreachable,
9418 .single => .single,
9419 .double => .double,
9420 .half => .half,
9421 },
9422 },
9423 } } };
9424 }
9425 /// C7.2.141 FNMADD
9426 pub fn fnmadd(d: Register, n: Register, m: Register, a: Register) Instruction {
9427 const ftype = d.format.scalar;
9428 assert(n.format.scalar == ftype and m.format.scalar == ftype and a.format.scalar == ftype);
9429 return .{ .data_processing_vector = .{ .float_data_processing_three_source = .{
9430 .fnmadd = .{
9431 .Rd = d.alias.encode(.{ .V = true }),
9432 .Rn = n.alias.encode(.{ .V = true }),
9433 .Rm = m.alias.encode(.{ .V = true }),
9434 .Ra = a.alias.encode(.{ .V = true }),
9435 .ftype = switch (ftype) {
9436 else => unreachable,
9437 .single => .single,
9438 .double => .double,
9439 .half => .half,
9440 },
9441 },
9442 } } };
9443 }
9444 /// C7.2.142 FNMSUB
9445 pub fn fnmsub(d: Register, n: Register, m: Register, a: Register) Instruction {
9446 const ftype = d.format.scalar;
9447 assert(n.format.scalar == ftype and m.format.scalar == ftype and a.format.scalar == ftype);
9448 return .{ .data_processing_vector = .{ .float_data_processing_three_source = .{
9449 .fnmsub = .{
9450 .Rd = d.alias.encode(.{ .V = true }),
9451 .Rn = n.alias.encode(.{ .V = true }),
9452 .Rm = m.alias.encode(.{ .V = true }),
9453 .Ra = a.alias.encode(.{ .V = true }),
9454 .ftype = switch (ftype) {
9455 else => unreachable,
9456 .single => .single,
9457 .double => .double,
9458 .half => .half,
9459 },
9460 },
9461 } } };
9462 }
9463 /// C7.2.143 FNMUL (scalar)
9464 pub fn fnmul(d: Register, n: Register, m: Register) Instruction {
9465 const ftype = d.format.scalar;
9466 assert(n.format.scalar == ftype and m.format.scalar == ftype);
9467 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
9468 .fnmul = .{
9469 .Rd = d.alias.encode(.{ .V = true }),
9470 .Rn = n.alias.encode(.{ .V = true }),
9471 .Rm = m.alias.encode(.{ .V = true }),
9472 .ftype = switch (ftype) {
9473 else => unreachable,
9474 .single => .single,
9475 .double => .double,
9476 .half => .half,
9477 },
9478 },
9479 } } };
9480 }
9481 /// C7.2.156 FRINTA (scalar)
9482 pub fn frinta(d: Register, n: Register) Instruction {
9483 const ftype = d.format.scalar;
9484 assert(n.format.scalar == ftype);
9485 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9486 .frinta = .{
9487 .Rd = d.alias.encode(.{ .V = true }),
9488 .Rn = n.alias.encode(.{ .V = true }),
9489 .ftype = switch (ftype) {
9490 else => unreachable,
9491 .single => .single,
9492 .double => .double,
9493 .half => .half,
9494 },
9495 },
9496 } } };
9497 }
9498 /// C7.2.158 FRINTI (scalar)
9499 pub fn frinti(d: Register, n: Register) Instruction {
9500 const ftype = d.format.scalar;
9501 assert(n.format.scalar == ftype);
9502 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9503 .frinti = .{
9504 .Rd = d.alias.encode(.{ .V = true }),
9505 .Rn = n.alias.encode(.{ .V = true }),
9506 .ftype = switch (ftype) {
9507 else => unreachable,
9508 .single => .single,
9509 .double => .double,
9510 .half => .half,
9511 },
9512 },
9513 } } };
9514 }
9515 /// C7.2.160 FRINTM (scalar)
9516 pub fn frintm(d: Register, n: Register) Instruction {
9517 const ftype = d.format.scalar;
9518 assert(n.format.scalar == ftype);
9519 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9520 .frintm = .{
9521 .Rd = d.alias.encode(.{ .V = true }),
9522 .Rn = n.alias.encode(.{ .V = true }),
9523 .ftype = switch (ftype) {
9524 else => unreachable,
9525 .single => .single,
9526 .double => .double,
9527 .half => .half,
9528 },
9529 },
9530 } } };
9531 }
9532 /// C7.2.162 FRINTN (scalar)
9533 pub fn frintn(d: Register, n: Register) Instruction {
9534 const ftype = d.format.scalar;
9535 assert(n.format.scalar == ftype);
9536 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9537 .frintn = .{
9538 .Rd = d.alias.encode(.{ .V = true }),
9539 .Rn = n.alias.encode(.{ .V = true }),
9540 .ftype = switch (ftype) {
9541 else => unreachable,
9542 .single => .single,
9543 .double => .double,
9544 .half => .half,
9545 },
9546 },
9547 } } };
9548 }
9549 /// C7.2.164 FRINTP (scalar)
9550 pub fn frintp(d: Register, n: Register) Instruction {
9551 const ftype = d.format.scalar;
9552 assert(n.format.scalar == ftype);
9553 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9554 .frintp = .{
9555 .Rd = d.alias.encode(.{ .V = true }),
9556 .Rn = n.alias.encode(.{ .V = true }),
9557 .ftype = switch (ftype) {
9558 else => unreachable,
9559 .single => .single,
9560 .double => .double,
9561 .half => .half,
9562 },
9563 },
9564 } } };
9565 }
9566 /// C7.2.166 FRINTX (scalar)
9567 pub fn frintx(d: Register, n: Register) Instruction {
9568 const ftype = d.format.scalar;
9569 assert(n.format.scalar == ftype);
9570 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9571 .frintx = .{
9572 .Rd = d.alias.encode(.{ .V = true }),
9573 .Rn = n.alias.encode(.{ .V = true }),
9574 .ftype = switch (ftype) {
9575 else => unreachable,
9576 .single => .single,
9577 .double => .double,
9578 .half => .half,
9579 },
9580 },
9581 } } };
9582 }
9583 /// C7.2.168 FRINTZ (scalar)
9584 pub fn frintz(d: Register, n: Register) Instruction {
9585 const ftype = d.format.scalar;
9586 assert(n.format.scalar == ftype);
9587 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9588 .frintz = .{
9589 .Rd = d.alias.encode(.{ .V = true }),
9590 .Rn = n.alias.encode(.{ .V = true }),
9591 .ftype = switch (ftype) {
9592 else => unreachable,
9593 .single => .single,
9594 .double => .double,
9595 .half => .half,
9596 },
9597 },
9598 } } };
9599 }
9600 /// C7.2.172 FSQRT (scalar)
9601 pub fn fsqrt(d: Register, n: Register) Instruction {
9602 const ftype = d.format.scalar;
9603 assert(n.format.scalar == ftype);
9604 return .{ .data_processing_vector = .{ .float_data_processing_one_source = .{
9605 .fsqrt = .{
9606 .Rd = d.alias.encode(.{ .V = true }),
9607 .Rn = n.alias.encode(.{ .V = true }),
9608 .ftype = switch (ftype) {
9609 else => unreachable,
9610 .single => .single,
9611 .double => .double,
9612 .half => .half,
9613 },
9614 },
9615 } } };
9616 }
9617 /// C7.2.174 FSUB (scalar)
9618 pub fn fsub(d: Register, n: Register, m: Register) Instruction {
9619 const ftype = d.format.scalar;
9620 assert(n.format.scalar == ftype and m.format.scalar == ftype);
9621 return .{ .data_processing_vector = .{ .float_data_processing_two_source = .{
9622 .fsub = .{
9623 .Rd = d.alias.encode(.{ .V = true }),
9624 .Rn = n.alias.encode(.{ .V = true }),
9625 .Rm = m.alias.encode(.{ .V = true }),
9626 .ftype = switch (ftype) {
9627 else => unreachable,
9628 .single => .single,
9629 .double => .double,
9630 .half => .half,
9631 },
9632 },
9633 } } };
9634 }
9635 /// C6.2.126 HINT
9636 pub fn hint(imm: u7) Instruction {
9637 return .{ .branch_exception_generating_system = .{ .hints = .{
9638 .group = .{
9639 .op2 = @truncate(imm >> 0),
9640 .CRm = @intCast(imm >> 3),
9641 },
9642 } } };
9643 }
9644 /// C6.2.127 HLT
9645 pub fn hlt(imm: u16) Instruction {
9646 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
9647 .hlt = .{ .imm16 = imm },
9648 } } };
9649 }
9650 /// C6.2.128 HVC
9651 pub fn hvc(imm: u16) Instruction {
9652 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
9653 .hvc = .{ .imm16 = imm },
9654 } } };
9655 }
9656 /// C6.2.131 ISB
9657 pub fn isb(option: BranchExceptionGeneratingSystem.Barriers.Option) Instruction {
9658 return .{ .branch_exception_generating_system = .{ .barriers = .{
9659 .isb = .{
9660 .CRm = option,
9661 },
9662 } } };
9663 }
9664 /// C6.2.164 LDP
9665 /// C7.2.190 LDP (SIMD&FP)
9666 pub fn ldp(t1: Register, t2: Register, form: union(enum) {
9667 post_index: struct { base: Register, index: i10 },
9668 pre_index: struct { base: Register, index: i10 },
9669 signed_offset: struct { base: Register, offset: i10 = 0 },
9670 base: Register,
9671 }) Instruction {
9672 switch (t1.format) {
9673 else => unreachable,
9674 .integer => |sf| {
9675 assert(t2.format.integer == sf);
9676 form: switch (form) {
9677 .post_index => |post_index| {
9678 assert(post_index.base.format.integer == .doubleword);
9679 return .{ .load_store = .{ .register_pair_post_indexed = .{ .integer = .{
9680 .ldp = .{
9681 .Rt = t1.alias.encode(.{}),
9682 .Rn = post_index.base.alias.encode(.{ .sp = true }),
9683 .Rt2 = t2.alias.encode(.{}),
9684 .imm7 = @intCast(@shrExact(post_index.index, @as(u2, 2) + @intFromEnum(sf))),
9685 .sf = sf,
9686 },
9687 } } } };
9688 },
9689 .signed_offset => |signed_offset| {
9690 assert(signed_offset.base.format.integer == .doubleword);
9691 return .{ .load_store = .{ .register_pair_offset = .{ .integer = .{
9692 .ldp = .{
9693 .Rt = t1.alias.encode(.{}),
9694 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
9695 .Rt2 = t2.alias.encode(.{}),
9696 .imm7 = @intCast(@shrExact(signed_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
9697 .sf = sf,
9698 },
9699 } } } };
9700 },
9701 .pre_index => |pre_index| {
9702 assert(pre_index.base.format.integer == .doubleword);
9703 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .integer = .{
9704 .ldp = .{
9705 .Rt = t1.alias.encode(.{}),
9706 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
9707 .Rt2 = t2.alias.encode(.{}),
9708 .imm7 = @intCast(@shrExact(pre_index.index, @as(u2, 2) + @intFromEnum(sf))),
9709 .sf = sf,
9710 },
9711 } } } };
9712 },
9713 .base => |base| continue :form .{ .signed_offset = .{ .base = base } },
9714 }
9715 },
9716 .scalar => |vs| {
9717 assert(t2.format.scalar == vs);
9718 form: switch (form) {
9719 .post_index => |post_index| {
9720 assert(post_index.base.format.integer == .doubleword);
9721 return .{ .load_store = .{ .register_pair_post_indexed = .{ .vector = .{
9722 .ldp = .{
9723 .Rt = t1.alias.encode(.{ .V = true }),
9724 .Rn = post_index.base.alias.encode(.{ .sp = true }),
9725 .Rt2 = t2.alias.encode(.{ .V = true }),
9726 .imm7 = @intCast(@shrExact(post_index.index, @intFromEnum(vs))),
9727 .opc = .encode(vs),
9728 },
9729 } } } };
9730 },
9731 .signed_offset => |signed_offset| {
9732 assert(signed_offset.base.format.integer == .doubleword);
9733 return .{ .load_store = .{ .register_pair_offset = .{ .vector = .{
9734 .ldp = .{
9735 .Rt = t1.alias.encode(.{ .V = true }),
9736 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
9737 .Rt2 = t2.alias.encode(.{ .V = true }),
9738 .imm7 = @intCast(@shrExact(signed_offset.offset, @intFromEnum(vs))),
9739 .opc = .encode(vs),
9740 },
9741 } } } };
9742 },
9743 .pre_index => |pre_index| {
9744 assert(pre_index.base.format.integer == .doubleword);
9745 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .vector = .{
9746 .ldp = .{
9747 .Rt = t1.alias.encode(.{ .V = true }),
9748 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
9749 .Rt2 = t2.alias.encode(.{ .V = true }),
9750 .imm7 = @intCast(@shrExact(pre_index.index, @intFromEnum(vs))),
9751 .opc = .encode(vs),
9752 },
9753 } } } };
9754 },
9755 .base => |base| continue :form .{ .signed_offset = .{ .base = base } },
9756 }
9757 },
9758 }
9759 }
9760 /// C6.2.166 LDR (immediate)
9761 /// C6.2.167 LDR (literal)
9762 /// C6.2.168 LDR (register)
9763 /// C7.2.191 LDR (immediate, SIMD&FP)
9764 /// C7.2.192 LDR (literal, SIMD&FP)
9765 /// C7.2.193 LDR (register, SIMD&FP)
9766 pub fn ldr(t: Register, form: union(enum) {
9767 post_index: struct { base: Register, index: i9 },
9768 pre_index: struct { base: Register, index: i9 },
9769 unsigned_offset: struct { base: Register, offset: u16 = 0 },
9770 base: Register,
9771 literal: i21,
9772 extended_register_explicit: struct {
9773 base: Register,
9774 index: Register,
9775 option: LoadStore.RegisterRegisterOffset.Option,
9776 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
9777 },
9778 extended_register: struct {
9779 base: Register,
9780 index: Register,
9781 extend: LoadStore.RegisterRegisterOffset.Extend,
9782 },
9783 }) Instruction {
9784 switch (t.format) {
9785 else => unreachable,
9786 .integer => |sf| form: switch (form) {
9787 .post_index => |post_index| {
9788 assert(post_index.base.format.integer == .doubleword);
9789 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
9790 .ldr = .{
9791 .Rt = t.alias.encode(.{}),
9792 .Rn = post_index.base.alias.encode(.{ .sp = true }),
9793 .imm9 = post_index.index,
9794 .sf = sf,
9795 },
9796 } } } };
9797 },
9798 .pre_index => |pre_index| {
9799 assert(pre_index.base.format.integer == .doubleword);
9800 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
9801 .ldr = .{
9802 .Rt = t.alias.encode(.{}),
9803 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
9804 .imm9 = pre_index.index,
9805 .sf = sf,
9806 },
9807 } } } };
9808 },
9809 .unsigned_offset => |unsigned_offset| {
9810 assert(unsigned_offset.base.format.integer == .doubleword);
9811 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
9812 .ldr = .{
9813 .Rt = t.alias.encode(.{}),
9814 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
9815 .imm12 = @intCast(@shrExact(unsigned_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
9816 .sf = sf,
9817 },
9818 } } } };
9819 },
9820 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
9821 .literal => |offset| return .{ .load_store = .{ .register_literal = .{ .integer = .{
9822 .ldr = .{
9823 .Rt = t.alias.encode(.{}),
9824 .imm19 = @intCast(@shrExact(offset, 2)),
9825 .sf = sf,
9826 },
9827 } } } },
9828 .extended_register_explicit => |extended_register_explicit| {
9829 assert(extended_register_explicit.base.format.integer == .doubleword and
9830 extended_register_explicit.index.format.integer == extended_register_explicit.option.sf());
9831 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
9832 .ldr = .{
9833 .Rt = t.alias.encode(.{}),
9834 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
9835 .S = switch (sf) {
9836 .word => switch (extended_register_explicit.amount) {
9837 0 => false,
9838 2 => true,
9839 else => unreachable,
9840 },
9841 .doubleword => switch (extended_register_explicit.amount) {
9842 0 => false,
9843 3 => true,
9844 else => unreachable,
9845 },
9846 },
9847 .option = extended_register_explicit.option,
9848 .Rm = extended_register_explicit.index.alias.encode(.{}),
9849 .sf = sf,
9850 },
9851 } } } };
9852 },
9853 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
9854 .base = extended_register.base,
9855 .index = extended_register.index,
9856 .option = extended_register.extend,
9857 .amount = switch (extended_register.extend) {
9858 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
9859 },
9860 } },
9861 },
9862 .scalar => |vs| form: switch (form) {
9863 .post_index => |post_index| {
9864 assert(post_index.base.format.integer == .doubleword);
9865 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .vector = .{
9866 .ldr = .{
9867 .Rt = t.alias.encode(.{ .V = true }),
9868 .Rn = post_index.base.alias.encode(.{ .sp = true }),
9869 .imm9 = post_index.index,
9870 .opc1 = .encode(vs),
9871 .size = .encode(vs),
9872 },
9873 } } } };
9874 },
9875 .pre_index => |pre_index| {
9876 assert(pre_index.base.format.integer == .doubleword);
9877 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .vector = .{
9878 .ldr = .{
9879 .Rt = t.alias.encode(.{ .V = true }),
9880 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
9881 .imm9 = pre_index.index,
9882 .opc1 = .encode(vs),
9883 .size = .encode(vs),
9884 },
9885 } } } };
9886 },
9887 .unsigned_offset => |unsigned_offset| {
9888 assert(unsigned_offset.base.format.integer == .doubleword);
9889 return .{ .load_store = .{ .register_unsigned_immediate = .{ .vector = .{
9890 .ldr = .{
9891 .Rt = t.alias.encode(.{ .V = true }),
9892 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
9893 .imm12 = @intCast(@shrExact(unsigned_offset.offset, @intFromEnum(vs))),
9894 .opc1 = .encode(vs),
9895 .size = .encode(vs),
9896 },
9897 } } } };
9898 },
9899 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
9900 .literal => |offset| return .{ .load_store = .{ .register_literal = .{ .vector = .{
9901 .ldr = .{
9902 .Rt = t.alias.encode(.{ .V = true }),
9903 .imm19 = @intCast(@shrExact(offset, 2)),
9904 .opc = .encode(vs),
9905 },
9906 } } } },
9907 .extended_register_explicit => |extended_register_explicit| {
9908 assert(extended_register_explicit.base.format.integer == .doubleword and
9909 extended_register_explicit.index.format.integer == extended_register_explicit.option.sf());
9910 return .{ .load_store = .{ .register_register_offset = .{ .vector = .{
9911 .ldr = .{
9912 .Rt = t.alias.encode(.{ .V = true }),
9913 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
9914 .S = switch (vs) {
9915 else => unreachable,
9916 .byte => switch (extended_register_explicit.amount) {
9917 0 => false,
9918 else => unreachable,
9919 },
9920 .half => switch (extended_register_explicit.amount) {
9921 0 => false,
9922 1 => true,
9923 else => unreachable,
9924 },
9925 .single => switch (extended_register_explicit.amount) {
9926 0 => false,
9927 2 => true,
9928 else => unreachable,
9929 },
9930 .double => switch (extended_register_explicit.amount) {
9931 0 => false,
9932 3 => true,
9933 else => unreachable,
9934 },
9935 .quad => switch (extended_register_explicit.amount) {
9936 0 => false,
9937 4 => true,
9938 else => unreachable,
9939 },
9940 },
9941 .option = extended_register_explicit.option,
9942 .Rm = extended_register_explicit.index.alias.encode(.{}),
9943 .opc1 = .encode(vs),
9944 .size = .encode(vs),
9945 },
9946 } } } };
9947 },
9948 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
9949 .base = extended_register.base,
9950 .index = extended_register.index,
9951 .option = extended_register.extend,
9952 .amount = switch (extended_register.extend) {
9953 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
9954 },
9955 } },
9956 },
9957 }
9958 }
9959 /// C6.2.170 LDRB (immediate)
9960 /// C6.2.171 LDRB (register)
9961 pub fn ldrb(t: Register, form: union(enum) {
9962 post_index: struct { base: Register, index: i9 },
9963 pre_index: struct { base: Register, index: i9 },
9964 unsigned_offset: struct { base: Register, offset: u12 = 0 },
9965 base: Register,
9966 extended_register_explicit: struct {
9967 base: Register,
9968 index: Register,
9969 option: LoadStore.RegisterRegisterOffset.Option,
9970 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
9971 },
9972 extended_register: struct {
9973 base: Register,
9974 index: Register,
9975 extend: LoadStore.RegisterRegisterOffset.Extend,
9976 },
9977 }) Instruction {
9978 assert(t.format.integer == .word);
9979 form: switch (form) {
9980 .post_index => |post_index| {
9981 assert(post_index.base.format.integer == .doubleword);
9982 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
9983 .ldrb = .{
9984 .Rt = t.alias.encode(.{}),
9985 .Rn = post_index.base.alias.encode(.{ .sp = true }),
9986 .imm9 = post_index.index,
9987 },
9988 } } } };
9989 },
9990 .pre_index => |pre_index| {
9991 assert(pre_index.base.format.integer == .doubleword);
9992 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
9993 .ldrb = .{
9994 .Rt = t.alias.encode(.{}),
9995 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
9996 .imm9 = pre_index.index,
9997 },
9998 } } } };
9999 },
10000 .unsigned_offset => |unsigned_offset| {
10001 assert(unsigned_offset.base.format.integer == .doubleword);
10002 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
10003 .ldrb = .{
10004 .Rt = t.alias.encode(.{}),
10005 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
10006 .imm12 = unsigned_offset.offset,
10007 },
10008 } } } };
10009 },
10010 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
10011 .extended_register_explicit => |extended_register_explicit| {
10012 assert(extended_register_explicit.base.format.integer == .doubleword and
10013 extended_register_explicit.index.format.integer == extended_register_explicit.option.sf());
10014 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
10015 .ldrb = .{
10016 .Rt = t.alias.encode(.{}),
10017 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
10018 .S = switch (extended_register_explicit.amount) {
10019 0 => false,
10020 else => unreachable,
10021 },
10022 .option = extended_register_explicit.option,
10023 .Rm = extended_register_explicit.index.alias.encode(.{}),
10024 },
10025 } } } };
10026 },
10027 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
10028 .base = extended_register.base,
10029 .index = extended_register.index,
10030 .option = extended_register.extend,
10031 .amount = switch (extended_register.extend) {
10032 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
10033 },
10034 } },
10035 }
10036 }
10037 /// C6.2.172 LDRH (immediate)
10038 /// C6.2.173 LDRH (register)
10039 pub fn ldrh(t: Register, form: union(enum) {
10040 post_index: struct { base: Register, index: i9 },
10041 pre_index: struct { base: Register, index: i9 },
10042 unsigned_offset: struct { base: Register, offset: u13 = 0 },
10043 base: Register,
10044 extended_register_explicit: struct {
10045 base: Register,
10046 index: Register,
10047 option: LoadStore.RegisterRegisterOffset.Option,
10048 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
10049 },
10050 extended_register: struct {
10051 base: Register,
10052 index: Register,
10053 extend: LoadStore.RegisterRegisterOffset.Extend,
10054 },
10055 }) Instruction {
10056 assert(t.format.integer == .word);
10057 form: switch (form) {
10058 .post_index => |post_index| {
10059 assert(post_index.base.format.integer == .doubleword);
10060 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
10061 .ldrh = .{
10062 .Rt = t.alias.encode(.{}),
10063 .Rn = post_index.base.alias.encode(.{ .sp = true }),
10064 .imm9 = post_index.index,
10065 },
10066 } } } };
10067 },
10068 .pre_index => |pre_index| {
10069 assert(pre_index.base.format.integer == .doubleword);
10070 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
10071 .ldrh = .{
10072 .Rt = t.alias.encode(.{}),
10073 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
10074 .imm9 = pre_index.index,
10075 },
10076 } } } };
10077 },
10078 .unsigned_offset => |unsigned_offset| {
10079 assert(unsigned_offset.base.format.integer == .doubleword);
10080 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
10081 .ldrh = .{
10082 .Rt = t.alias.encode(.{}),
10083 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
10084 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 1)),
10085 },
10086 } } } };
10087 },
10088 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
10089 .extended_register_explicit => |extended_register_explicit| {
10090 assert(extended_register_explicit.base.format.integer == .doubleword and
10091 extended_register_explicit.index.format.integer == extended_register_explicit.option.sf());
10092 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
10093 .ldrh = .{
10094 .Rt = t.alias.encode(.{}),
10095 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
10096 .S = switch (extended_register_explicit.amount) {
10097 0 => false,
10098 1 => true,
10099 else => unreachable,
10100 },
10101 .option = extended_register_explicit.option,
10102 .Rm = extended_register_explicit.index.alias.encode(.{}),
10103 },
10104 } } } };
10105 },
10106 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
10107 .base = extended_register.base,
10108 .index = extended_register.index,
10109 .option = extended_register.extend,
10110 .amount = switch (extended_register.extend) {
10111 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
10112 },
10113 } },
10114 }
10115 }
10116 /// C6.2.174 LDRSB (immediate)
10117 /// C6.2.175 LDRSB (register)
10118 pub fn ldrsb(t: Register, form: union(enum) {
10119 post_index: struct { base: Register, index: i9 },
10120 pre_index: struct { base: Register, index: i9 },
10121 unsigned_offset: struct { base: Register, offset: u12 = 0 },
10122 base: Register,
10123 extended_register_explicit: struct {
10124 base: Register,
10125 index: Register,
10126 option: LoadStore.RegisterRegisterOffset.Option,
10127 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
10128 },
10129 extended_register: struct {
10130 base: Register,
10131 index: Register,
10132 extend: LoadStore.RegisterRegisterOffset.Extend,
10133 },
10134 }) Instruction {
10135 const sf = t.format.integer;
10136 form: switch (form) {
10137 .post_index => |post_index| {
10138 assert(post_index.base.format.integer == .doubleword);
10139 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
10140 .ldrsb = .{
10141 .Rt = t.alias.encode(.{}),
10142 .Rn = post_index.base.alias.encode(.{ .sp = true }),
10143 .imm9 = post_index.index,
10144 .opc0 = ~@intFromEnum(sf),
10145 },
10146 } } } };
10147 },
10148 .pre_index => |pre_index| {
10149 assert(pre_index.base.format.integer == .doubleword);
10150 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
10151 .ldrsb = .{
10152 .Rt = t.alias.encode(.{}),
10153 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
10154 .imm9 = pre_index.index,
10155 .opc0 = ~@intFromEnum(sf),
10156 },
10157 } } } };
10158 },
10159 .unsigned_offset => |unsigned_offset| {
10160 assert(unsigned_offset.base.format.integer == .doubleword);
10161 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
10162 .ldrsb = .{
10163 .Rt = t.alias.encode(.{}),
10164 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
10165 .imm12 = unsigned_offset.offset,
10166 .opc0 = ~@intFromEnum(sf),
10167 },
10168 } } } };
10169 },
10170 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
10171 .extended_register_explicit => |extended_register_explicit| {
10172 assert(extended_register_explicit.base.format.integer == .doubleword and
10173 extended_register_explicit.index.format.integer == extended_register_explicit.option.sf());
10174 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
10175 .ldrsb = .{
10176 .Rt = t.alias.encode(.{}),
10177 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
10178 .S = switch (extended_register_explicit.amount) {
10179 0 => false,
10180 else => unreachable,
10181 },
10182 .option = extended_register_explicit.option,
10183 .Rm = extended_register_explicit.index.alias.encode(.{}),
10184 .opc0 = ~@intFromEnum(sf),
10185 },
10186 } } } };
10187 },
10188 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
10189 .base = extended_register.base,
10190 .index = extended_register.index,
10191 .option = extended_register.extend,
10192 .amount = switch (extended_register.extend) {
10193 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
10194 },
10195 } },
10196 }
10197 }
10198 /// C6.2.176 LDRSH (immediate)
10199 /// C6.2.177 LDRSH (register)
10200 pub fn ldrsh(t: Register, form: union(enum) {
10201 post_index: struct { base: Register, index: i9 },
10202 pre_index: struct { base: Register, index: i9 },
10203 unsigned_offset: struct { base: Register, offset: u13 = 0 },
10204 base: Register,
10205 extended_register_explicit: struct {
10206 base: Register,
10207 index: Register,
10208 option: LoadStore.RegisterRegisterOffset.Option,
10209 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
10210 },
10211 extended_register: struct {
10212 base: Register,
10213 index: Register,
10214 extend: LoadStore.RegisterRegisterOffset.Extend,
10215 },
10216 }) Instruction {
10217 const sf = t.format.integer;
10218 form: switch (form) {
10219 .post_index => |post_index| {
10220 assert(post_index.base.format.integer == .doubleword);
10221 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
10222 .ldrsh = .{
10223 .Rt = t.alias.encode(.{}),
10224 .Rn = post_index.base.alias.encode(.{ .sp = true }),
10225 .imm9 = post_index.index,
10226 .opc0 = ~@intFromEnum(sf),
10227 },
10228 } } } };
10229 },
10230 .pre_index => |pre_index| {
10231 assert(pre_index.base.format.integer == .doubleword);
10232 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
10233 .ldrsh = .{
10234 .Rt = t.alias.encode(.{}),
10235 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
10236 .imm9 = pre_index.index,
10237 .opc0 = ~@intFromEnum(sf),
10238 },
10239 } } } };
10240 },
10241 .unsigned_offset => |unsigned_offset| {
10242 assert(unsigned_offset.base.format.integer == .doubleword);
10243 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
10244 .ldrsh = .{
10245 .Rt = t.alias.encode(.{}),
10246 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
10247 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 1)),
10248 .opc0 = ~@intFromEnum(sf),
10249 },
10250 } } } };
10251 },
10252 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
10253 .extended_register_explicit => |extended_register_explicit| {
10254 assert(extended_register_explicit.base.format.integer == .doubleword and
10255 extended_register_explicit.index.format.integer == extended_register_explicit.option.sf());
10256 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
10257 .ldrsh = .{
10258 .Rt = t.alias.encode(.{}),
10259 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
10260 .S = switch (extended_register_explicit.amount) {
10261 0 => false,
10262 1 => true,
10263 else => unreachable,
10264 },
10265 .option = extended_register_explicit.option,
10266 .Rm = extended_register_explicit.index.alias.encode(.{}),
10267 .opc0 = ~@intFromEnum(sf),
10268 },
10269 } } } };
10270 },
10271 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
10272 .base = extended_register.base,
10273 .index = extended_register.index,
10274 .option = extended_register.extend,
10275 .amount = switch (extended_register.extend) {
10276 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
10277 },
10278 } },
10279 }
10280 }
10281 /// C6.2.178 LDRSW (immediate)
10282 /// C6.2.179 LDRSW (literal)
10283 /// C6.2.180 LDRSW (register)
10284 pub fn ldrsw(t: Register, form: union(enum) {
10285 post_index: struct { base: Register, index: i9 },
10286 pre_index: struct { base: Register, index: i9 },
10287 unsigned_offset: struct { base: Register, offset: u14 = 0 },
10288 base: Register,
10289 literal: i21,
10290 extended_register_explicit: struct {
10291 base: Register,
10292 index: Register,
10293 option: LoadStore.RegisterRegisterOffset.Integer.Option,
10294 amount: LoadStore.RegisterRegisterOffset.Integer.Extend.Amount,
10295 },
10296 extended_register: struct {
10297 base: Register,
10298 index: Register,
10299 extend: LoadStore.RegisterRegisterOffset.Integer.Extend,
10300 },
10301 }) Instruction {
10302 assert(t.format.integer == .doubleword);
10303 form: switch (form) {
10304 .post_index => |post_index| {
10305 assert(post_index.base.format.integer == .doubleword);
10306 return .{ .load_store = .{ .register_immediate_post_indexed = .{
10307 .ldrsw = .{
10308 .Rt = t.alias.encode(.{}),
10309 .Rn = post_index.base.alias.encode(.{ .sp = true }),
10310 .imm9 = post_index.index,
10311 },
10312 } } };
10313 },
10314 .pre_index => |pre_index| {
10315 assert(pre_index.base.format.integer == .doubleword);
10316 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
10317 .ldrsw = .{
10318 .Rt = t.alias.encode(.{}),
10319 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
10320 .imm9 = pre_index.index,
10321 },
10322 } } } };
10323 },
10324 .unsigned_offset => |unsigned_offset| {
10325 assert(unsigned_offset.base.format.integer == .doubleword);
10326 return .{ .load_store = .{ .register_unsigned_immediate = .{
10327 .ldrsw = .{
10328 .Rt = t.alias.encode(.{}),
10329 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
10330 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 2)),
10331 },
10332 } } };
10333 },
10334 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
10335 .literal => |offset| return .{ .load_store = .{ .register_literal = .{
10336 .ldrsw = .{
10337 .Rt = t.alias.encode(.{}),
10338 .imm19 = @intCast(@shrExact(offset, 2)),
10339 },
10340 } } },
10341 .extended_register_explicit => |extended_register_explicit| {
10342 assert(extended_register_explicit.base.format.integer == .doubleword and
10343 extended_register_explicit.index.format.integer == extended_register_explicit.option.sf());
10344 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
10345 .ldrsw = .{
10346 .Rt = t.alias.encode(.{}),
10347 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
10348 .S = switch (extended_register_explicit.amount) {
10349 0 => 0b0,
10350 2 => 0b1,
10351 else => unreachable,
10352 },
10353 .option = extended_register_explicit.option,
10354 .Rm = extended_register_explicit.index.alias.encode(.{}),
10355 },
10356 } } } };
10357 },
10358 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
10359 .base = extended_register.base,
10360 .index = extended_register.index,
10361 .option = extended_register.extend,
10362 .amount = switch (extended_register.extend) {
10363 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
10364 },
10365 } },
10366 }
10367 }
10368 /// C6.2.202 LDUR
10369 /// C7.2.194 LDUR (SIMD&FP)
10370 pub fn ldur(t: Register, n: Register, simm: i9) Instruction {
10371 assert(n.format.integer == .doubleword);
10372 switch (t.format) {
10373 else => unreachable,
10374 .integer => |sf| return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
10375 .ldur = .{
10376 .Rt = t.alias.encode(.{}),
10377 .Rn = n.alias.encode(.{ .sp = true }),
10378 .imm9 = simm,
10379 .sf = sf,
10380 },
10381 } } } },
10382 .scalar => |vs| return .{ .load_store = .{ .register_unscaled_immediate = .{ .vector = .{
10383 .ldur = .{
10384 .Rt = t.alias.encode(.{ .V = true }),
10385 .Rn = n.alias.encode(.{ .sp = true }),
10386 .imm9 = simm,
10387 .opc1 = .encode(vs),
10388 .size = .encode(vs),
10389 },
10390 } } } },
10391 }
10392 }
10393 /// C6.2.203 LDURB
10394 pub fn ldurb(t: Register, n: Register, simm: i9) Instruction {
10395 assert(t.format.integer == .word and n.format.integer == .doubleword);
10396 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
10397 .ldurb = .{
10398 .Rt = t.alias.encode(.{}),
10399 .Rn = n.alias.encode(.{ .sp = true }),
10400 .imm9 = simm,
10401 },
10402 } } } };
10403 }
10404 /// C6.2.204 LDURH
10405 pub fn ldurh(t: Register, n: Register, simm: i9) Instruction {
10406 assert(t.format.integer == .word and n.format.integer == .doubleword);
10407 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
10408 .ldurh = .{
10409 .Rt = t.alias.encode(.{}),
10410 .Rn = n.alias.encode(.{ .sp = true }),
10411 .imm9 = simm,
10412 },
10413 } } } };
10414 }
10415 /// C6.2.205 LDURSB
10416 pub fn ldursb(t: Register, n: Register, simm: i9) Instruction {
10417 assert(n.format.integer == .doubleword);
10418 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
10419 .ldursb = .{
10420 .Rt = t.alias.encode(.{}),
10421 .Rn = n.alias.encode(.{ .sp = true }),
10422 .imm9 = simm,
10423 .opc0 = ~@intFromEnum(t.format.integer),
10424 },
10425 } } } };
10426 }
10427 /// C6.2.206 LDURSH
10428 pub fn ldursh(t: Register, n: Register, simm: i9) Instruction {
10429 assert(n.format.integer == .doubleword);
10430 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
10431 .ldursh = .{
10432 .Rt = t.alias.encode(.{}),
10433 .Rn = n.alias.encode(.{ .sp = true }),
10434 .imm9 = simm,
10435 .opc0 = ~@intFromEnum(t.format.integer),
10436 },
10437 } } } };
10438 }
10439 /// C6.2.207 LDURSW
10440 pub fn ldursw(t: Register, n: Register, simm: i9) Instruction {
10441 assert(t.format.integer == .doubleword and n.format.integer == .doubleword);
10442 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
10443 .ldursw = .{
10444 .Rt = t.alias.encode(.{}),
10445 .Rn = n.alias.encode(.{ .sp = true }),
10446 .imm9 = simm,
10447 },
10448 } } } };
10449 }
10450 /// C6.2.214 LSLV
10451 pub fn lslv(d: Register, n: Register, m: Register) Instruction {
10452 const sf = d.format.integer;
10453 assert(n.format.integer == sf and m.format.integer == sf);
10454 return .{ .data_processing_register = .{ .data_processing_two_source = .{
10455 .lslv = .{
10456 .Rd = d.alias.encode(.{}),
10457 .Rn = n.alias.encode(.{}),
10458 .Rm = m.alias.encode(.{}),
10459 .sf = sf,
10460 },
10461 } } };
10462 }
10463 /// C6.2.217 LSRV
10464 pub fn lsrv(d: Register, n: Register, m: Register) Instruction {
10465 const sf = d.format.integer;
10466 assert(n.format.integer == sf and m.format.integer == sf);
10467 return .{ .data_processing_register = .{ .data_processing_two_source = .{
10468 .lsrv = .{
10469 .Rd = d.alias.encode(.{}),
10470 .Rn = n.alias.encode(.{}),
10471 .Rm = m.alias.encode(.{}),
10472 .sf = sf,
10473 },
10474 } } };
10475 }
10476 /// C6.2.218 MADD
10477 pub fn madd(d: Register, n: Register, m: Register, a: Register) Instruction {
10478 const sf = d.format.integer;
10479 assert(n.format.integer == sf and m.format.integer == sf and a.format.integer == sf);
10480 return .{ .data_processing_register = .{ .data_processing_three_source = .{
10481 .madd = .{
10482 .Rd = d.alias.encode(.{}),
10483 .Rn = n.alias.encode(.{}),
10484 .Ra = a.alias.encode(.{}),
10485 .Rm = m.alias.encode(.{}),
10486 .sf = sf,
10487 },
10488 } } };
10489 }
10490 /// C7.2.204 MOVI
10491 pub fn movi(d: Register, imm8: u8, shift: union(enum) { lsl: u5, msl: u5, replicate }) Instruction {
10492 const arrangement = switch (d.format) {
10493 else => unreachable,
10494 .scalar => |vs| switch (vs) {
10495 else => unreachable,
10496 .double => .@"1d",
10497 },
10498 .vector => |arrangement| switch (arrangement) {
10499 .@"1d" => unreachable,
10500 else => arrangement,
10501 },
10502 };
10503 return .{ .data_processing_vector = .{ .simd_modified_immediate = .{
10504 .movi = .{
10505 .Rd = d.alias.encode(.{ .V = true }),
10506 .imm5 = @truncate(imm8 >> 0),
10507 .cmode = switch (shift) {
10508 .lsl => |amount| switch (arrangement) {
10509 else => unreachable,
10510 .@"8b", .@"16b" => @as(u4, 0b1110) |
10511 @as(u4, @as(u0, @intCast(@shrExact(amount, 3)))) << 1,
10512 .@"4h", .@"8h" => @as(u4, 0b1000) |
10513 @as(u4, @as(u1, @intCast(@shrExact(amount, 3)))) << 1,
10514 .@"2s", .@"4s" => @as(u4, 0b0000) |
10515 @as(u4, @as(u2, @intCast(@shrExact(amount, 3)))) << 1,
10516 },
10517 .msl => |amount| switch (arrangement) {
10518 else => unreachable,
10519 .@"2s", .@"4s" => @as(u4, 0b1100) |
10520 @as(u4, @as(u1, @intCast(@shrExact(amount, 3) - 1))) << 0,
10521 },
10522 .replicate => switch (arrangement) {
10523 else => unreachable,
10524 .@"1d", .@"2d" => 0b1110,
10525 },
10526 },
10527 .imm3 = @intCast(imm8 >> 5),
10528 .op = switch (shift) {
10529 .lsl, .msl => 0b0,
10530 .replicate => 0b1,
10531 },
10532 .Q = arrangement.size(),
10533 },
10534 } } };
10535 }
10536 /// C6.2.225 MOVK
10537 pub fn movk(
10538 d: Register,
10539 imm: u16,
10540 shift: struct { lsl: DataProcessingImmediate.MoveWideImmediate.Hw = .@"0" },
10541 ) Instruction {
10542 const sf = d.format.integer;
10543 assert(sf == .doubleword or shift.lsl.sf() == .word);
10544 return .{ .data_processing_immediate = .{ .move_wide_immediate = .{
10545 .movk = .{
10546 .Rd = d.alias.encode(.{}),
10547 .imm16 = imm,
10548 .hw = shift.lsl,
10549 .sf = sf,
10550 },
10551 } } };
10552 }
10553 /// C6.2.226 MOVN
10554 pub fn movn(
10555 d: Register,
10556 imm: u16,
10557 shift: struct { lsl: DataProcessingImmediate.MoveWideImmediate.Hw = .@"0" },
10558 ) Instruction {
10559 const sf = d.format.integer;
10560 assert(sf == .doubleword or shift.lsl.sf() == .word);
10561 return .{ .data_processing_immediate = .{ .move_wide_immediate = .{
10562 .movn = .{
10563 .Rd = d.alias.encode(.{}),
10564 .imm16 = imm,
10565 .hw = shift.lsl,
10566 .sf = sf,
10567 },
10568 } } };
10569 }
10570 /// C6.2.227 MOVZ
10571 pub fn movz(
10572 d: Register,
10573 imm: u16,
10574 shift: struct { lsl: DataProcessingImmediate.MoveWideImmediate.Hw = .@"0" },
10575 ) Instruction {
10576 const sf = d.format.integer;
10577 assert(sf == .doubleword or shift.lsl.sf() == .word);
10578 return .{ .data_processing_immediate = .{ .move_wide_immediate = .{
10579 .movz = .{
10580 .Rd = d.alias.encode(.{}),
10581 .imm16 = imm,
10582 .hw = shift.lsl,
10583 .sf = sf,
10584 },
10585 } } };
10586 }
10587 /// C6.2.228 MRS
10588 pub fn mrs(t: Register, op0: u2, op1: u3, n: u4, m: u4, op2: u3) Instruction {
10589 assert(t.format.integer == .doubleword);
10590 return .{ .branch_exception_generating_system = .{ .system_register_move = .{
10591 .mrs = .{
10592 .Rt = t.alias.encode(.{}),
10593 .op2 = op2,
10594 .CRm = m,
10595 .CRn = n,
10596 .op1 = op1,
10597 .o0 = @intCast(op0 - 0b10),
10598 },
10599 } } };
10600 }
10601 /// C6.2.230 MSR (register)
10602 pub fn msr(op0: u2, op1: u3, n: u4, m: u4, op2: u3, t: Register) Instruction {
10603 assert(t.format.integer == .doubleword);
10604 return .{ .branch_exception_generating_system = .{ .system_register_move = .{
10605 .msr = .{
10606 .Rt = t.alias.encode(.{}),
10607 .op2 = op2,
10608 .CRm = m,
10609 .CRn = n,
10610 .op1 = op1,
10611 .o0 = @intCast(op0 - 0b10),
10612 },
10613 } } };
10614 }
10615 /// C6.2.231 MSUB
10616 pub fn msub(d: Register, n: Register, m: Register, a: Register) Instruction {
10617 const sf = d.format.integer;
10618 assert(n.format.integer == sf and m.format.integer == sf and a.format.integer == sf);
10619 return .{ .data_processing_register = .{ .data_processing_three_source = .{
10620 .msub = .{
10621 .Rd = d.alias.encode(.{}),
10622 .Rn = n.alias.encode(.{}),
10623 .Ra = a.alias.encode(.{}),
10624 .Rm = m.alias.encode(.{}),
10625 .sf = sf,
10626 },
10627 } } };
10628 }
10629 /// C6.2.238 NOP
10630 pub fn nop() Instruction {
10631 return .{ .branch_exception_generating_system = .{ .hints = .{
10632 .nop = .{},
10633 } } };
10634 }
10635 /// C6.2.239 ORN (shifted register)
10636 /// C7.2.211 ORN (vector)
10637 pub fn orn(d: Register, n: Register, form: union(enum) {
10638 register: Register,
10639 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
10640 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
10641 }) Instruction {
10642 switch (d.format) {
10643 else => unreachable,
10644 .integer => |sf| {
10645 assert(n.format.integer == sf);
10646 form: switch (form) {
10647 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
10648 .shifted_register_explicit => |shifted_register_explicit| {
10649 assert(shifted_register_explicit.register.format.integer == sf);
10650 return .{ .data_processing_register = .{ .logical_shifted_register = .{
10651 .orn = .{
10652 .Rd = d.alias.encode(.{}),
10653 .Rn = n.alias.encode(.{}),
10654 .imm6 = switch (sf) {
10655 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
10656 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
10657 },
10658 .Rm = shifted_register_explicit.register.alias.encode(.{}),
10659 .shift = shifted_register_explicit.shift,
10660 .sf = sf,
10661 },
10662 } } };
10663 },
10664 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
10665 .register = shifted_register.register,
10666 .shift = shifted_register.shift,
10667 .amount = switch (shifted_register.shift) {
10668 .lsl, .lsr, .asr, .ror => |amount| amount,
10669 },
10670 } },
10671 }
10672 },
10673 .vector => |arrangement| {
10674 const m = form.register;
10675 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
10676 return .{ .data_processing_vector = .{ .simd_three_same = .{
10677 .orn = .{
10678 .Rd = d.alias.encode(.{ .V = true }),
10679 .Rn = n.alias.encode(.{ .V = true }),
10680 .Rm = m.alias.encode(.{ .V = true }),
10681 .Q = arrangement.size(),
10682 },
10683 } } };
10684 },
10685 }
10686 }
10687 /// C6.2.240 ORR (immediate)
10688 /// C6.2.241 ORR (shifted register)
10689 /// C7.2.212 ORR (vector, immediate)
10690 /// C7.2.213 ORR (vector, register)
10691 pub fn orr(d: Register, n: Register, form: union(enum) {
10692 immediate: DataProcessingImmediate.Bitmask,
10693 shifted_immediate: struct { immediate: u8, lsl: u5 = 0 },
10694 register: Register,
10695 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
10696 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
10697 }) Instruction {
10698 switch (d.format) {
10699 else => unreachable,
10700 .integer => |sf| {
10701 assert(n.format.integer == sf);
10702 form: switch (form) {
10703 .immediate => |bitmask| {
10704 assert(bitmask.validImmediate(sf));
10705 return .{ .data_processing_immediate = .{ .logical_immediate = .{
10706 .orr = .{
10707 .Rd = d.alias.encode(.{ .sp = true }),
10708 .Rn = n.alias.encode(.{}),
10709 .imm = bitmask,
10710 .sf = sf,
10711 },
10712 } } };
10713 },
10714 .shifted_immediate => unreachable,
10715 .register => |register| continue :form .{ .shifted_register = .{ .register = register } },
10716 .shifted_register_explicit => |shifted_register_explicit| {
10717 assert(shifted_register_explicit.register.format.integer == sf);
10718 return .{ .data_processing_register = .{ .logical_shifted_register = .{
10719 .orr = .{
10720 .Rd = d.alias.encode(.{}),
10721 .Rn = n.alias.encode(.{}),
10722 .imm6 = switch (sf) {
10723 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
10724 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
10725 },
10726 .Rm = shifted_register_explicit.register.alias.encode(.{}),
10727 .shift = shifted_register_explicit.shift,
10728 .sf = sf,
10729 },
10730 } } };
10731 },
10732 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
10733 .register = shifted_register.register,
10734 .shift = shifted_register.shift,
10735 .amount = switch (shifted_register.shift) {
10736 .lsl, .lsr, .asr, .ror => |amount| amount,
10737 },
10738 } },
10739 }
10740 },
10741 .vector => |arrangement| switch (form) {
10742 else => unreachable,
10743 .shifted_immediate => |shifted_immediate| {
10744 assert(n.alias == d.alias and n.format.vector == arrangement);
10745 return .{ .data_processing_vector = .{ .simd_modified_immediate = .{
10746 .orr = .{
10747 .Rd = d.alias.encode(.{ .V = true }),
10748 .imm5 = @truncate(shifted_immediate.immediate >> 0),
10749 .cmode = switch (arrangement) {
10750 else => unreachable,
10751 .@"4h", .@"8h" => @as(u3, 0b100) |
10752 @as(u3, @as(u1, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0,
10753 .@"2s", .@"4s" => @as(u3, 0b000) |
10754 @as(u3, @as(u2, @intCast(@shrExact(shifted_immediate.lsl, 3)))) << 0,
10755 },
10756 .imm3 = @intCast(shifted_immediate.immediate >> 5),
10757 .Q = arrangement.size(),
10758 },
10759 } } };
10760 },
10761 .register => |m| {
10762 assert(arrangement.elemSize() == .byte and n.format.vector == arrangement and m.format.vector == arrangement);
10763 return .{ .data_processing_vector = .{ .simd_three_same = .{
10764 .orr = .{
10765 .Rd = d.alias.encode(.{ .V = true }),
10766 .Rn = n.alias.encode(.{ .V = true }),
10767 .Rm = m.alias.encode(.{ .V = true }),
10768 .Q = arrangement.size(),
10769 },
10770 } } };
10771 },
10772 },
10773 }
10774 }
10775 /// C6.2.247 PRFM (immediate)
10776 /// C6.2.248 PRFM (literal)
10777 /// C6.2.249 PRFM (register)
10778 pub fn prfm(prfop: LoadStore.PrfOp, form: union(enum) {
10779 unsigned_offset: struct { base: Register, offset: u15 = 0 },
10780 base: Register,
10781 literal: i21,
10782 extended_register_explicit: struct {
10783 base: Register,
10784 index: Register,
10785 option: LoadStore.RegisterRegisterOffset.Option,
10786 amount: LoadStore.RegisterRegisterOffset.Extend.Amount,
10787 },
10788 extended_register: struct {
10789 base: Register,
10790 index: Register,
10791 extend: LoadStore.RegisterRegisterOffset.Extend,
10792 },
10793 }) Instruction {
10794 form: switch (form) {
10795 .unsigned_offset => |unsigned_offset| {
10796 assert(unsigned_offset.base.format.integer == .doubleword);
10797 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
10798 .prfm = .{
10799 .prfop = prfop,
10800 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
10801 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 3)),
10802 },
10803 } } } };
10804 },
10805 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
10806 .literal => |offset| return .{ .load_store = .{ .register_literal = .{ .integer = .{
10807 .prfm = .{
10808 .prfop = prfop,
10809 .imm19 = @intCast(@shrExact(offset, 2)),
10810 },
10811 } } } },
10812 .extended_register_explicit => |extended_register_explicit| {
10813 assert(extended_register_explicit.base.format.integer == .doubleword and
10814 extended_register_explicit.index.format.integer == extended_register_explicit.option.sf());
10815 return .{ .load_store = .{ .register_register_offset = .{ .integer = .{
10816 .prfm = .{
10817 .prfop = prfop,
10818 .Rn = extended_register_explicit.base.alias.encode(.{ .sp = true }),
10819 .S = switch (extended_register_explicit.amount) {
10820 0 => false,
10821 3 => true,
10822 else => unreachable,
10823 },
10824 .option = extended_register_explicit.option,
10825 .Rm = extended_register_explicit.index.alias.encode(.{}),
10826 },
10827 } } } };
10828 },
10829 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
10830 .base = extended_register.base,
10831 .index = extended_register.index,
10832 .option = extended_register.extend,
10833 .amount = switch (extended_register.extend) {
10834 .uxtw, .lsl, .sxtw, .sxtx => |amount| amount,
10835 },
10836 } },
10837 }
10838 }
10839 /// C6.2.253 RBIT
10840 pub fn rbit(d: Register, n: Register) Instruction {
10841 const sf = d.format.integer;
10842 assert(n.format.integer == sf);
10843 return .{ .data_processing_register = .{ .data_processing_one_source = .{
10844 .rbit = .{
10845 .Rd = d.alias.encode(.{}),
10846 .Rn = n.alias.encode(.{}),
10847 .sf = sf,
10848 },
10849 } } };
10850 }
10851 /// C6.2.254 RET
10852 pub fn ret(n: Register) Instruction {
10853 assert(n.format.integer == .doubleword);
10854 return .{ .branch_exception_generating_system = .{ .unconditional_branch_register = .{
10855 .ret = .{ .Rn = n.alias.encode(.{}) },
10856 } } };
10857 }
10858 /// C6.2.256 REV
10859 pub fn rev(d: Register, n: Register) Instruction {
10860 const sf = d.format.integer;
10861 assert(n.format.integer == sf);
10862 return .{ .data_processing_register = .{ .data_processing_one_source = .{
10863 .rev = .{
10864 .Rd = d.alias.encode(.{}),
10865 .Rn = n.alias.encode(.{}),
10866 .opc0 = sf,
10867 .sf = sf,
10868 },
10869 } } };
10870 }
10871 /// C6.2.257 REV16
10872 pub fn rev16(d: Register, n: Register) Instruction {
10873 const sf = d.format.integer;
10874 assert(n.format.integer == sf);
10875 return .{ .data_processing_register = .{ .data_processing_one_source = .{
10876 .rev16 = .{
10877 .Rd = d.alias.encode(.{}),
10878 .Rn = n.alias.encode(.{}),
10879 .sf = sf,
10880 },
10881 } } };
10882 }
10883 /// C6.2.258 REV32
10884 pub fn rev32(d: Register, n: Register) Instruction {
10885 assert(d.format.integer == .doubleword and n.format.integer == .doubleword);
10886 return .{ .data_processing_register = .{ .data_processing_one_source = .{
10887 .rev32 = .{
10888 .Rd = d.alias.encode(.{}),
10889 .Rn = n.alias.encode(.{}),
10890 },
10891 } } };
10892 }
10893 /// C6.2.263 RORV
10894 pub fn rorv(d: Register, n: Register, m: Register) Instruction {
10895 const sf = d.format.integer;
10896 assert(n.format.integer == sf and m.format.integer == sf);
10897 return .{ .data_processing_register = .{ .data_processing_two_source = .{
10898 .rorv = .{
10899 .Rd = d.alias.encode(.{}),
10900 .Rn = n.alias.encode(.{}),
10901 .Rm = m.alias.encode(.{}),
10902 .sf = sf,
10903 },
10904 } } };
10905 }
10906 /// C6.2.264 SB
10907 pub fn sb() Instruction {
10908 return .{ .branch_exception_generating_system = .{ .barriers = .{
10909 .sb = .{},
10910 } } };
10911 }
10912 /// C6.2.265 SBC
10913 pub fn sbc(d: Register, n: Register, m: Register) Instruction {
10914 const sf = d.format.integer;
10915 assert(n.format.integer == sf and m.format.integer == sf);
10916 return .{ .data_processing_register = .{ .add_subtract_with_carry = .{
10917 .sbc = .{
10918 .Rd = d.alias.encode(.{}),
10919 .Rn = n.alias.encode(.{}),
10920 .Rm = m.alias.encode(.{}),
10921 .sf = sf,
10922 },
10923 } } };
10924 }
10925 /// C6.2.266 SBCS
10926 pub fn sbcs(d: Register, n: Register, m: Register) Instruction {
10927 const sf = d.format.integer;
10928 assert(n.format.integer == sf and m.format.integer == sf);
10929 return .{ .data_processing_register = .{ .add_subtract_with_carry = .{
10930 .sbcs = .{
10931 .Rd = d.alias.encode(.{}),
10932 .Rn = n.alias.encode(.{}),
10933 .Rm = m.alias.encode(.{}),
10934 .sf = sf,
10935 },
10936 } } };
10937 }
10938 /// C6.2.268 SBFM
10939 pub fn sbfm(d: Register, n: Register, bitmask: DataProcessingImmediate.Bitmask) Instruction {
10940 const sf = d.format.integer;
10941 assert(n.format.integer == sf and bitmask.validBitfield(sf));
10942 return .{ .data_processing_immediate = .{ .bitfield = .{
10943 .sbfm = .{
10944 .Rd = d.alias.encode(.{}),
10945 .Rn = n.alias.encode(.{}),
10946 .imm = bitmask,
10947 .sf = sf,
10948 },
10949 } } };
10950 }
10951 /// C7.2.236 SCVTF (scalar, integer)
10952 pub fn scvtf(d: Register, n: Register) Instruction {
10953 return .{ .data_processing_vector = .{ .convert_float_integer = .{
10954 .scvtf = .{
10955 .Rd = d.alias.encode(.{ .V = true }),
10956 .Rn = n.alias.encode(.{}),
10957 .ftype = switch (d.format.scalar) {
10958 else => unreachable,
10959 .single => .single,
10960 .double => .double,
10961 .half => .half,
10962 },
10963 .sf = n.format.integer,
10964 },
10965 } } };
10966 }
10967 /// C6.2.270 SDIV
10968 pub fn sdiv(d: Register, n: Register, m: Register) Instruction {
10969 const sf = d.format.integer;
10970 assert(n.format.integer == sf and m.format.integer == sf);
10971 return .{ .data_processing_register = .{ .data_processing_two_source = .{
10972 .sdiv = .{
10973 .Rd = d.alias.encode(.{}),
10974 .Rn = n.alias.encode(.{}),
10975 .Rm = m.alias.encode(.{}),
10976 .sf = sf,
10977 },
10978 } } };
10979 }
10980 /// C6.2.280 SEV
10981 pub fn sev() Instruction {
10982 return .{ .branch_exception_generating_system = .{ .hints = .{
10983 .sev = .{},
10984 } } };
10985 }
10986 /// C6.2.281 SEVL
10987 pub fn sevl() Instruction {
10988 return .{ .branch_exception_generating_system = .{ .hints = .{
10989 .sevl = .{},
10990 } } };
10991 }
10992 /// C6.2.282 SMADDL
10993 pub fn smaddl(d: Register, n: Register, m: Register, a: Register) Instruction {
10994 assert(d.format.integer == .doubleword and n.format.integer == .word and m.format.integer == .word and a.format.integer == .doubleword);
10995 return .{ .data_processing_register = .{ .data_processing_three_source = .{
10996 .smaddl = .{
10997 .Rd = d.alias.encode(.{}),
10998 .Rn = n.alias.encode(.{}),
10999 .Ra = a.alias.encode(.{}),
11000 .Rm = m.alias.encode(.{}),
11001 },
11002 } } };
11003 }
11004 /// C6.2.283 SMC
11005 pub fn smc(imm: u16) Instruction {
11006 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
11007 .smc = .{ .imm16 = imm },
11008 } } };
11009 }
11010 /// C7.2.279 SMOV
11011 pub fn smov(d: Register, n: Register) Instruction {
11012 const sf = d.format.integer;
11013 const vs = n.format.element.size;
11014 switch (vs) {
11015 else => unreachable,
11016 .byte, .half => {},
11017 .single => assert(sf == .doubleword),
11018 }
11019 return .{ .data_processing_vector = .{ .simd_copy = .{
11020 .smov = .{
11021 .Rd = d.alias.encode(.{}),
11022 .Rn = n.alias.encode(.{ .V = true }),
11023 .imm5 = switch (vs) {
11024 else => unreachable,
11025 .byte => @as(u5, @as(u4, @intCast(n.format.element.index))) << 1 | @as(u5, 0b1) << 0,
11026 .half => @as(u5, @as(u3, @intCast(n.format.element.index))) << 2 | @as(u5, 0b10) << 0,
11027 .single => @as(u5, @as(u2, @intCast(n.format.element.index))) << 3 | @as(u5, 0b100) << 0,
11028 },
11029 .Q = sf,
11030 },
11031 } } };
11032 }
11033 /// C6.2.287 SMSUBL
11034 pub fn smsubl(d: Register, n: Register, m: Register, a: Register) Instruction {
11035 assert(d.format.integer == .doubleword and n.format.integer == .word and m.format.integer == .word and a.format.integer == .doubleword);
11036 return .{ .data_processing_register = .{ .data_processing_three_source = .{
11037 .smsubl = .{
11038 .Rd = d.alias.encode(.{}),
11039 .Rn = n.alias.encode(.{}),
11040 .Ra = a.alias.encode(.{}),
11041 .Rm = m.alias.encode(.{}),
11042 },
11043 } } };
11044 }
11045 /// C6.2.288 SMULH
11046 pub fn smulh(d: Register, n: Register, m: Register) Instruction {
11047 assert(d.format.integer == .doubleword and n.format.integer == .doubleword and m.format.integer == .doubleword);
11048 return .{ .data_processing_register = .{ .data_processing_three_source = .{
11049 .smulh = .{
11050 .Rd = d.alias.encode(.{}),
11051 .Rn = n.alias.encode(.{}),
11052 .Rm = m.alias.encode(.{}),
11053 },
11054 } } };
11055 }
11056 /// C6.2.321 STP
11057 /// C7.2.330 STP (SIMD&FP)
11058 pub fn stp(t1: Register, t2: Register, form: union(enum) {
11059 post_index: struct { base: Register, index: i10 },
11060 pre_index: struct { base: Register, index: i10 },
11061 signed_offset: struct { base: Register, offset: i10 = 0 },
11062 base: Register,
11063 }) Instruction {
11064 switch (t1.format) {
11065 else => unreachable,
11066 .integer => |sf| {
11067 assert(t2.format.integer == sf);
11068 form: switch (form) {
11069 .post_index => |post_index| {
11070 assert(post_index.base.format.integer == .doubleword);
11071 return .{ .load_store = .{ .register_pair_post_indexed = .{ .integer = .{
11072 .stp = .{
11073 .Rt = t1.alias.encode(.{}),
11074 .Rn = post_index.base.alias.encode(.{ .sp = true }),
11075 .Rt2 = t2.alias.encode(.{}),
11076 .imm7 = @intCast(@shrExact(post_index.index, @as(u2, 2) + @intFromEnum(sf))),
11077 .sf = sf,
11078 },
11079 } } } };
11080 },
11081 .signed_offset => |signed_offset| {
11082 assert(signed_offset.base.format.integer == .doubleword);
11083 return .{ .load_store = .{ .register_pair_offset = .{ .integer = .{
11084 .stp = .{
11085 .Rt = t1.alias.encode(.{}),
11086 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
11087 .Rt2 = t2.alias.encode(.{}),
11088 .imm7 = @intCast(@shrExact(signed_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
11089 .sf = sf,
11090 },
11091 } } } };
11092 },
11093 .pre_index => |pre_index| {
11094 assert(pre_index.base.format.integer == .doubleword);
11095 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .integer = .{
11096 .stp = .{
11097 .Rt = t1.alias.encode(.{}),
11098 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
11099 .Rt2 = t2.alias.encode(.{}),
11100 .imm7 = @intCast(@shrExact(pre_index.index, @as(u2, 2) + @intFromEnum(sf))),
11101 .sf = sf,
11102 },
11103 } } } };
11104 },
11105 .base => |base| continue :form .{ .signed_offset = .{ .base = base } },
11106 }
11107 },
11108 .scalar => |vs| {
11109 assert(t2.format.scalar == vs);
11110 form: switch (form) {
11111 .post_index => |post_index| {
11112 assert(post_index.base.format.integer == .doubleword);
11113 return .{ .load_store = .{ .register_pair_post_indexed = .{ .vector = .{
11114 .stp = .{
11115 .Rt = t1.alias.encode(.{ .V = true }),
11116 .Rn = post_index.base.alias.encode(.{ .sp = true }),
11117 .Rt2 = t2.alias.encode(.{ .V = true }),
11118 .imm7 = @intCast(@shrExact(post_index.index, @intFromEnum(vs))),
11119 .opc = .encode(vs),
11120 },
11121 } } } };
11122 },
11123 .signed_offset => |signed_offset| {
11124 assert(signed_offset.base.format.integer == .doubleword);
11125 return .{ .load_store = .{ .register_pair_offset = .{ .vector = .{
11126 .stp = .{
11127 .Rt = t1.alias.encode(.{ .V = true }),
11128 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
11129 .Rt2 = t2.alias.encode(.{ .V = true }),
11130 .imm7 = @intCast(@shrExact(signed_offset.offset, @intFromEnum(vs))),
11131 .opc = .encode(vs),
11132 },
11133 } } } };
11134 },
11135 .pre_index => |pre_index| {
11136 assert(pre_index.base.format.integer == .doubleword);
11137 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .vector = .{
11138 .stp = .{
11139 .Rt = t1.alias.encode(.{ .V = true }),
11140 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
11141 .Rt2 = t2.alias.encode(.{ .V = true }),
11142 .imm7 = @intCast(@shrExact(pre_index.index, @intFromEnum(vs))),
11143 .opc = .encode(vs),
11144 },
11145 } } } };
11146 },
11147 .base => |base| continue :form .{ .signed_offset = .{ .base = base } },
11148 }
11149 },
11150 }
11151 }
11152 /// C6.2.322 STR (immediate)
11153 /// C7.2.331 STR (immediate, SIMD&FP)
11154 pub fn str(t: Register, form: union(enum) {
11155 post_index: struct { base: Register, index: i9 },
11156 pre_index: struct { base: Register, index: i9 },
11157 unsigned_offset: struct { base: Register, offset: u16 = 0 },
11158 base: Register,
11159 }) Instruction {
11160 switch (t.format) {
11161 else => unreachable,
11162 .integer => |sf| form: switch (form) {
11163 .post_index => |post_index| {
11164 assert(post_index.base.format.integer == .doubleword);
11165 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
11166 .str = .{
11167 .Rt = t.alias.encode(.{}),
11168 .Rn = post_index.base.alias.encode(.{ .sp = true }),
11169 .imm9 = post_index.index,
11170 .sf = sf,
11171 },
11172 } } } };
11173 },
11174 .pre_index => |pre_index| {
11175 assert(pre_index.base.format.integer == .doubleword);
11176 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
11177 .str = .{
11178 .Rt = t.alias.encode(.{}),
11179 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
11180 .imm9 = pre_index.index,
11181 .sf = sf,
11182 },
11183 } } } };
11184 },
11185 .unsigned_offset => |unsigned_offset| {
11186 assert(unsigned_offset.base.format.integer == .doubleword);
11187 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
11188 .str = .{
11189 .Rt = t.alias.encode(.{}),
11190 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
11191 .imm12 = @intCast(@shrExact(unsigned_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
11192 .sf = sf,
11193 },
11194 } } } };
11195 },
11196 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
11197 },
11198 .scalar => |vs| form: switch (form) {
11199 .post_index => |post_index| {
11200 assert(post_index.base.format.integer == .doubleword);
11201 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .vector = .{
11202 .str = .{
11203 .Rt = t.alias.encode(.{ .V = true }),
11204 .Rn = post_index.base.alias.encode(.{ .sp = true }),
11205 .imm9 = post_index.index,
11206 .opc1 = .encode(vs),
11207 .size = .encode(vs),
11208 },
11209 } } } };
11210 },
11211 .pre_index => |pre_index| {
11212 assert(pre_index.base.format.integer == .doubleword);
11213 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .vector = .{
11214 .str = .{
11215 .Rt = t.alias.encode(.{ .V = true }),
11216 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
11217 .imm9 = pre_index.index,
11218 .opc1 = .encode(vs),
11219 .size = .encode(vs),
11220 },
11221 } } } };
11222 },
11223 .unsigned_offset => |unsigned_offset| {
11224 assert(unsigned_offset.base.format.integer == .doubleword);
11225 return .{ .load_store = .{ .register_unsigned_immediate = .{ .vector = .{
11226 .str = .{
11227 .Rt = t.alias.encode(.{ .V = true }),
11228 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
11229 .imm12 = @intCast(@shrExact(unsigned_offset.offset, @intFromEnum(vs))),
11230 .opc1 = .encode(vs),
11231 .size = .encode(vs),
11232 },
11233 } } } };
11234 },
11235 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
11236 },
11237 }
11238 }
11239 /// C6.2.324 STRB (immediate)
11240 pub fn strb(t: Register, form: union(enum) {
11241 post_index: struct { base: Register, index: i9 },
11242 pre_index: struct { base: Register, index: i9 },
11243 unsigned_offset: struct { base: Register, offset: u12 = 0 },
11244 base: Register,
11245 }) Instruction {
11246 assert(t.format.integer == .word);
11247 form: switch (form) {
11248 .post_index => |post_index| {
11249 assert(post_index.base.format.integer == .doubleword);
11250 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
11251 .strb = .{
11252 .Rt = t.alias.encode(.{}),
11253 .Rn = post_index.base.alias.encode(.{ .sp = true }),
11254 .imm9 = post_index.index,
11255 },
11256 } } } };
11257 },
11258 .pre_index => |pre_index| {
11259 assert(pre_index.base.format.integer == .doubleword);
11260 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
11261 .strb = .{
11262 .Rt = t.alias.encode(.{}),
11263 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
11264 .imm9 = pre_index.index,
11265 },
11266 } } } };
11267 },
11268 .unsigned_offset => |unsigned_offset| {
11269 assert(unsigned_offset.base.format.integer == .doubleword);
11270 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
11271 .strb = .{
11272 .Rt = t.alias.encode(.{}),
11273 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
11274 .imm12 = unsigned_offset.offset,
11275 },
11276 } } } };
11277 },
11278 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
11279 }
11280 }
11281 /// C6.2.326 STRH (immediate)
11282 pub fn strh(t: Register, form: union(enum) {
11283 post_index: struct { base: Register, index: i9 },
11284 pre_index: struct { base: Register, index: i9 },
11285 unsigned_offset: struct { base: Register, offset: u13 = 0 },
11286 base: Register,
11287 }) Instruction {
11288 assert(t.format.integer == .word);
11289 form: switch (form) {
11290 .post_index => |post_index| {
11291 assert(post_index.base.format.integer == .doubleword);
11292 return .{ .load_store = .{ .register_immediate_post_indexed = .{ .integer = .{
11293 .strh = .{
11294 .Rt = t.alias.encode(.{}),
11295 .Rn = post_index.base.alias.encode(.{ .sp = true }),
11296 .imm9 = post_index.index,
11297 },
11298 } } } };
11299 },
11300 .pre_index => |pre_index| {
11301 assert(pre_index.base.format.integer == .doubleword);
11302 return .{ .load_store = .{ .register_immediate_pre_indexed = .{ .integer = .{
11303 .strh = .{
11304 .Rt = t.alias.encode(.{}),
11305 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
11306 .imm9 = pre_index.index,
11307 },
11308 } } } };
11309 },
11310 .unsigned_offset => |unsigned_offset| {
11311 assert(unsigned_offset.base.format.integer == .doubleword);
11312 return .{ .load_store = .{ .register_unsigned_immediate = .{ .integer = .{
11313 .strh = .{
11314 .Rt = t.alias.encode(.{}),
11315 .Rn = unsigned_offset.base.alias.encode(.{ .sp = true }),
11316 .imm12 = @intCast(@shrExact(unsigned_offset.offset, 1)),
11317 },
11318 } } } };
11319 },
11320 .base => |base| continue :form .{ .unsigned_offset = .{ .base = base } },
11321 }
11322 }
11323 /// C6.2.346 STUR
11324 /// C7.2.333 STUR (SIMD&FP)
11325 pub fn stur(t: Register, n: Register, simm: i9) Instruction {
11326 assert(n.format.integer == .doubleword);
11327 switch (t.format) {
11328 else => unreachable,
11329 .integer => |sf| return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
11330 .stur = .{
11331 .Rt = t.alias.encode(.{}),
11332 .Rn = n.alias.encode(.{ .sp = true }),
11333 .imm9 = simm,
11334 .sf = sf,
11335 },
11336 } } } },
11337 .scalar => |vs| return .{ .load_store = .{ .register_unscaled_immediate = .{ .vector = .{
11338 .stur = .{
11339 .Rt = t.alias.encode(.{ .V = true }),
11340 .Rn = n.alias.encode(.{ .sp = true }),
11341 .imm9 = simm,
11342 .opc1 = .encode(vs),
11343 .size = .encode(vs),
11344 },
11345 } } } },
11346 }
11347 }
11348 /// C6.2.347 STURB
11349 pub fn sturb(t: Register, n: Register, simm: i9) Instruction {
11350 assert(t.format.integer == .word and n.format.integer == .doubleword);
11351 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
11352 .sturb = .{
11353 .Rt = t.alias.encode(.{}),
11354 .Rn = n.alias.encode(.{ .sp = true }),
11355 .imm9 = simm,
11356 },
11357 } } } };
11358 }
11359 /// C6.2.348 STURH
11360 pub fn sturh(t: Register, n: Register, simm: i9) Instruction {
11361 assert(t.format.integer == .word and n.format.integer == .doubleword);
11362 return .{ .load_store = .{ .register_unscaled_immediate = .{ .integer = .{
11363 .sturh = .{
11364 .Rt = t.alias.encode(.{}),
11365 .Rn = n.alias.encode(.{ .sp = true }),
11366 .imm9 = simm,
11367 },
11368 } } } };
11369 }
11370 /// C6.2.356 SUB (extended register)
11371 /// C6.2.357 SUB (immediate)
11372 /// C6.2.358 SUB (shifted register)
11373 pub fn sub(d: Register, n: Register, form: union(enum) {
11374 extended_register_explicit: struct {
11375 register: Register,
11376 option: DataProcessingRegister.AddSubtractExtendedRegister.Option,
11377 amount: DataProcessingRegister.AddSubtractExtendedRegister.Extend.Amount,
11378 },
11379 extended_register: struct { register: Register, extend: DataProcessingRegister.AddSubtractExtendedRegister.Extend },
11380 immediate: u12,
11381 shifted_immediate: struct { immediate: u12, lsl: DataProcessingImmediate.AddSubtractImmediate.Shift = .@"0" },
11382 register: Register,
11383 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
11384 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
11385 }) Instruction {
11386 const sf = d.format.integer;
11387 assert(n.format.integer == sf);
11388 form: switch (form) {
11389 .extended_register_explicit => |extended_register_explicit| {
11390 assert(extended_register_explicit.register.format.integer == extended_register_explicit.option.sf());
11391 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
11392 .sub = .{
11393 .Rd = d.alias.encode(.{ .sp = true }),
11394 .Rn = n.alias.encode(.{ .sp = true }),
11395 .imm3 = switch (extended_register_explicit.amount) {
11396 0...4 => |amount| amount,
11397 else => unreachable,
11398 },
11399 .option = extended_register_explicit.option,
11400 .Rm = extended_register_explicit.register.alias.encode(.{}),
11401 .sf = sf,
11402 },
11403 } } };
11404 },
11405 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
11406 .register = extended_register.register,
11407 .option = extended_register.extend,
11408 .amount = switch (extended_register.extend) {
11409 .uxtb, .uxth, .uxtw, .uxtx, .sxtb, .sxth, .sxtw, .sxtx => |amount| amount,
11410 },
11411 } },
11412 .immediate => |immediate| continue :form .{ .shifted_immediate = .{ .immediate = immediate } },
11413 .shifted_immediate => |shifted_immediate| {
11414 return .{ .data_processing_immediate = .{ .add_subtract_immediate = .{
11415 .sub = .{
11416 .Rd = d.alias.encode(.{ .sp = true }),
11417 .Rn = n.alias.encode(.{ .sp = true }),
11418 .imm12 = shifted_immediate.immediate,
11419 .sh = shifted_immediate.lsl,
11420 .sf = sf,
11421 },
11422 } } };
11423 },
11424 .register => |register| continue :form if (d.alias == .sp or n.alias == .sp or register.alias == .sp)
11425 .{ .extended_register = .{ .register = register, .extend = switch (sf) {
11426 .word => .{ .uxtw = 0 },
11427 .doubleword => .{ .uxtx = 0 },
11428 } } }
11429 else
11430 .{ .shifted_register = .{ .register = register } },
11431 .shifted_register_explicit => |shifted_register_explicit| {
11432 assert(shifted_register_explicit.register.format.integer == sf);
11433 return .{ .data_processing_register = .{ .add_subtract_shifted_register = .{
11434 .sub = .{
11435 .Rd = d.alias.encode(.{}),
11436 .Rn = n.alias.encode(.{}),
11437 .imm6 = switch (sf) {
11438 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
11439 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
11440 },
11441 .Rm = shifted_register_explicit.register.alias.encode(.{}),
11442 .shift = switch (shifted_register_explicit.shift) {
11443 .lsl, .lsr, .asr => |shift| shift,
11444 .ror => unreachable,
11445 },
11446 .sf = sf,
11447 },
11448 } } };
11449 },
11450 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
11451 .register = shifted_register.register,
11452 .shift = shifted_register.shift,
11453 .amount = switch (shifted_register.shift) {
11454 .lsl, .lsr, .asr => |amount| amount,
11455 .ror => unreachable,
11456 },
11457 } },
11458 }
11459 }
11460 /// C6.2.362 SUBS (extended register)
11461 /// C6.2.363 SUBS (immediate)
11462 /// C6.2.364 SUBS (shifted register)
11463 pub fn subs(d: Register, n: Register, form: union(enum) {
11464 extended_register_explicit: struct {
11465 register: Register,
11466 option: DataProcessingRegister.AddSubtractExtendedRegister.Option,
11467 amount: DataProcessingRegister.AddSubtractExtendedRegister.Extend.Amount,
11468 },
11469 extended_register: struct { register: Register, extend: DataProcessingRegister.AddSubtractExtendedRegister.Extend },
11470 immediate: u12,
11471 shifted_immediate: struct { immediate: u12, lsl: DataProcessingImmediate.AddSubtractImmediate.Shift = .@"0" },
11472 register: Register,
11473 shifted_register_explicit: struct { register: Register, shift: DataProcessingRegister.Shift.Op, amount: u6 },
11474 shifted_register: struct { register: Register, shift: DataProcessingRegister.Shift = .none },
11475 }) Instruction {
11476 const sf = d.format.integer;
11477 assert(n.format.integer == sf);
11478 form: switch (form) {
11479 .extended_register_explicit => |extended_register_explicit| {
11480 assert(extended_register_explicit.register.format.integer == extended_register_explicit.option.sf());
11481 return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
11482 .subs = .{
11483 .Rd = d.alias.encode(.{}),
11484 .Rn = n.alias.encode(.{ .sp = true }),
11485 .imm3 = switch (extended_register_explicit.amount) {
11486 0...4 => |amount| amount,
11487 else => unreachable,
11488 },
11489 .option = extended_register_explicit.option,
11490 .Rm = extended_register_explicit.register.alias.encode(.{}),
11491 .sf = sf,
11492 },
11493 } } };
11494 },
11495 .extended_register => |extended_register| continue :form .{ .extended_register_explicit = .{
11496 .register = extended_register.register,
11497 .option = extended_register.extend,
11498 .amount = switch (extended_register.extend) {
11499 .uxtb, .uxth, .uxtw, .uxtx, .sxtb, .sxth, .sxtw, .sxtx => |amount| amount,
11500 },
11501 } },
11502 .immediate => |immediate| continue :form .{ .shifted_immediate = .{ .immediate = immediate } },
11503 .shifted_immediate => |shifted_immediate| {
11504 return .{ .data_processing_immediate = .{ .add_subtract_immediate = .{
11505 .subs = .{
11506 .Rd = d.alias.encode(.{}),
11507 .Rn = n.alias.encode(.{ .sp = true }),
11508 .imm12 = shifted_immediate.immediate,
11509 .sh = shifted_immediate.lsl,
11510 .sf = sf,
11511 },
11512 } } };
11513 },
11514 .register => |register| continue :form if (d.alias == .sp or n.alias == .sp or register.alias == .sp)
11515 .{ .extended_register = .{ .register = register, .extend = switch (sf) {
11516 .word => .{ .uxtw = 0 },
11517 .doubleword => .{ .uxtx = 0 },
11518 } } }
11519 else
11520 .{ .shifted_register = .{ .register = register } },
11521 .shifted_register_explicit => |shifted_register_explicit| {
11522 assert(shifted_register_explicit.register.format.integer == sf);
11523 return .{ .data_processing_register = .{ .add_subtract_shifted_register = .{
11524 .subs = .{
11525 .Rd = d.alias.encode(.{}),
11526 .Rn = n.alias.encode(.{}),
11527 .imm6 = switch (sf) {
11528 .word => @as(u5, @intCast(shifted_register_explicit.amount)),
11529 .doubleword => @as(u6, @intCast(shifted_register_explicit.amount)),
11530 },
11531 .Rm = shifted_register_explicit.register.alias.encode(.{}),
11532 .shift = switch (shifted_register_explicit.shift) {
11533 .lsl, .lsr, .asr => |shift| shift,
11534 .ror => unreachable,
11535 },
11536 .sf = sf,
11537 },
11538 } } };
11539 },
11540 .shifted_register => |shifted_register| continue :form .{ .shifted_register_explicit = .{
11541 .register = shifted_register.register,
11542 .shift = shifted_register.shift,
11543 .amount = switch (shifted_register.shift) {
11544 .lsl, .lsr, .asr => |amount| amount,
11545 .ror => unreachable,
11546 },
11547 } },
11548 }
11549 }
11550 /// C6.2.365 SVC
11551 pub fn svc(imm: u16) Instruction {
11552 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
11553 .svc = .{ .imm16 = imm },
11554 } } };
11555 }
11556 /// C6.2.372 SYS
11557 pub fn sys(op1: u3, n: u4, m: u4, op2: u3, t: Register) Instruction {
11558 assert(t.format.integer == .doubleword);
11559 return .{ .branch_exception_generating_system = .{ .system = .{
11560 .sys = .{
11561 .Rt = t.alias.encode(.{}),
11562 .op2 = op2,
11563 .CRm = m,
11564 .CRn = n,
11565 .op1 = op1,
11566 },
11567 } } };
11568 }
11569 /// C6.2.373 SYSL
11570 pub fn sysl(t: Register, op1: u3, n: u4, m: u4, op2: u3) Instruction {
11571 assert(t.format.integer == .doubleword);
11572 return .{ .branch_exception_generating_system = .{ .system = .{
11573 .sysl = .{
11574 .Rt = t.alias.encode(.{}),
11575 .op2 = op2,
11576 .CRm = m,
11577 .CRn = n,
11578 .op1 = op1,
11579 },
11580 } } };
11581 }
11582 /// C6.2.374 TBNZ
11583 pub fn tbnz(t: Register, imm: u6, label: i16) Instruction {
11584 return .{ .branch_exception_generating_system = .{ .test_branch_immediate = .{
11585 .tbnz = .{
11586 .Rt = t.alias.encode(.{}),
11587 .imm14 = @intCast(@shrExact(label, 2)),
11588 .b40 = @truncate(switch (t.format.integer) {
11589 .word => @as(u5, @intCast(imm)),
11590 .doubleword => imm,
11591 }),
11592 .b5 = @intCast(imm >> 5),
11593 },
11594 } } };
11595 }
11596 /// C6.2.375 TBZ
11597 pub fn tbz(t: Register, imm: u6, label: i16) Instruction {
11598 return .{ .branch_exception_generating_system = .{ .test_branch_immediate = .{
11599 .tbz = .{
11600 .Rt = t.alias.encode(.{}),
11601 .imm14 = @intCast(@shrExact(label, 2)),
11602 .b40 = @truncate(switch (t.format.integer) {
11603 .word => @as(u5, @intCast(imm)),
11604 .doubleword => imm,
11605 }),
11606 .b5 = @intCast(imm >> 5),
11607 },
11608 } } };
11609 }
11610 /// C6.2.376 TCANCEL
11611 pub fn tcancel(imm: u16) Instruction {
11612 return .{ .branch_exception_generating_system = .{ .exception_generating = .{
11613 .tcancel = .{ .imm16 = imm },
11614 } } };
11615 }
11616 /// C6.2.385 UBFM
11617 pub fn ubfm(d: Register, n: Register, bitmask: DataProcessingImmediate.Bitmask) Instruction {
11618 const sf = d.format.integer;
11619 assert(n.format.integer == sf and bitmask.validBitfield(sf));
11620 return .{ .data_processing_immediate = .{ .bitfield = .{
11621 .ubfm = .{
11622 .Rd = d.alias.encode(.{}),
11623 .Rn = n.alias.encode(.{}),
11624 .imm = bitmask,
11625 .sf = sf,
11626 },
11627 } } };
11628 }
11629 /// C7.2.355 UCVTF (scalar, integer)
11630 pub fn ucvtf(d: Register, n: Register) Instruction {
11631 return .{ .data_processing_vector = .{ .convert_float_integer = .{
11632 .ucvtf = .{
11633 .Rd = d.alias.encode(.{ .V = true }),
11634 .Rn = n.alias.encode(.{}),
11635 .ftype = switch (d.format.scalar) {
11636 else => unreachable,
11637 .single => .single,
11638 .double => .double,
11639 .half => .half,
11640 },
11641 .sf = n.format.integer,
11642 },
11643 } } };
11644 }
11645 /// C6.2.387 UDF
11646 pub fn udf(imm: u16) Instruction {
11647 return .{ .reserved = .{
11648 .udf = .{ .imm16 = imm },
11649 } };
11650 }
11651 /// C6.2.388 UDIV
11652 pub fn udiv(d: Register, n: Register, m: Register) Instruction {
11653 const sf = d.format.integer;
11654 assert(n.format.integer == sf and m.format.integer == sf);
11655 return .{ .data_processing_register = .{ .data_processing_two_source = .{
11656 .udiv = .{
11657 .Rd = d.alias.encode(.{}),
11658 .Rn = n.alias.encode(.{}),
11659 .Rm = m.alias.encode(.{}),
11660 .sf = sf,
11661 },
11662 } } };
11663 }
11664 /// C6.2.389 UMADDL
11665 pub fn umaddl(d: Register, n: Register, m: Register, a: Register) Instruction {
11666 assert(d.format.integer == .doubleword and n.format.integer == .word and m.format.integer == .word and a.format.integer == .doubleword);
11667 return .{ .data_processing_register = .{ .data_processing_three_source = .{
11668 .umaddl = .{
11669 .Rd = d.alias.encode(.{}),
11670 .Rn = n.alias.encode(.{}),
11671 .Ra = a.alias.encode(.{}),
11672 .Rm = m.alias.encode(.{}),
11673 },
11674 } } };
11675 }
11676 /// C6.2.391 UMSUBL
11677 pub fn umsubl(d: Register, n: Register, m: Register, a: Register) Instruction {
11678 assert(d.format.integer == .doubleword and n.format.integer == .word and m.format.integer == .word and a.format.integer == .doubleword);
11679 return .{ .data_processing_register = .{ .data_processing_three_source = .{
11680 .umsubl = .{
11681 .Rd = d.alias.encode(.{}),
11682 .Rn = n.alias.encode(.{}),
11683 .Ra = a.alias.encode(.{}),
11684 .Rm = m.alias.encode(.{}),
11685 },
11686 } } };
11687 }
11688 /// C7.2.371 UMOV
11689 pub fn umov(d: Register, n: Register) Instruction {
11690 const sf = d.format.integer;
11691 const vs = n.format.element.size;
11692 switch (vs) {
11693 else => unreachable,
11694 .byte, .half, .single => assert(sf == .word),
11695 .double => assert(sf == .doubleword),
11696 }
11697 return .{ .data_processing_vector = .{ .simd_copy = .{
11698 .umov = .{
11699 .Rd = d.alias.encode(.{}),
11700 .Rn = n.alias.encode(.{ .V = true }),
11701 .imm5 = switch (vs) {
11702 else => unreachable,
11703 .byte => @as(u5, @as(u4, @intCast(n.format.element.index))) << 1 | @as(u5, 0b1) << 0,
11704 .half => @as(u5, @as(u3, @intCast(n.format.element.index))) << 2 | @as(u5, 0b10) << 0,
11705 .single => @as(u5, @as(u2, @intCast(n.format.element.index))) << 3 | @as(u5, 0b100) << 0,
11706 .double => @as(u5, @as(u1, @intCast(n.format.element.index))) << 4 | @as(u5, 0b1000) << 0,
11707 },
11708 .Q = sf,
11709 },
11710 } } };
11711 }
11712 /// C6.2.392 UMULH
11713 pub fn umulh(d: Register, n: Register, m: Register) Instruction {
11714 assert(d.format.integer == .doubleword and n.format.integer == .doubleword and m.format.integer == .doubleword);
11715 return .{ .data_processing_register = .{ .data_processing_three_source = .{
11716 .umulh = .{
11717 .Rd = d.alias.encode(.{}),
11718 .Rn = n.alias.encode(.{}),
11719 .Rm = m.alias.encode(.{}),
11720 },
11721 } } };
11722 }
11723 /// C6.2.396 WFE
11724 pub fn wfe() Instruction {
11725 return .{ .branch_exception_generating_system = .{ .hints = .{
11726 .wfe = .{},
11727 } } };
11728 }
11729 /// C6.2.398 WFI
11730 pub fn wfi() Instruction {
11731 return .{ .branch_exception_generating_system = .{ .hints = .{
11732 .wfi = .{},
11733 } } };
11734 }
11735 /// C6.2.402 YIELD
11736 pub fn yield() Instruction {
11737 return .{ .branch_exception_generating_system = .{ .hints = .{
11738 .yield = .{},
11739 } } };
11740 }
11741
11742 pub const size = @divExact(@bitSizeOf(Backing), 8);
11743 pub const Backing = u32;
11744 pub fn read(mem: *const [size]u8) Instruction {
11745 return @bitCast(std.mem.readInt(Backing, mem, .little));
11746 }
11747 pub fn write(inst: Instruction, mem: *[size]u8) void {
11748 std.mem.writeInt(Backing, mem, @bitCast(inst), .little);
11749 }
11750
11751 pub fn format(inst: Instruction, writer: *std.Io.Writer) std.Io.Writer.Error!void {
11752 const dis: aarch64.Disassemble = .{};
11753 try dis.printInstruction(inst, writer);
11754 }
11755
11756 comptime {
11757 @setEvalBranchQuota(68_000);
11758 verify(@typeName(Instruction), Instruction);
11759 }
11760 fn verify(name: []const u8, Type: type) void {
11761 switch (@typeInfo(Type)) {
11762 .@"union" => |info| {
11763 if (info.layout != .@"packed" or @bitSizeOf(Type) != @bitSizeOf(Backing)) {
11764 @compileLog(name ++ " should have u32 abi");
11765 }
11766 for (info.fields) |field| verify(name ++ "." ++ field.name, field.type);
11767 },
11768 .@"struct" => |info| {
11769 if (info.layout != .@"packed" or info.backing_integer != Backing) {
11770 @compileLog(name ++ " should have u32 abi");
11771 }
11772 var bit_offset = 0;
11773 for (info.fields) |field| {
11774 if (std.mem.startsWith(u8, field.name, "encoded")) {
11775 if (if (std.fmt.parseInt(u5, field.name["encoded".len..], 10)) |encoded_bit_offset| encoded_bit_offset != bit_offset else |_| true) {
11776 @compileError(std.fmt.comptimePrint("{s}.{s} should be named encoded{d}", .{ name, field.name, bit_offset }));
11777 }
11778 if (field.default_value_ptr != null) {
11779 @compileError(std.fmt.comptimePrint("{s}.{s} should be named decoded{d}", .{ name, field.name, bit_offset }));
11780 }
11781 } else if (std.mem.startsWith(u8, field.name, "decoded")) {
11782 if (if (std.fmt.parseInt(u5, field.name["decoded".len..], 10)) |decoded_bit_offset| decoded_bit_offset != bit_offset else |_| true) {
11783 @compileError(std.fmt.comptimePrint("{s}.{s} should be named decoded{d}", .{ name, field.name, bit_offset }));
11784 }
11785 if (field.default_value_ptr == null) {
11786 @compileError(std.fmt.comptimePrint("{s}.{s} should be named encoded{d}", .{ name, field.name, bit_offset }));
11787 }
11788 }
11789 bit_offset += @bitSizeOf(field.type);
11790 }
11791 },
11792 else => @compileError(name ++ " has an unexpected field type"),
11793 }
11794 }
11795};
11796
11797const aarch64 = @import("../aarch64.zig");
11798const assert = std.debug.assert;
11799const std = @import("std");
src/codegen/aarch64/instructions.zon created+1343
...@@ -0,0 +1,1343 @@
1.{
2 // C6.2.3 ADD (extended register)
3 .{
4 .pattern = "ADD <Wd|WSP>, <Wn|WSP>, <Wm>",
5 .symbols = .{
6 .Wd = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
7 .Wn = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
8 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
9 },
10 .encode = .{ .add, .Wd, .Wn, .{ .register = .Wm } },
11 },
12 .{
13 .pattern = "ADD <Wd|WSP>, <Wn|WSP>, <Wm>, <extend> #<amount>",
14 .symbols = .{
15 .Wd = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
16 .Wn = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
17 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
18 .extend = .{ .extend = .{ .size = .word } },
19 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
20 },
21 .encode = .{ .add, .Wd, .Wn, .{ .extended_register_explicit = .{ .register = .Wm, .option = .extend, .amount = .amount } } },
22 },
23 .{
24 .pattern = "ADD <Xd|SP>, <Xn|SP>, <Xm>",
25 .symbols = .{
26 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
27 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
28 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
29 },
30 .encode = .{ .add, .Xd, .Xn, .{ .register = .Xm } },
31 },
32 .{
33 .pattern = "ADD <Xd|SP>, <Xn|SP>, <Wm>, <extend> #<amount>",
34 .symbols = .{
35 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
36 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
37 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
38 .extend = .{ .extend = .{ .size = .word } },
39 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
40 },
41 .encode = .{ .add, .Xd, .Xn, .{ .extended_register_explicit = .{ .register = .Wm, .option = .extend, .amount = .amount } } },
42 },
43 .{
44 .pattern = "ADD <Xd|SP>, <Xn|SP>, <Xm>, <extend> #<amount>",
45 .symbols = .{
46 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
47 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
48 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
49 .extend = .{ .extend = .{ .size = .doubleword } },
50 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
51 },
52 .encode = .{ .add, .Xd, .Xn, .{ .extended_register_explicit = .{ .register = .Xm, .option = .extend, .amount = .amount } } },
53 },
54 // C6.2.4 ADD (immediate)
55 .{
56 .pattern = "ADD <Wd|WSP>, <Wn|WSP>, #<imm>",
57 .symbols = .{
58 .Wd = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
59 .Wn = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
60 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
61 },
62 .encode = .{ .add, .Wd, .Wn, .{ .immediate = .imm } },
63 },
64 .{
65 .pattern = "ADD <Wd|WSP>, <Wn|WSP>, #<imm>, LSL #<shift>",
66 .symbols = .{
67 .Wd = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
68 .Wn = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
69 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
70 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
71 },
72 .encode = .{ .add, .Wd, .Wn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
73 },
74 .{
75 .pattern = "ADD <Xd|SP>, <Xn|SP>, #<imm>",
76 .symbols = .{
77 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
78 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
79 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
80 },
81 .encode = .{ .add, .Xd, .Xn, .{ .immediate = .imm } },
82 },
83 .{
84 .pattern = "ADD <Xd|SP>, <Xn|SP>, #<imm>, LSL #<shift>",
85 .symbols = .{
86 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
87 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
88 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
89 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
90 },
91 .encode = .{ .add, .Xd, .Xn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
92 },
93 // C6.2.5 ADD (shifted register)
94 .{
95 .pattern = "ADD <Wd>, <Wn>, <Wm>",
96 .symbols = .{
97 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
98 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
99 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
100 },
101 .encode = .{ .add, .Wd, .Wn, .{ .register = .Wm } },
102 },
103 .{
104 .pattern = "ADD <Wd>, <Wn>, <Wm>, <shift> #<amount>",
105 .symbols = .{
106 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
107 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
108 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
109 .shift = .{ .shift = .{ .allow_ror = false } },
110 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
111 },
112 .encode = .{ .add, .Wd, .Wn, .{ .shifted_register_explicit = .{ .register = .Wm, .shift = .shift, .amount = .amount } } },
113 },
114 .{
115 .pattern = "ADD <Xd>, <Xn>, <Xm>",
116 .symbols = .{
117 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
118 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
119 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
120 },
121 .encode = .{ .add, .Xd, .Xn, .{ .register = .Xm } },
122 },
123 .{
124 .pattern = "ADD <Xd>, <Xn>, <Xm>, <shift> #<amount>",
125 .symbols = .{
126 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
127 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
128 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
129 .shift = .{ .shift = .{ .allow_ror = false } },
130 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
131 },
132 .encode = .{ .add, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } },
133 },
134 // C6.2.13 AND (shifted register)
135 .{
136 .pattern = "AND <Wd>, <Wn>, <Wm>",
137 .symbols = .{
138 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
139 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
140 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
141 },
142 .encode = .{ .@"and", .Wd, .Wn, .{ .register = .Wm } },
143 },
144 .{
145 .pattern = "AND <Wd>, <Wn>, <Wm>, <shift> #<amount>",
146 .symbols = .{
147 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
148 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
149 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
150 .shift = .{ .shift = .{} },
151 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
152 },
153 .encode = .{ .@"and", .Wd, .Wn, .{ .shifted_register_explicit = .{ .register = .Wm, .shift = .shift, .amount = .amount } } },
154 },
155 .{
156 .pattern = "AND <Xd>, <Xn>, <Xm>",
157 .symbols = .{
158 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
159 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
160 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
161 },
162 .encode = .{ .@"and", .Xd, .Xn, .{ .register = .Xm } },
163 },
164 .{
165 .pattern = "AND <Xd>, <Xn>, <Xm>, <shift> #<amount>",
166 .symbols = .{
167 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
168 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
169 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
170 .shift = .{ .shift = .{} },
171 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
172 },
173 .encode = .{ .@"and", .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } },
174 },
175 // C6.2.15 ANDS (shifted register)
176 .{
177 .pattern = "ANDS <Wd>, <Wn>, <Wm>",
178 .symbols = .{
179 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
180 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
181 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
182 },
183 .encode = .{ .ands, .Wd, .Wn, .{ .register = .Wm } },
184 },
185 .{
186 .pattern = "ANDS <Wd>, <Wn>, <Wm>, <shift> #<amount>",
187 .symbols = .{
188 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
189 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
190 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
191 .shift = .{ .shift = .{} },
192 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
193 },
194 .encode = .{ .ands, .Wd, .Wn, .{ .shifted_register_explicit = .{ .register = .Wm, .shift = .shift, .amount = .amount } } },
195 },
196 .{
197 .pattern = "ANDS <Xd>, <Xn>, <Xm>",
198 .symbols = .{
199 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
200 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
201 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
202 },
203 .encode = .{ .ands, .Xd, .Xn, .{ .register = .Xm } },
204 },
205 .{
206 .pattern = "ANDS <Xd>, <Xn>, <Xm>, <shift> #<amount>",
207 .symbols = .{
208 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
209 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
210 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
211 .shift = .{ .shift = .{} },
212 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
213 },
214 .encode = .{ .ands, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } },
215 },
216 // C6.2.35 BLR
217 .{
218 .pattern = "BLR <Xn>",
219 .symbols = .{
220 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
221 },
222 .encode = .{ .blr, .Xn },
223 },
224 // C6.2.30 BFM
225 .{
226 .pattern = "BFM <Wd>, <Wn>, #<immr>, #<imms>",
227 .symbols = .{
228 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
229 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
230 .immr = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
231 .imms = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
232 },
233 .encode = .{ .bfm, .Wd, .Wn, .{ .N = .word, .immr = .immr, .imms = .imms } },
234 },
235 .{
236 .pattern = "BFM <Xd>, <Xn>, #<immr>, #<imms>",
237 .symbols = .{
238 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
239 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
240 .immr = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
241 .imms = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
242 },
243 .encode = .{ .bfm, .Xd, .Xn, .{ .N = .doubleword, .immr = .immr, .imms = .imms } },
244 },
245 // C6.2.37 BR
246 .{
247 .pattern = "BR <Xn>",
248 .symbols = .{
249 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
250 },
251 .encode = .{ .br, .Xn },
252 },
253 // C6.2.40 BRK
254 .{
255 .pattern = "BRK #<imm>",
256 .symbols = .{
257 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
258 },
259 .encode = .{ .brk, .imm },
260 },
261 // C6.2.56 CLREX
262 .{
263 .pattern = "CLREX",
264 .symbols = .{},
265 .encode = .{ .clrex, 0b1111 },
266 },
267 .{
268 .pattern = "CLREX #<imm>",
269 .symbols = .{
270 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 } } },
271 },
272 .encode = .{ .clrex, .imm },
273 },
274 // C6.2.109 DC
275 .{
276 .pattern = "DC IVAC, <Xt>",
277 .symbols = .{
278 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
279 },
280 .encode = .{ .sys, 0b000, 0b0111, 0b0110, 0b001, .Xt },
281 },
282 .{
283 .pattern = "DC ISW, <Xt>",
284 .symbols = .{
285 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
286 },
287 .encode = .{ .sys, 0b000, 0b0111, 0b0110, 0b010, .Xt },
288 },
289 .{
290 .pattern = "DC CSW, <Xt>",
291 .symbols = .{
292 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
293 },
294 .encode = .{ .sys, 0b000, 0b0111, 0b1010, 0b010, .Xt },
295 },
296 .{
297 .pattern = "DC CISW, <Xt>",
298 .symbols = .{
299 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
300 },
301 .encode = .{ .sys, 0b000, 0b0111, 0b1110, 0b010, .Xt },
302 },
303 .{
304 .pattern = "DC ZVA, <Xt>",
305 .symbols = .{
306 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
307 },
308 .encode = .{ .sys, 0b011, 0b0111, 0b0100, 0b001, .Xt },
309 },
310 .{
311 .pattern = "DC CVAC, <Xt>",
312 .symbols = .{
313 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
314 },
315 .encode = .{ .sys, 0b011, 0b0111, 0b1010, 0b001, .Xt },
316 },
317 .{
318 .pattern = "DC CVAU, <Xt>",
319 .symbols = .{
320 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
321 },
322 .encode = .{ .sys, 0b011, 0b0111, 0b1011, 0b001, .Xt },
323 },
324 .{
325 .pattern = "DC CIVAC, <Xt>",
326 .symbols = .{
327 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
328 },
329 .encode = .{ .sys, 0b011, 0b0111, 0b1110, 0b001, .Xt },
330 },
331 // C6.2.110 DCPS1
332 .{
333 .pattern = "DCPS1",
334 .symbols = .{},
335 .encode = .{ .dcps1, 0 },
336 },
337 .{
338 .pattern = "DCPS1 #<imm>",
339 .symbols = .{
340 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
341 },
342 .encode = .{ .dcps1, .imm },
343 },
344 // C6.2.111 DCPS2
345 .{
346 .pattern = "DCPS2",
347 .symbols = .{},
348 .encode = .{ .dcps2, 0 },
349 },
350 .{
351 .pattern = "DCPS2 #<imm>",
352 .symbols = .{
353 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
354 },
355 .encode = .{ .dcps2, .imm },
356 },
357 // C6.2.112 DCPS3
358 .{
359 .pattern = "DCPS3",
360 .symbols = .{},
361 .encode = .{ .dcps3, 0 },
362 },
363 .{
364 .pattern = "DCPS3 #<imm>",
365 .symbols = .{
366 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
367 },
368 .encode = .{ .dcps3, .imm },
369 },
370 // C6.2.116 DSB
371 .{
372 .pattern = "DSB <option>",
373 .symbols = .{
374 .option = .{ .barrier = .{} },
375 },
376 .encode = .{ .dsb, .option },
377 },
378 .{
379 .pattern = "DSB #<imm>",
380 .symbols = .{
381 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 } } },
382 },
383 .encode = .{ .dsb, .imm },
384 },
385 // C6.2.120 EOR (shifted register)
386 .{
387 .pattern = "EOR <Wd>, <Wn>, <Wm>",
388 .symbols = .{
389 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
390 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
391 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
392 },
393 .encode = .{ .eor, .Wd, .Wn, .{ .register = .Wm } },
394 },
395 .{
396 .pattern = "EOR <Wd>, <Wn>, <Wm>, <shift> #<amount>",
397 .symbols = .{
398 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
399 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
400 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
401 .shift = .{ .shift = .{} },
402 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
403 },
404 .encode = .{ .eor, .Wd, .Wn, .{ .shifted_register_explicit = .{ .register = .Wm, .shift = .shift, .amount = .amount } } },
405 },
406 .{
407 .pattern = "EOR <Xd>, <Xn>, <Xm>",
408 .symbols = .{
409 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
410 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
411 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
412 },
413 .encode = .{ .eor, .Xd, .Xn, .{ .register = .Xm } },
414 },
415 .{
416 .pattern = "EOR <Xd>, <Xn>, <Xm>, <shift> #<amount>",
417 .symbols = .{
418 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
419 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
420 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
421 .shift = .{ .shift = .{} },
422 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
423 },
424 .encode = .{ .eor, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } },
425 },
426 // C6.2.124 EXTR
427 .{
428 .pattern = "EXTR <Wd>, <Wn>, <Wm>, #<lsb>",
429 .symbols = .{
430 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
431 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
432 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
433 .lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
434 },
435 .encode = .{ .extr, .Wd, .Wn, .Wm, .lsb },
436 },
437 .{
438 .pattern = "EXTR <Xd>, <Xn>, <Xm>, #<lsb>",
439 .symbols = .{
440 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
441 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
442 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
443 .lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
444 },
445 .encode = .{ .extr, .Xd, .Xn, .Xm, .lsb },
446 },
447 // C6.2.126 HINT
448 .{
449 .pattern = "HINT #<imm>",
450 .symbols = .{
451 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 7 } } },
452 },
453 .encode = .{ .hint, .imm },
454 },
455 // C6.2.127 HLT
456 .{
457 .pattern = "HLT #<imm>",
458 .symbols = .{
459 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
460 },
461 .encode = .{ .hlt, .imm },
462 },
463 // C6.2.128 HVC
464 .{
465 .pattern = "HVC #<imm>",
466 .symbols = .{
467 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
468 },
469 .encode = .{ .hvc, .imm },
470 },
471 // C6.2.129 IC
472 .{
473 .pattern = "IC IALLUIS",
474 .symbols = .{
475 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
476 },
477 .encode = .{ .sys, 0b000, 0b0111, 0b0001, 0b000, .xzr },
478 },
479 .{
480 .pattern = "IC IALLUIS, <Xt>",
481 .symbols = .{
482 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
483 },
484 .encode = .{ .sys, 0b000, 0b0111, 0b0001, 0b000, .Xt },
485 },
486 .{
487 .pattern = "IC IALLU",
488 .symbols = .{
489 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
490 },
491 .encode = .{ .sys, 0b000, 0b0111, 0b0101, 0b000, .xzr },
492 },
493 .{
494 .pattern = "IC IALLU, <Xt>",
495 .symbols = .{
496 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
497 },
498 .encode = .{ .sys, 0b000, 0b0111, 0b0101, 0b000, .Xt },
499 },
500 .{
501 .pattern = "IC IVAU",
502 .symbols = .{
503 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
504 },
505 .encode = .{ .sys, 0b011, 0b0111, 0b0101, 0b001, .xzr },
506 },
507 .{
508 .pattern = "IC IVAU, <Xt>",
509 .symbols = .{
510 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
511 },
512 .encode = .{ .sys, 0b011, 0b0111, 0b0101, 0b001, .Xt },
513 },
514 // C6.2.131 ISB
515 .{
516 .pattern = "ISB",
517 .symbols = .{},
518 .encode = .{ .isb, .sy },
519 },
520 .{
521 .pattern = "ISB <option>",
522 .symbols = .{
523 .option = .{ .barrier = .{ .only_sy = true } },
524 },
525 .encode = .{ .isb, .option },
526 },
527 .{
528 .pattern = "ISB #<imm>",
529 .symbols = .{
530 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 } } },
531 },
532 .encode = .{ .isb, .imm },
533 },
534 // C6.2.164 LDP
535 .{
536 .pattern = "LDP <Wt1>, <Wt2>, [<Xn|SP>], #<imm>",
537 .symbols = .{
538 .Wt1 = .{ .reg = .{ .format = .{ .integer = .word } } },
539 .Wt2 = .{ .reg = .{ .format = .{ .integer = .word } } },
540 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
541 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 }, .multiple_of = 4 } },
542 },
543 .encode = .{ .ldp, .Wt1, .Wt2, .{ .post_index = .{ .base = .Xn, .index = .imm } } },
544 },
545 .{
546 .pattern = "LDP <Xt1>, <Xt2>, [<Xn|SP>], #<imm>",
547 .symbols = .{
548 .Xt1 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
549 .Xt2 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
550 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
551 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 10 }, .multiple_of = 8 } },
552 },
553 .encode = .{ .ldp, .Xt1, .Xt2, .{ .post_index = .{ .base = .Xn, .index = .imm } } },
554 },
555 .{
556 .pattern = "LDP <Wt1>, <Wt2>, [<Xn|SP>, #<imm>]!",
557 .symbols = .{
558 .Wt1 = .{ .reg = .{ .format = .{ .integer = .word } } },
559 .Wt2 = .{ .reg = .{ .format = .{ .integer = .word } } },
560 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
561 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 }, .multiple_of = 4 } },
562 },
563 .encode = .{ .ldp, .Wt1, .Wt2, .{ .pre_index = .{ .base = .Xn, .index = .imm } } },
564 },
565 .{
566 .pattern = "LDP <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]!",
567 .symbols = .{
568 .Xt1 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
569 .Xt2 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
570 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
571 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 10 }, .multiple_of = 8 } },
572 },
573 .encode = .{ .ldp, .Xt1, .Xt2, .{ .pre_index = .{ .base = .Xn, .index = .imm } } },
574 },
575 .{
576 .pattern = "LDP <Wt1>, <Wt2>, [<Xn|SP>]",
577 .symbols = .{
578 .Wt1 = .{ .reg = .{ .format = .{ .integer = .word } } },
579 .Wt2 = .{ .reg = .{ .format = .{ .integer = .word } } },
580 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
581 },
582 .encode = .{ .ldp, .Wt1, .Wt2, .{ .base = .Xn } },
583 },
584 .{
585 .pattern = "LDP <Wt1>, <Wt2>, [<Xn|SP>, #<imm>]",
586 .symbols = .{
587 .Wt1 = .{ .reg = .{ .format = .{ .integer = .word } } },
588 .Wt2 = .{ .reg = .{ .format = .{ .integer = .word } } },
589 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
590 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 }, .multiple_of = 4 } },
591 },
592 .encode = .{ .ldp, .Wt1, .Wt2, .{ .signed_offset = .{ .base = .Xn, .offset = .imm } } },
593 },
594 .{
595 .pattern = "LDP <Xt1>, <Xt2>, [<Xn|SP>]",
596 .symbols = .{
597 .Xt1 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
598 .Xt2 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
599 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
600 },
601 .encode = .{ .ldp, .Xt1, .Xt2, .{ .base = .Xn } },
602 },
603 .{
604 .pattern = "LDP <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]",
605 .symbols = .{
606 .Xt1 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
607 .Xt2 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
608 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
609 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 10 }, .multiple_of = 8 } },
610 },
611 .encode = .{ .ldp, .Xt1, .Xt2, .{ .signed_offset = .{ .base = .Xn, .offset = .imm } } },
612 },
613 // C6.2.166 LDR (immediate)
614 .{
615 .pattern = "LDR <Wt>, [<Xn|SP>], #<simm>",
616 .symbols = .{
617 .Wt = .{ .reg = .{ .format = .{ .integer = .word } } },
618 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
619 .simm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 } } },
620 },
621 .encode = .{ .ldr, .Wt, .{ .post_index = .{ .base = .Xn, .index = .simm } } },
622 },
623 .{
624 .pattern = "LDR <Xt>, [<Xn|SP>], #<simm>",
625 .symbols = .{
626 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
627 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
628 .simm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 } } },
629 },
630 .encode = .{ .ldr, .Xt, .{ .post_index = .{ .base = .Xn, .index = .simm } } },
631 },
632 .{
633 .pattern = "LDR <Wt>, [<Xn|SP>, #<simm>]!",
634 .symbols = .{
635 .Wt = .{ .reg = .{ .format = .{ .integer = .word } } },
636 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
637 .simm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 } } },
638 },
639 .encode = .{ .ldr, .Wt, .{ .pre_index = .{ .base = .Xn, .index = .simm } } },
640 },
641 .{
642 .pattern = "LDR <Xt>, [<Xn|SP>, #<simm>]!",
643 .symbols = .{
644 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
645 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
646 .simm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 } } },
647 },
648 .encode = .{ .ldr, .Xt, .{ .pre_index = .{ .base = .Xn, .index = .simm } } },
649 },
650 .{
651 .pattern = "LDR <Wt>, [<Xn|SP>]",
652 .symbols = .{
653 .Wt = .{ .reg = .{ .format = .{ .integer = .word } } },
654 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
655 },
656 .encode = .{ .ldr, .Wt, .{ .base = .Xn } },
657 },
658 .{
659 .pattern = "LDR <Wt>, [<Xn|SP>, #<pimm>]",
660 .symbols = .{
661 .Wt = .{ .reg = .{ .format = .{ .integer = .word } } },
662 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
663 .pimm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 14 }, .multiple_of = 4 } },
664 },
665 .encode = .{ .ldr, .Wt, .{ .unsigned_offset = .{ .base = .Xn, .offset = .pimm } } },
666 },
667 .{
668 .pattern = "LDR <Xt>, [<Xn|SP>]",
669 .symbols = .{
670 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
671 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
672 },
673 .encode = .{ .ldr, .Xt, .{ .base = .Xn } },
674 },
675 .{
676 .pattern = "LDR <Xt>, [<Xn|SP>, #<pimm>]",
677 .symbols = .{
678 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
679 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
680 .pimm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 15 }, .multiple_of = 8 } },
681 },
682 .encode = .{ .ldr, .Xt, .{ .unsigned_offset = .{ .base = .Xn, .offset = .pimm } } },
683 },
684 // C6.2.220 MOV (to/from SP)
685 .{
686 .pattern = "MOV WSP, <Wn|WSP>",
687 .symbols = .{
688 .Wn = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
689 },
690 .encode = .{ .add, .wsp, .Wn, .{ .immediate = 0 } },
691 },
692 .{
693 .pattern = "MOV <Wd|WSP>, WSP",
694 .symbols = .{
695 .Wd = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
696 },
697 .encode = .{ .add, .Wd, .wsp, .{ .immediate = 0 } },
698 },
699 .{
700 .pattern = "MOV SP, <Xn|SP>",
701 .symbols = .{
702 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
703 },
704 .encode = .{ .add, .sp, .Xn, .{ .immediate = 0 } },
705 },
706 .{
707 .pattern = "MOV <Xd|SP>, SP",
708 .symbols = .{
709 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
710 },
711 .encode = .{ .add, .Xd, .sp, .{ .immediate = 0 } },
712 },
713 // C6.2.222 MOV (wide immediate)
714 .{
715 .pattern = "MOV <Wd>, #<imm>",
716 .symbols = .{
717 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
718 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
719 },
720 .encode = .{ .movz, .Wd, .imm, .{ .lsl = .@"0" } },
721 },
722 .{
723 .pattern = "MOV <Xd>, #<imm>",
724 .symbols = .{
725 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
726 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
727 },
728 .encode = .{ .movz, .Xd, .imm, .{ .lsl = .@"0" } },
729 },
730 // C6.2.224 MOV (register)
731 .{
732 .pattern = "MOV <Wd>, <Wm>",
733 .symbols = .{
734 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
735 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
736 },
737 .encode = .{ .orr, .Wd, .wzr, .{ .register = .Wm } },
738 },
739 .{
740 .pattern = "MOV <Xd>, <Xm>",
741 .symbols = .{
742 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
743 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
744 },
745 .encode = .{ .orr, .Xd, .xzr, .{ .register = .Xm } },
746 },
747 // C6.2.225 MOVK
748 .{
749 .pattern = "MOVK <Wd>, #<imm>",
750 .symbols = .{
751 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
752 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
753 },
754 .encode = .{ .movk, .Wd, .imm, .{} },
755 },
756 .{
757 .pattern = "MOVK <Wd>, #<imm>, LSL #<shift>",
758 .symbols = .{
759 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
760 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
761 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .multiple_of = 16 } },
762 },
763 .encode = .{ .movk, .Wd, .imm, .{ .lsl = .shift } },
764 },
765 .{
766 .pattern = "MOVK <Xd>, #<imm>",
767 .symbols = .{
768 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
769 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
770 },
771 .encode = .{ .movk, .Xd, .imm, .{} },
772 },
773 .{
774 .pattern = "MOVK <Xd>, #<imm>, LSL #<shift>",
775 .symbols = .{
776 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
777 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
778 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .multiple_of = 16 } },
779 },
780 .encode = .{ .movk, .Xd, .imm, .{ .lsl = .shift } },
781 },
782 // C6.2.226 MOVN
783 .{
784 .pattern = "MOVN <Wd>, #<imm>",
785 .symbols = .{
786 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
787 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
788 },
789 .encode = .{ .movn, .Wd, .imm, .{} },
790 },
791 .{
792 .pattern = "MOVN <Wd>, #<imm>, LSL #<shift>",
793 .symbols = .{
794 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
795 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
796 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .multiple_of = 16 } },
797 },
798 .encode = .{ .movn, .Wd, .imm, .{ .lsl = .shift } },
799 },
800 .{
801 .pattern = "MOVN <Xd>, #<imm>",
802 .symbols = .{
803 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
804 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
805 },
806 .encode = .{ .movn, .Xd, .imm, .{} },
807 },
808 .{
809 .pattern = "MOVN <Xd>, #<imm>, LSL #<shift>",
810 .symbols = .{
811 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
812 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
813 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .multiple_of = 16 } },
814 },
815 .encode = .{ .movn, .Xd, .imm, .{ .lsl = .shift } },
816 },
817 // C6.2.227 MOVZ
818 .{
819 .pattern = "MOVZ <Wd>, #<imm>",
820 .symbols = .{
821 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
822 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
823 },
824 .encode = .{ .movz, .Wd, .imm, .{} },
825 },
826 .{
827 .pattern = "MOVZ <Wd>, #<imm>, LSL #<shift>",
828 .symbols = .{
829 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
830 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
831 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .multiple_of = 16 } },
832 },
833 .encode = .{ .movz, .Wd, .imm, .{ .lsl = .shift } },
834 },
835 .{
836 .pattern = "MOVZ <Xd>, #<imm>",
837 .symbols = .{
838 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
839 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
840 },
841 .encode = .{ .movz, .Xd, .imm, .{} },
842 },
843 .{
844 .pattern = "MOVZ <Xd>, #<imm>, LSL #<shift>",
845 .symbols = .{
846 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
847 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
848 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .multiple_of = 16 } },
849 },
850 .encode = .{ .movz, .Xd, .imm, .{ .lsl = .shift } },
851 },
852 // C6.2.228 MRS
853 .{
854 .pattern = "MRS <Xt>, CTR_EL0",
855 .symbols = .{
856 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
857 },
858 .encode = .{ .mrs, .Xt, 0b11, 0b011, 0b0000, 0b0000, 0b001 },
859 },
860 // C6.2.234 NEG
861 .{
862 .pattern = "NEG <Wd>, <Wm>",
863 .symbols = .{
864 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
865 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
866 },
867 .encode = .{ .sub, .Wd, .wzr, .{ .register = .Wm } },
868 },
869 .{
870 .pattern = "NEG <Wd>, <Wm>, <shift> #<amount>",
871 .symbols = .{
872 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
873 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
874 .shift = .{ .shift = .{ .allow_ror = false } },
875 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
876 },
877 .encode = .{ .sub, .Wd, .wzr, .{ .shifted_register_explicit = .{ .register = .Wm, .shift = .shift, .amount = .amount } } },
878 },
879 .{
880 .pattern = "NEG <Xd>, <Xm>",
881 .symbols = .{
882 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
883 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
884 },
885 .encode = .{ .sub, .Xd, .xzr, .{ .register = .Xm } },
886 },
887 .{
888 .pattern = "NEG <Xd>, <Xm>, <shift> #<amount>",
889 .symbols = .{
890 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
891 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
892 .shift = .{ .shift = .{ .allow_ror = false } },
893 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
894 },
895 .encode = .{ .sub, .Xd, .xzr, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } },
896 },
897 // C6.2.238 NOP
898 .{
899 .pattern = "NOP",
900 .symbols = .{},
901 .encode = .{.nop},
902 },
903 // C6.2.241 ORR (shifted register)
904 .{
905 .pattern = "ORR <Wd>, <Wn>, <Wm>",
906 .symbols = .{
907 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
908 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
909 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
910 },
911 .encode = .{ .orr, .Wd, .Wn, .{ .register = .Wm } },
912 },
913 .{
914 .pattern = "ORR <Wd>, <Wn>, <Wm>, <shift> #<amount>",
915 .symbols = .{
916 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
917 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
918 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
919 .shift = .{ .shift = .{} },
920 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
921 },
922 .encode = .{ .orr, .Wd, .Wn, .{ .shifted_register_explicit = .{ .register = .Wm, .shift = .shift, .amount = .amount } } },
923 },
924 .{
925 .pattern = "ORR <Xd>, <Xn>, <Xm>",
926 .symbols = .{
927 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
928 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
929 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
930 },
931 .encode = .{ .orr, .Xd, .Xn, .{ .register = .Xm } },
932 },
933 .{
934 .pattern = "ORR <Xd>, <Xn>, <Xm>, <shift> #<amount>",
935 .symbols = .{
936 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
937 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
938 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
939 .shift = .{ .shift = .{} },
940 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
941 },
942 .encode = .{ .orr, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } },
943 },
944 // C6.2.254 RET
945 .{
946 .pattern = "RET",
947 .symbols = .{},
948 .encode = .{ .ret, .x30 },
949 },
950 .{
951 .pattern = "RET <Xn>",
952 .symbols = .{
953 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
954 },
955 .encode = .{ .ret, .Xn },
956 },
957 // C6.2.268 SBFM
958 .{
959 .pattern = "SBFM <Wd>, <Wn>, #<immr>, #<imms>",
960 .symbols = .{
961 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
962 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
963 .immr = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
964 .imms = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
965 },
966 .encode = .{ .sbfm, .Wd, .Wn, .{ .N = .word, .immr = .immr, .imms = .imms } },
967 },
968 .{
969 .pattern = "SBFM <Xd>, <Xn>, #<immr>, #<imms>",
970 .symbols = .{
971 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
972 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
973 .immr = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
974 .imms = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
975 },
976 .encode = .{ .sbfm, .Xd, .Xn, .{ .N = .doubleword, .immr = .immr, .imms = .imms } },
977 },
978 // C6.2.280 SEV
979 .{
980 .pattern = "SEV",
981 .symbols = .{},
982 .encode = .{.sev},
983 },
984 // C6.2.281 SEVL
985 .{
986 .pattern = "SEVL",
987 .symbols = .{},
988 .encode = .{.sevl},
989 },
990 // C6.2.283 SMC
991 .{
992 .pattern = "SMC #<imm>",
993 .symbols = .{
994 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
995 },
996 .encode = .{ .smc, .imm },
997 },
998 // C6.2.321 STP
999 .{
1000 .pattern = "STP <Wt1>, <Wt2>, [<Xn|SP>], #<imm>",
1001 .symbols = .{
1002 .Wt1 = .{ .reg = .{ .format = .{ .integer = .word } } },
1003 .Wt2 = .{ .reg = .{ .format = .{ .integer = .word } } },
1004 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1005 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 }, .multiple_of = 4 } },
1006 },
1007 .encode = .{ .stp, .Wt1, .Wt2, .{ .post_index = .{ .base = .Xn, .index = .imm } } },
1008 },
1009 .{
1010 .pattern = "STP <Xt1>, <Xt2>, [<Xn|SP>], #<imm>",
1011 .symbols = .{
1012 .Xt1 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1013 .Xt2 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1014 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1015 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 10 }, .multiple_of = 8 } },
1016 },
1017 .encode = .{ .stp, .Xt1, .Xt2, .{ .post_index = .{ .base = .Xn, .index = .imm } } },
1018 },
1019 .{
1020 .pattern = "STP <Wt1>, <Wt2>, [<Xn|SP>, #<imm>]!",
1021 .symbols = .{
1022 .Wt1 = .{ .reg = .{ .format = .{ .integer = .word } } },
1023 .Wt2 = .{ .reg = .{ .format = .{ .integer = .word } } },
1024 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1025 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 }, .multiple_of = 4 } },
1026 },
1027 .encode = .{ .stp, .Wt1, .Wt2, .{ .pre_index = .{ .base = .Xn, .index = .imm } } },
1028 },
1029 .{
1030 .pattern = "STP <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]!",
1031 .symbols = .{
1032 .Xt1 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1033 .Xt2 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1034 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1035 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 10 }, .multiple_of = 8 } },
1036 },
1037 .encode = .{ .stp, .Xt1, .Xt2, .{ .pre_index = .{ .base = .Xn, .index = .imm } } },
1038 },
1039 .{
1040 .pattern = "STP <Wt1>, <Wt2>, [<Xn|SP>]",
1041 .symbols = .{
1042 .Wt1 = .{ .reg = .{ .format = .{ .integer = .word } } },
1043 .Wt2 = .{ .reg = .{ .format = .{ .integer = .word } } },
1044 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1045 },
1046 .encode = .{ .stp, .Wt1, .Wt2, .{ .base = .Xn } },
1047 },
1048 .{
1049 .pattern = "STP <Wt1>, <Wt2>, [<Xn|SP>, #<imm>]",
1050 .symbols = .{
1051 .Wt1 = .{ .reg = .{ .format = .{ .integer = .word } } },
1052 .Wt2 = .{ .reg = .{ .format = .{ .integer = .word } } },
1053 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1054 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 }, .multiple_of = 4 } },
1055 },
1056 .encode = .{ .stp, .Wt1, .Wt2, .{ .signed_offset = .{ .base = .Xn, .offset = .imm } } },
1057 },
1058 .{
1059 .pattern = "STP <Xt1>, <Xt2>, [<Xn|SP>]",
1060 .symbols = .{
1061 .Xt1 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1062 .Xt2 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1063 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1064 },
1065 .encode = .{ .stp, .Xt1, .Xt2, .{ .base = .Xn } },
1066 },
1067 .{
1068 .pattern = "STP <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]",
1069 .symbols = .{
1070 .Xt1 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1071 .Xt2 = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1072 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1073 .imm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 10 }, .multiple_of = 8 } },
1074 },
1075 .encode = .{ .stp, .Xt1, .Xt2, .{ .signed_offset = .{ .base = .Xn, .offset = .imm } } },
1076 },
1077 // C6.2.322 STR (immediate)
1078 .{
1079 .pattern = "STR <Wt>, [<Xn|SP>], #<simm>",
1080 .symbols = .{
1081 .Wt = .{ .reg = .{ .format = .{ .integer = .word } } },
1082 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1083 .simm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 } } },
1084 },
1085 .encode = .{ .str, .Wt, .{ .post_index = .{ .base = .Xn, .index = .simm } } },
1086 },
1087 .{
1088 .pattern = "STR <Xt>, [<Xn|SP>], #<simm>",
1089 .symbols = .{
1090 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1091 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1092 .simm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 } } },
1093 },
1094 .encode = .{ .str, .Xt, .{ .post_index = .{ .base = .Xn, .index = .simm } } },
1095 },
1096 .{
1097 .pattern = "STR <Wt>, [<Xn|SP>, #<simm>]!",
1098 .symbols = .{
1099 .Wt = .{ .reg = .{ .format = .{ .integer = .word } } },
1100 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1101 .simm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 } } },
1102 },
1103 .encode = .{ .str, .Wt, .{ .pre_index = .{ .base = .Xn, .index = .simm } } },
1104 },
1105 .{
1106 .pattern = "STR <Xt>, [<Xn|SP>, #<simm>]!",
1107 .symbols = .{
1108 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1109 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1110 .simm = .{ .imm = .{ .type = .{ .signedness = .signed, .bits = 9 } } },
1111 },
1112 .encode = .{ .str, .Xt, .{ .pre_index = .{ .base = .Xn, .index = .simm } } },
1113 },
1114 .{
1115 .pattern = "STR <Wt>, [<Xn|SP>]",
1116 .symbols = .{
1117 .Wt = .{ .reg = .{ .format = .{ .integer = .word } } },
1118 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1119 },
1120 .encode = .{ .str, .Wt, .{ .base = .Xn } },
1121 },
1122 .{
1123 .pattern = "STR <Wt>, [<Xn|SP>, #<pimm>]",
1124 .symbols = .{
1125 .Wt = .{ .reg = .{ .format = .{ .integer = .word } } },
1126 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1127 .pimm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 14 }, .multiple_of = 4 } },
1128 },
1129 .encode = .{ .str, .Wt, .{ .unsigned_offset = .{ .base = .Xn, .offset = .pimm } } },
1130 },
1131 .{
1132 .pattern = "STR <Xt>, [<Xn|SP>]",
1133 .symbols = .{
1134 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1135 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1136 },
1137 .encode = .{ .str, .Xt, .{ .base = .Xn } },
1138 },
1139 .{
1140 .pattern = "STR <Xt>, [<Xn|SP>, #<pimm>]",
1141 .symbols = .{
1142 .Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1143 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1144 .pimm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 15 }, .multiple_of = 8 } },
1145 },
1146 .encode = .{ .str, .Xt, .{ .unsigned_offset = .{ .base = .Xn, .offset = .pimm } } },
1147 },
1148 // C6.2.356 SUB (extended register)
1149 .{
1150 .pattern = "SUB <Wd|WSP>, <Wn|WSP>, <Wm>",
1151 .symbols = .{
1152 .Wd = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
1153 .Wn = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
1154 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
1155 },
1156 .encode = .{ .sub, .Wd, .Wn, .{ .register = .Wm } },
1157 },
1158 .{
1159 .pattern = "SUB <Wd|WSP>, <Wn|WSP>, <Wm>, <extend> #<amount>",
1160 .symbols = .{
1161 .Wd = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
1162 .Wn = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
1163 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
1164 .extend = .{ .extend = .{ .size = .word } },
1165 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
1166 },
1167 .encode = .{ .sub, .Wd, .Wn, .{ .extended_register_explicit = .{ .register = .Wm, .option = .extend, .amount = .amount } } },
1168 },
1169 .{
1170 .pattern = "SUB <Xd|SP>, <Xn|SP>, <Xm>",
1171 .symbols = .{
1172 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1173 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1174 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1175 },
1176 .encode = .{ .sub, .Xd, .Xn, .{ .register = .Xm } },
1177 },
1178 .{
1179 .pattern = "SUB <Xd|SP>, <Xn|SP>, <Wm>, <extend> #<amount>",
1180 .symbols = .{
1181 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1182 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1183 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
1184 .extend = .{ .extend = .{ .size = .word } },
1185 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
1186 },
1187 .encode = .{ .sub, .Xd, .Xn, .{ .extended_register_explicit = .{ .register = .Wm, .option = .extend, .amount = .amount } } },
1188 },
1189 .{
1190 .pattern = "SUB <Xd|SP>, <Xn|SP>, <Xm>, <extend> #<amount>",
1191 .symbols = .{
1192 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1193 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1194 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1195 .extend = .{ .extend = .{ .size = .doubleword } },
1196 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
1197 },
1198 .encode = .{ .sub, .Xd, .Xn, .{ .extended_register_explicit = .{ .register = .Xm, .option = .extend, .amount = .amount } } },
1199 },
1200 // C6.2.357 SUB (immediate)
1201 .{
1202 .pattern = "SUB <Wd|WSP>, <Wn|WSP>, #<imm>",
1203 .symbols = .{
1204 .Wd = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
1205 .Wn = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
1206 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
1207 },
1208 .encode = .{ .sub, .Wd, .Wn, .{ .immediate = .imm } },
1209 },
1210 .{
1211 .pattern = "SUB <Wd|WSP>, <Wn|WSP>, #<imm>, LSL #<shift>",
1212 .symbols = .{
1213 .Wd = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
1214 .Wn = .{ .reg = .{ .format = .{ .integer = .word }, .allow_sp = true } },
1215 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
1216 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
1217 },
1218 .encode = .{ .sub, .Wd, .Wn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
1219 },
1220 .{
1221 .pattern = "SUB <Xd|SP>, <Xn|SP>, #<imm>",
1222 .symbols = .{
1223 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1224 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1225 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
1226 },
1227 .encode = .{ .sub, .Xd, .Xn, .{ .immediate = .imm } },
1228 },
1229 .{
1230 .pattern = "SUB <Xd|SP>, <Xn|SP>, #<imm>, LSL #<shift>",
1231 .symbols = .{
1232 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1233 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword }, .allow_sp = true } },
1234 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
1235 .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
1236 },
1237 .encode = .{ .sub, .Xd, .Xn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
1238 },
1239 // C6.2.358 SUB (shifted register)
1240 .{
1241 .pattern = "SUB <Wd>, <Wn>, <Wm>",
1242 .symbols = .{
1243 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
1244 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
1245 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
1246 },
1247 .encode = .{ .sub, .Wd, .Wn, .{ .register = .Wm } },
1248 },
1249 .{
1250 .pattern = "SUB <Wd>, <Wn>, <Wm>, <shift> #<amount>",
1251 .symbols = .{
1252 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
1253 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
1254 .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
1255 .shift = .{ .shift = .{ .allow_ror = false } },
1256 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
1257 },
1258 .encode = .{ .sub, .Wd, .Wn, .{ .shifted_register_explicit = .{ .register = .Wm, .shift = .shift, .amount = .amount } } },
1259 },
1260 .{
1261 .pattern = "SUB <Xd>, <Xn>, <Xm>",
1262 .symbols = .{
1263 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1264 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1265 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1266 },
1267 .encode = .{ .sub, .Xd, .Xn, .{ .register = .Xm } },
1268 },
1269 .{
1270 .pattern = "SUB <Xd>, <Xn>, <Xm>, <shift> #<amount>",
1271 .symbols = .{
1272 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1273 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1274 .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1275 .shift = .{ .shift = .{ .allow_ror = false } },
1276 .amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
1277 },
1278 .encode = .{ .sub, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } },
1279 },
1280 // C6.2.365 SVC
1281 .{
1282 .pattern = "SVC #<imm>",
1283 .symbols = .{
1284 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
1285 },
1286 .encode = .{ .svc, .imm },
1287 },
1288 // C6.2.376 TCANCEL
1289 .{
1290 .pattern = "TCANCEL #<imm>",
1291 .symbols = .{
1292 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
1293 },
1294 .encode = .{ .tcancel, .imm },
1295 },
1296 // C6.2.385 UBFM
1297 .{
1298 .pattern = "UBFM <Wd>, <Wn>, #<immr>, #<imms>",
1299 .symbols = .{
1300 .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
1301 .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
1302 .immr = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
1303 .imms = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
1304 },
1305 .encode = .{ .ubfm, .Wd, .Wn, .{ .N = .word, .immr = .immr, .imms = .imms } },
1306 },
1307 .{
1308 .pattern = "UBFM <Xd>, <Xn>, #<immr>, #<imms>",
1309 .symbols = .{
1310 .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1311 .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
1312 .immr = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
1313 .imms = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
1314 },
1315 .encode = .{ .ubfm, .Xd, .Xn, .{ .N = .doubleword, .immr = .immr, .imms = .imms } },
1316 },
1317 // C6.2.387 UDF
1318 .{
1319 .pattern = "UDF #<imm>",
1320 .symbols = .{
1321 .imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 16 } } },
1322 },
1323 .encode = .{ .udf, .imm },
1324 },
1325 // C6.2.396 WFE
1326 .{
1327 .pattern = "WFE",
1328 .symbols = .{},
1329 .encode = .{.wfe},
1330 },
1331 // C6.2.398 WFI
1332 .{
1333 .pattern = "WFI",
1334 .symbols = .{},
1335 .encode = .{.wfi},
1336 },
1337 // C6.2.402 YIELD
1338 .{
1339 .pattern = "YIELD",
1340 .symbols = .{},
1341 .encode = .{.yield},
1342 },
1343}
src/codegen/c.zig+16-17
...@@ -449,14 +449,15 @@ pub const Function = struct {...@@ -449,14 +449,15 @@ pub const Function = struct {
449 if (gop.found_existing) return gop.value_ptr.*;449 if (gop.found_existing) return gop.value_ptr.*;
450450
451 const pt = f.object.dg.pt;451 const pt = f.object.dg.pt;
452 const zcu = pt.zcu;
452 const val = (try f.air.value(ref, pt)).?;453 const val = (try f.air.value(ref, pt)).?;
453 const ty = f.typeOf(ref);454 const ty = f.typeOf(ref);
454455
455 const result: CValue = if (lowersToArray(ty, pt)) result: {456 const result: CValue = if (lowersToArray(ty, zcu)) result: {
456 const ch = &f.object.code_header.writer;457 const ch = &f.object.code_header.writer;
457 const decl_c_value = try f.allocLocalValue(.{458 const decl_c_value = try f.allocLocalValue(.{
458 .ctype = try f.ctypeFromType(ty, .complete),459 .ctype = try f.ctypeFromType(ty, .complete),
459 .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(pt.zcu)),460 .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(zcu)),
460 });461 });
461 const gpa = f.object.dg.gpa;462 const gpa = f.object.dg.gpa;
462 try f.allocs.put(gpa, decl_c_value.new_local, false);463 try f.allocs.put(gpa, decl_c_value.new_local, false);
...@@ -916,7 +917,7 @@ pub const DeclGen = struct {...@@ -916,7 +917,7 @@ pub const DeclGen = struct {
916 // Ensure complete type definition is available before accessing fields.917 // Ensure complete type definition is available before accessing fields.
917 _ = try dg.ctypeFromType(parent_ptr_ty.childType(zcu), .complete);918 _ = try dg.ctypeFromType(parent_ptr_ty.childType(zcu), .complete);
918919
919 switch (fieldLocation(parent_ptr_ty, field.result_ptr_ty, field.field_idx, pt)) {920 switch (fieldLocation(parent_ptr_ty, field.result_ptr_ty, field.field_idx, zcu)) {
920 .begin => {921 .begin => {
921 const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete);922 const ptr_ctype = try dg.ctypeFromType(field.result_ptr_ty, .complete);
922 try w.writeByte('(');923 try w.writeByte('(');
...@@ -3008,7 +3009,7 @@ pub fn generate(...@@ -3008,7 +3009,7 @@ pub fn generate(
3008 src_loc: Zcu.LazySrcLoc,3009 src_loc: Zcu.LazySrcLoc,
3009 func_index: InternPool.Index,3010 func_index: InternPool.Index,
3010 air: *const Air,3011 air: *const Air,
3011 liveness: *const Air.Liveness,3012 liveness: *const ?Air.Liveness,
3012) @import("../codegen.zig").CodeGenError!Mir {3013) @import("../codegen.zig").CodeGenError!Mir {
3013 const zcu = pt.zcu;3014 const zcu = pt.zcu;
3014 const gpa = zcu.gpa;3015 const gpa = zcu.gpa;
...@@ -3021,7 +3022,7 @@ pub fn generate(...@@ -3021,7 +3022,7 @@ pub fn generate(
3021 var function: Function = .{3022 var function: Function = .{
3022 .value_map = .init(gpa),3023 .value_map = .init(gpa),
3023 .air = air.*,3024 .air = air.*,
3024 .liveness = liveness.*,3025 .liveness = liveness.*.?,
3025 .func_index = func_index,3026 .func_index = func_index,
3026 .object = .{3027 .object = .{
3027 .dg = .{3028 .dg = .{
...@@ -3961,7 +3962,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3961,7 +3962,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3961 ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte)3962 ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte)
3962 else3963 else
3963 true;3964 true;
3964 const is_array = lowersToArray(src_ty, pt);3965 const is_array = lowersToArray(src_ty, zcu);
3965 const need_memcpy = !is_aligned or is_array;3966 const need_memcpy = !is_aligned or is_array;
39663967
3967 const w = &f.object.code.writer;3968 const w = &f.object.code.writer;
...@@ -4044,7 +4045,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {...@@ -4044,7 +4045,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void {
4044 const operand = try f.resolveInst(un_op);4045 const operand = try f.resolveInst(un_op);
4045 try reap(f, inst, &.{un_op});4046 try reap(f, inst, &.{un_op});
4046 var deref = is_ptr;4047 var deref = is_ptr;
4047 const is_array = lowersToArray(ret_ty, pt);4048 const is_array = lowersToArray(ret_ty, zcu);
4048 const ret_val = if (is_array) ret_val: {4049 const ret_val = if (is_array) ret_val: {
4049 const array_local = try f.allocAlignedLocal(inst, .{4050 const array_local = try f.allocAlignedLocal(inst, .{
4050 .ctype = ret_ctype,4051 .ctype = ret_ctype,
...@@ -4228,7 +4229,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {...@@ -4228,7 +4229,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
4228 ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte)4229 ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte)
4229 else4230 else
4230 true;4231 true;
4231 const is_array = lowersToArray(.fromInterned(ptr_info.child), pt);4232 const is_array = lowersToArray(.fromInterned(ptr_info.child), zcu);
4232 const need_memcpy = !is_aligned or is_array;4233 const need_memcpy = !is_aligned or is_array;
42334234
4234 const src_val = try f.resolveInst(bin_op.rhs);4235 const src_val = try f.resolveInst(bin_op.rhs);
...@@ -4873,7 +4874,7 @@ fn airCall(...@@ -4873,7 +4874,7 @@ fn airCall(
4873 }4874 }
48744875
4875 const result = result: {4876 const result = result: {
4876 if (result_local == .none or !lowersToArray(ret_ty, pt))4877 if (result_local == .none or !lowersToArray(ret_ty, zcu))
4877 break :result result_local;4878 break :result result_local;
48784879
4879 const array_local = try f.allocLocal(inst, ret_ty);4880 const array_local = try f.allocLocal(inst, ret_ty);
...@@ -5971,13 +5972,12 @@ fn fieldLocation(...@@ -5971,13 +5972,12 @@ fn fieldLocation(
5971 container_ptr_ty: Type,5972 container_ptr_ty: Type,
5972 field_ptr_ty: Type,5973 field_ptr_ty: Type,
5973 field_index: u32,5974 field_index: u32,
5974 pt: Zcu.PerThread,5975 zcu: *Zcu,
5975) union(enum) {5976) union(enum) {
5976 begin: void,5977 begin: void,
5977 field: CValue,5978 field: CValue,
5978 byte_offset: u64,5979 byte_offset: u64,
5979} {5980} {
5980 const zcu = pt.zcu;
5981 const ip = &zcu.intern_pool;5981 const ip = &zcu.intern_pool;
5982 const container_ty: Type = .fromInterned(ip.indexToKey(container_ptr_ty.toIntern()).ptr_type.child);5982 const container_ty: Type = .fromInterned(ip.indexToKey(container_ptr_ty.toIntern()).ptr_type.child);
5983 switch (ip.indexToKey(container_ty.toIntern())) {5983 switch (ip.indexToKey(container_ty.toIntern())) {
...@@ -5994,7 +5994,7 @@ fn fieldLocation(...@@ -5994,7 +5994,7 @@ fn fieldLocation(
5994 else5994 else
5995 .{ .field = field_index } },5995 .{ .field = field_index } },
5996 .@"packed" => if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0)5996 .@"packed" => if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0)
5997 .{ .byte_offset = @divExact(pt.structPackedFieldBitOffset(loaded_struct, field_index) +5997 .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(loaded_struct, field_index) +
5998 container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) }5998 container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) }
5999 else5999 else
6000 .begin,6000 .begin,
...@@ -6076,7 +6076,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6076,7 +6076,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
6076 try f.renderType(w, container_ptr_ty);6076 try f.renderType(w, container_ptr_ty);
6077 try w.writeByte(')');6077 try w.writeByte(')');
60786078
6079 switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, pt)) {6079 switch (fieldLocation(container_ptr_ty, field_ptr_ty, extra.field_index, zcu)) {
6080 .begin => try f.writeCValue(w, field_ptr_val, .Other),6080 .begin => try f.writeCValue(w, field_ptr_val, .Other),
6081 .field => |field| {6081 .field => |field| {
6082 const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);6082 const u8_ptr_ty = try pt.adjustPtrTypeChild(field_ptr_ty, .u8);
...@@ -6131,7 +6131,7 @@ fn fieldPtr(...@@ -6131,7 +6131,7 @@ fn fieldPtr(
6131 try f.renderType(w, field_ptr_ty);6131 try f.renderType(w, field_ptr_ty);
6132 try w.writeByte(')');6132 try w.writeByte(')');
61336133
6134 switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, pt)) {6134 switch (fieldLocation(container_ptr_ty, field_ptr_ty, field_index, zcu)) {
6135 .begin => try f.writeCValue(w, container_ptr_val, .Other),6135 .begin => try f.writeCValue(w, container_ptr_val, .Other),
6136 .field => |field| {6136 .field => |field| {
6137 try w.writeByte('&');6137 try w.writeByte('&');
...@@ -6189,7 +6189,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6189,7 +6189,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
61896189
6190 const bit_offset_ty = try pt.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));6190 const bit_offset_ty = try pt.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
61916191
6192 const bit_offset = pt.structPackedFieldBitOffset(loaded_struct, extra.field_index);6192 const bit_offset = zcu.structPackedFieldBitOffset(loaded_struct, extra.field_index);
61936193
6194 const field_int_signedness = if (inst_ty.isAbiInt(zcu))6194 const field_int_signedness = if (inst_ty.isAbiInt(zcu))
6195 inst_ty.intInfo(zcu).signedness6195 inst_ty.intInfo(zcu).signedness
...@@ -8573,8 +8573,7 @@ const Vectorize = struct {...@@ -8573,8 +8573,7 @@ const Vectorize = struct {
8573 }8573 }
8574};8574};
85758575
8576fn lowersToArray(ty: Type, pt: Zcu.PerThread) bool {8576fn lowersToArray(ty: Type, zcu: *Zcu) bool {
8577 const zcu = pt.zcu;
8578 return switch (ty.zigTypeTag(zcu)) {8577 return switch (ty.zigTypeTag(zcu)) {
8579 .array, .vector => return true,8578 .array, .vector => return true,
8580 else => return ty.isAbiInt(zcu) and toCIntBits(@as(u32, @intCast(ty.bitSize(zcu)))) == null,8579 else => return ty.isAbiInt(zcu) and toCIntBits(@as(u32, @intCast(ty.bitSize(zcu)))) == null,
src/codegen/llvm.zig+9-8
...@@ -20,6 +20,7 @@ const Package = @import("../Package.zig");...@@ -20,6 +20,7 @@ const Package = @import("../Package.zig");
20const Air = @import("../Air.zig");20const Air = @import("../Air.zig");
21const Value = @import("../Value.zig");21const Value = @import("../Value.zig");
22const Type = @import("../Type.zig");22const Type = @import("../Type.zig");
23const codegen = @import("../codegen.zig");
23const x86_64_abi = @import("../arch/x86_64/abi.zig");24const x86_64_abi = @import("../arch/x86_64/abi.zig");
24const wasm_c_abi = @import("wasm/abi.zig");25const wasm_c_abi = @import("wasm/abi.zig");
25const aarch64_c_abi = @import("aarch64/abi.zig");26const aarch64_c_abi = @import("aarch64/abi.zig");
...@@ -1131,7 +1132,7 @@ pub const Object = struct {...@@ -1131,7 +1132,7 @@ pub const Object = struct {
1131 pt: Zcu.PerThread,1132 pt: Zcu.PerThread,
1132 func_index: InternPool.Index,1133 func_index: InternPool.Index,
1133 air: *const Air,1134 air: *const Air,
1134 liveness: *const Air.Liveness,1135 liveness: *const ?Air.Liveness,
1135 ) !void {1136 ) !void {
1136 const zcu = pt.zcu;1137 const zcu = pt.zcu;
1137 const comp = zcu.comp;1138 const comp = zcu.comp;
...@@ -1489,7 +1490,7 @@ pub const Object = struct {...@@ -1489,7 +1490,7 @@ pub const Object = struct {
1489 var fg: FuncGen = .{1490 var fg: FuncGen = .{
1490 .gpa = gpa,1491 .gpa = gpa,
1491 .air = air.*,1492 .air = air.*,
1492 .liveness = liveness.*,1493 .liveness = liveness.*.?,
1493 .ng = &ng,1494 .ng = &ng,
1494 .wip = wip,1495 .wip = wip,
1495 .is_naked = fn_info.cc == .naked,1496 .is_naked = fn_info.cc == .naked,
...@@ -4210,7 +4211,7 @@ pub const Object = struct {...@@ -4210,7 +4211,7 @@ pub const Object = struct {
4210 .eu_payload => |eu_ptr| try o.lowerPtr(4211 .eu_payload => |eu_ptr| try o.lowerPtr(
4211 pt,4212 pt,
4212 eu_ptr,4213 eu_ptr,
4213 offset + @import("../codegen.zig").errUnionPayloadOffset(4214 offset + codegen.errUnionPayloadOffset(
4214 Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu),4215 Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu),
4215 zcu,4216 zcu,
4216 ),4217 ),
...@@ -6050,10 +6051,10 @@ pub const FuncGen = struct {...@@ -6050,10 +6051,10 @@ pub const FuncGen = struct {
6050 const target_blocks = dispatch_info.case_blocks[0..target_blocks_len];6051 const target_blocks = dispatch_info.case_blocks[0..target_blocks_len];
60516052
6052 // Make sure to cast the index to a usize so it's not treated as negative!6053 // Make sure to cast the index to a usize so it's not treated as negative!
6053 const table_index = try self.wip.cast(6054 const table_index = try self.wip.conv(
6054 .zext,6055 .unsigned,
6055 try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""),6056 try self.wip.bin(.@"sub nuw", cond, jmp_table.min.toValue(), ""),
6056 try o.lowerType(pt, Type.usize),6057 try o.lowerType(pt, .usize),
6057 "",6058 "",
6058 );6059 );
6059 const target_ptr_ptr = try self.wip.gep(6060 const target_ptr_ptr = try self.wip.gep(
...@@ -6969,7 +6970,7 @@ pub const FuncGen = struct {...@@ -6969,7 +6970,7 @@ pub const FuncGen = struct {
6969 .@"struct" => switch (struct_ty.containerLayout(zcu)) {6970 .@"struct" => switch (struct_ty.containerLayout(zcu)) {
6970 .@"packed" => {6971 .@"packed" => {
6971 const struct_type = zcu.typeToStruct(struct_ty).?;6972 const struct_type = zcu.typeToStruct(struct_ty).?;
6972 const bit_offset = pt.structPackedFieldBitOffset(struct_type, field_index);6973 const bit_offset = zcu.structPackedFieldBitOffset(struct_type, field_index);
6973 const containing_int = struct_llvm_val;6974 const containing_int = struct_llvm_val;
6974 const shift_amt =6975 const shift_amt =
6975 try o.builder.intValue(containing_int.typeOfWip(&self.wip), bit_offset);6976 try o.builder.intValue(containing_int.typeOfWip(&self.wip), bit_offset);
...@@ -11364,7 +11365,7 @@ pub const FuncGen = struct {...@@ -11364,7 +11365,7 @@ pub const FuncGen = struct {
1136411365
11365 // We have a pointer to a packed struct field that happens to be byte-aligned.11366 // We have a pointer to a packed struct field that happens to be byte-aligned.
11366 // Offset our operand pointer by the correct number of bytes.11367 // Offset our operand pointer by the correct number of bytes.
11367 const byte_offset = @divExact(pt.structPackedFieldBitOffset(struct_type, field_index) + struct_ptr_ty_info.packed_offset.bit_offset, 8);11368 const byte_offset = @divExact(zcu.structPackedFieldBitOffset(struct_type, field_index) + struct_ptr_ty_info.packed_offset.bit_offset, 8);
11368 if (byte_offset == 0) return struct_ptr;11369 if (byte_offset == 0) return struct_ptr;
11369 const usize_ty = try o.lowerType(pt, Type.usize);11370 const usize_ty = try o.lowerType(pt, Type.usize);
11370 const llvm_index = try o.builder.intValue(usize_ty, byte_offset);11371 const llvm_index = try o.builder.intValue(usize_ty, byte_offset);
src/codegen/spirv.zig+3-3
...@@ -251,11 +251,11 @@ pub const Object = struct {...@@ -251,11 +251,11 @@ pub const Object = struct {
251 pt: Zcu.PerThread,251 pt: Zcu.PerThread,
252 func_index: InternPool.Index,252 func_index: InternPool.Index,
253 air: *const Air,253 air: *const Air,
254 liveness: *const Air.Liveness,254 liveness: *const ?Air.Liveness,
255 ) !void {255 ) !void {
256 const nav = pt.zcu.funcInfo(func_index).owner_nav;256 const nav = pt.zcu.funcInfo(func_index).owner_nav;
257 // TODO: Separate types for generating decls and functions?257 // TODO: Separate types for generating decls and functions?
258 try self.genNav(pt, nav, air.*, liveness.*, true);258 try self.genNav(pt, nav, air.*, liveness.*.?, true);
259 }259 }
260260
261 pub fn updateNav(261 pub fn updateNav(
...@@ -5134,7 +5134,7 @@ const NavGen = struct {...@@ -5134,7 +5134,7 @@ const NavGen = struct {
5134 .@"struct" => switch (object_ty.containerLayout(zcu)) {5134 .@"struct" => switch (object_ty.containerLayout(zcu)) {
5135 .@"packed" => {5135 .@"packed" => {
5136 const struct_ty = zcu.typeToPackedStruct(object_ty).?;5136 const struct_ty = zcu.typeToPackedStruct(object_ty).?;
5137 const bit_offset = pt.structPackedFieldBitOffset(struct_ty, field_index);5137 const bit_offset = zcu.structPackedFieldBitOffset(struct_ty, field_index);
5138 const bit_offset_id = try self.constInt(.u16, bit_offset);5138 const bit_offset_id = try self.constInt(.u16, bit_offset);
5139 const signedness = if (field_ty.isInt(zcu)) field_ty.intInfo(zcu).signedness else .unsigned;5139 const signedness = if (field_ty.isInt(zcu)) field_ty.intInfo(zcu).signedness else .unsigned;
5140 const field_bit_size: u16 = @intCast(field_ty.bitSize(zcu));5140 const field_bit_size: u16 = @intCast(field_ty.bitSize(zcu));
src/dev.zig+27-14
...@@ -25,13 +25,13 @@ pub const Env = enum {...@@ -25,13 +25,13 @@ pub const Env = enum {
25 /// - `zig build-* -fno-emit-bin`25 /// - `zig build-* -fno-emit-bin`
26 sema,26 sema,
2727
28 /// - sema
29 /// - `zig build-* -fincremental -fno-llvm -fno-lld -target aarch64-linux --listen=-`
30 @"aarch64-linux",
31
28 /// - `zig build-* -ofmt=c`32 /// - `zig build-* -ofmt=c`
29 cbe,33 cbe,
3034
31 /// - sema
32 /// - `zig build-* -fincremental -fno-llvm -fno-lld -target x86_64-linux --listen=-`
33 @"x86_64-linux",
34
35 /// - sema35 /// - sema
36 /// - `zig build-* -fincremental -fno-llvm -fno-lld -target powerpc(64)(le)-linux --listen=-`36 /// - `zig build-* -fincremental -fno-llvm -fno-lld -target powerpc(64)(le)-linux --listen=-`
37 @"powerpc-linux",37 @"powerpc-linux",
...@@ -48,6 +48,10 @@ pub const Env = enum {...@@ -48,6 +48,10 @@ pub const Env = enum {
48 /// - `zig build-* -fno-llvm -fno-lld -target wasm32-* --listen=-`48 /// - `zig build-* -fno-llvm -fno-lld -target wasm32-* --listen=-`
49 wasm,49 wasm,
5050
51 /// - sema
52 /// - `zig build-* -fincremental -fno-llvm -fno-lld -target x86_64-linux --listen=-`
53 @"x86_64-linux",
54
51 pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool {55 pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool {
52 return switch (dev_env) {56 return switch (dev_env) {
53 .full => true,57 .full => true,
...@@ -153,23 +157,22 @@ pub const Env = enum {...@@ -153,23 +157,22 @@ pub const Env = enum {
153 => true,157 => true,
154 else => Env.ast_gen.supports(feature),158 else => Env.ast_gen.supports(feature),
155 },159 },
156 .cbe => switch (feature) {160 .@"aarch64-linux" => switch (feature) {
157 .legalize,
158 .c_backend,
159 .c_linker,
160 => true,
161 else => Env.sema.supports(feature),
162 },
163 .@"x86_64-linux" => switch (feature) {
164 .build_command,161 .build_command,
165 .stdio_listen,162 .stdio_listen,
166 .incremental,163 .incremental,
167 .legalize,164 .aarch64_backend,
168 .x86_64_backend,
169 .elf_linker,165 .elf_linker,
170 => true,166 => true,
171 else => Env.sema.supports(feature),167 else => Env.sema.supports(feature),
172 },168 },
169 .cbe => switch (feature) {
170 .legalize,
171 .c_backend,
172 .c_linker,
173 => true,
174 else => Env.sema.supports(feature),
175 },
173 .@"powerpc-linux" => switch (feature) {176 .@"powerpc-linux" => switch (feature) {
174 .build_command,177 .build_command,
175 .stdio_listen,178 .stdio_listen,
...@@ -199,6 +202,16 @@ pub const Env = enum {...@@ -199,6 +202,16 @@ pub const Env = enum {
199 => true,202 => true,
200 else => Env.sema.supports(feature),203 else => Env.sema.supports(feature),
201 },204 },
205 .@"x86_64-linux" => switch (feature) {
206 .build_command,
207 .stdio_listen,
208 .incremental,
209 .legalize,
210 .x86_64_backend,
211 .elf_linker,
212 => true,
213 else => Env.sema.supports(feature),
214 },
202 };215 };
203 }216 }
204217
src/link.zig+1
...@@ -23,6 +23,7 @@ const dev = @import("dev.zig");...@@ -23,6 +23,7 @@ const dev = @import("dev.zig");
23const target_util = @import("target.zig");23const target_util = @import("target.zig");
24const codegen = @import("codegen.zig");24const codegen = @import("codegen.zig");
2525
26pub const aarch64 = @import("link/aarch64.zig");
26pub const LdScript = @import("link/LdScript.zig");27pub const LdScript = @import("link/LdScript.zig");
27pub const Queue = @import("link/Queue.zig");28pub const Queue = @import("link/Queue.zig");
2829
src/link/Coff.zig+26-52
...@@ -17,9 +17,9 @@ const Allocator = std.mem.Allocator;...@@ -17,9 +17,9 @@ const Allocator = std.mem.Allocator;
17const Path = std.Build.Cache.Path;17const Path = std.Build.Cache.Path;
18const Directory = std.Build.Cache.Directory;18const Directory = std.Build.Cache.Directory;
19const Cache = std.Build.Cache;19const Cache = std.Build.Cache;
20const Writer = std.io.Writer;20const Writer = std.Io.Writer;
2121
22const aarch64_util = @import("../arch/aarch64/bits.zig");22const aarch64_util = link.aarch64;
23const allocPrint = std.fmt.allocPrint;23const allocPrint = std.fmt.allocPrint;
24const codegen = @import("../codegen.zig");24const codegen = @import("../codegen.zig");
25const link = @import("../link.zig");25const link = @import("../link.zig");
...@@ -1371,9 +1371,13 @@ fn updateNavCode(...@@ -1371,9 +1371,13 @@ fn updateNavCode(
13711371
1372 log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });1372 log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
13731373
1374 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;1374 const mod = zcu.navFileScope(nav_index).mod.?;
1375 const required_alignment = switch (pt.navAlignment(nav_index)) {1375 const target = &mod.resolved_target.result;
1376 .none => target_util.defaultFunctionAlignment(target),1376 const required_alignment = switch (nav.status.fully_resolved.alignment) {
1377 .none => switch (mod.optimize_mode) {
1378 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
1379 .ReleaseSmall => target_util.minFunctionAlignment(target),
1380 },
1377 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),1381 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
1378 };1382 };
13791383
...@@ -2867,58 +2871,33 @@ pub const Relocation = struct {...@@ -2867,58 +2871,33 @@ pub const Relocation = struct {
2867 };2871 };
28682872
2869 fn resolveAarch64(reloc: Relocation, ctx: Context) void {2873 fn resolveAarch64(reloc: Relocation, ctx: Context) void {
2874 const Instruction = aarch64_util.encoding.Instruction;
2870 var buffer = ctx.code[reloc.offset..];2875 var buffer = ctx.code[reloc.offset..];
2871 switch (reloc.type) {2876 switch (reloc.type) {
2872 .got_page, .import_page, .page => {2877 .got_page, .import_page, .page => {
2873 const source_page = @as(i32, @intCast(ctx.source_vaddr >> 12));2878 const source_page = @as(i32, @intCast(ctx.source_vaddr >> 12));
2874 const target_page = @as(i32, @intCast(ctx.target_vaddr >> 12));2879 const target_page = @as(i32, @intCast(ctx.target_vaddr >> 12));
2875 const pages = @as(u21, @bitCast(@as(i21, @intCast(target_page - source_page))));2880 const pages: i21 = @intCast(target_page - source_page);
2876 var inst = aarch64_util.Instruction{2881 var inst: Instruction = .read(buffer[0..Instruction.size]);
2877 .pc_relative_address = mem.bytesToValue(@FieldType(2882 inst.data_processing_immediate.pc_relative_addressing.group.immhi = @intCast(pages >> 2);
2878 aarch64_util.Instruction,2883 inst.data_processing_immediate.pc_relative_addressing.group.immlo = @truncate(@as(u21, @bitCast(pages)));
2879 @tagName(aarch64_util.Instruction.pc_relative_address),2884 inst.write(buffer[0..Instruction.size]);
2880 ), buffer[0..4]),
2881 };
2882 inst.pc_relative_address.immhi = @as(u19, @truncate(pages >> 2));
2883 inst.pc_relative_address.immlo = @as(u2, @truncate(pages));
2884 mem.writeInt(u32, buffer[0..4], inst.toU32(), .little);
2885 },2885 },
2886 .got_pageoff, .import_pageoff, .pageoff => {2886 .got_pageoff, .import_pageoff, .pageoff => {
2887 assert(!reloc.pcrel);2887 assert(!reloc.pcrel);
28882888
2889 const narrowed = @as(u12, @truncate(@as(u64, @intCast(ctx.target_vaddr))));2889 const narrowed: u12 = @truncate(@as(u64, @intCast(ctx.target_vaddr)));
2890 if (isArithmeticOp(buffer[0..4])) {2890 var inst: Instruction = .read(buffer[0..Instruction.size]);
2891 var inst = aarch64_util.Instruction{2891 switch (inst.decode()) {
2892 .add_subtract_immediate = mem.bytesToValue(@FieldType(2892 else => unreachable,
2893 aarch64_util.Instruction,2893 .data_processing_immediate => inst.data_processing_immediate.add_subtract_immediate.group.imm12 = narrowed,
2894 @tagName(aarch64_util.Instruction.add_subtract_immediate),2894 .load_store => |load_store| inst.load_store.register_unsigned_immediate.group.imm12 =
2895 ), buffer[0..4]),2895 switch (load_store.register_unsigned_immediate.decode()) {
2896 };2896 .integer => |integer| @shrExact(narrowed, @intFromEnum(integer.group.size)),
2897 inst.add_subtract_immediate.imm12 = narrowed;2897 .vector => |vector| @shrExact(narrowed, @intFromEnum(vector.group.opc1.decode(vector.group.size))),
2898 mem.writeInt(u32, buffer[0..4], inst.toU32(), .little);2898 },
2899 } else {
2900 var inst = aarch64_util.Instruction{
2901 .load_store_register = mem.bytesToValue(@FieldType(
2902 aarch64_util.Instruction,
2903 @tagName(aarch64_util.Instruction.load_store_register),
2904 ), buffer[0..4]),
2905 };
2906 const offset: u12 = blk: {
2907 if (inst.load_store_register.size == 0) {
2908 if (inst.load_store_register.v == 1) {
2909 // 128-bit SIMD is scaled by 16.
2910 break :blk @divExact(narrowed, 16);
2911 }
2912 // Otherwise, 8-bit SIMD or ldrb.
2913 break :blk narrowed;
2914 } else {
2915 const denom: u4 = math.powi(u4, 2, inst.load_store_register.size) catch unreachable;
2916 break :blk @divExact(narrowed, denom);
2917 }
2918 };
2919 inst.load_store_register.offset = offset;
2920 mem.writeInt(u32, buffer[0..4], inst.toU32(), .little);
2921 }2899 }
2900 inst.write(buffer[0..Instruction.size]);
2922 },2901 },
2923 .direct => {2902 .direct => {
2924 assert(!reloc.pcrel);2903 assert(!reloc.pcrel);
...@@ -2969,11 +2948,6 @@ pub const Relocation = struct {...@@ -2969,11 +2948,6 @@ pub const Relocation = struct {
2969 },2948 },
2970 }2949 }
2971 }2950 }
2972
2973 fn isArithmeticOp(inst: *const [4]u8) bool {
2974 const group_decode = @as(u5, @truncate(inst[3]));
2975 return ((group_decode >> 2) == 4);
2976 }
2977};2951};
29782952
2979pub fn addRelocation(coff: *Coff, atom_index: Atom.Index, reloc: Relocation) !void {2953pub fn addRelocation(coff: *Coff, atom_index: Atom.Index, reloc: Relocation) !void {
src/link/Dwarf.zig+7-1
...@@ -2555,7 +2555,13 @@ fn initWipNavInner(...@@ -2555,7 +2555,13 @@ fn initWipNavInner(
2555 try wip_nav.strp(nav.fqn.toSlice(ip));2555 try wip_nav.strp(nav.fqn.toSlice(ip));
2556 const ty: Type = nav_val.typeOf(zcu);2556 const ty: Type = nav_val.typeOf(zcu);
2557 const addr: Loc = .{ .addr_reloc = sym_index };2557 const addr: Loc = .{ .addr_reloc = sym_index };
2558 const loc: Loc = if (decl.is_threadlocal) .{ .form_tls_address = &addr } else addr;2558 const loc: Loc = if (decl.is_threadlocal) loc: {
2559 const target = zcu.comp.root_mod.resolved_target.result;
2560 break :loc switch (target.cpu.arch) {
2561 .x86_64 => .{ .form_tls_address = &addr },
2562 else => .empty,
2563 };
2564 } else addr;
2559 switch (decl.kind) {2565 switch (decl.kind) {
2560 .unnamed_test, .@"test", .decltest, .@"comptime" => unreachable,2566 .unnamed_test, .@"test", .decltest, .@"comptime" => unreachable,
2561 .@"const" => {2567 .@"const" => {
src/link/Elf/Atom.zig+27-43
...@@ -1611,7 +1611,7 @@ const aarch64 = struct {...@@ -1611,7 +1611,7 @@ const aarch64 = struct {
1611 const S_ = th.targetAddress(target_index, elf_file);1611 const S_ = th.targetAddress(target_index, elf_file);
1612 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;1612 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
1613 };1613 };
1614 aarch64_util.writeBranchImm(disp, code);1614 util.writeBranchImm(disp, code);
1615 },1615 },
16161616
1617 .PREL32 => {1617 .PREL32 => {
...@@ -1624,15 +1624,18 @@ const aarch64 = struct {...@@ -1624,15 +1624,18 @@ const aarch64 = struct {
1624 try bw.writeInt(u64, @bitCast(value), .little);1624 try bw.writeInt(u64, @bitCast(value), .little);
1625 },1625 },
16261626
1627 .ADR_PREL_LO21 => {
1628 const value = math.cast(i21, S + A - P) orelse return error.Overflow;
1629 util.writeAdrInst(value, code);
1630 },
1631
1627 .ADR_PREL_PG_HI21 => {1632 .ADR_PREL_PG_HI21 => {
1628 // TODO: check for relaxation of ADRP+ADD1633 // TODO: check for relaxation of ADRP+ADD
1629 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(P, S + A)));1634 util.writeAdrInst(try util.calcNumberOfPages(P, S + A), code);
1630 aarch64_util.writeAdrpInst(pages, code);
1631 },1635 },
16321636
1633 .ADR_GOT_PAGE => if (target.flags.has_got) {1637 .ADR_GOT_PAGE => if (target.flags.has_got) {
1634 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(P, G + GOT + A)));1638 util.writeAdrInst(try util.calcNumberOfPages(P, G + GOT + A), code);
1635 aarch64_util.writeAdrpInst(pages, code);
1636 } else {1639 } else {
1637 // TODO: relax1640 // TODO: relax
1638 var err = try diags.addErrorWithNotes(1);1641 var err = try diags.addErrorWithNotes(1);
...@@ -1647,12 +1650,12 @@ const aarch64 = struct {...@@ -1647,12 +1650,12 @@ const aarch64 = struct {
1647 .LD64_GOT_LO12_NC => {1650 .LD64_GOT_LO12_NC => {
1648 assert(target.flags.has_got);1651 assert(target.flags.has_got);
1649 const taddr = @as(u64, @intCast(G + GOT + A));1652 const taddr = @as(u64, @intCast(G + GOT + A));
1650 aarch64_util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code);1653 util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code);
1651 },1654 },
16521655
1653 .ADD_ABS_LO12_NC => {1656 .ADD_ABS_LO12_NC => {
1654 const taddr = @as(u64, @intCast(S + A));1657 const taddr = @as(u64, @intCast(S + A));
1655 aarch64_util.writeAddImmInst(@truncate(taddr), code);1658 util.writeAddImmInst(@truncate(taddr), code);
1656 },1659 },
16571660
1658 .LDST8_ABS_LO12_NC,1661 .LDST8_ABS_LO12_NC,
...@@ -1671,57 +1674,54 @@ const aarch64 = struct {...@@ -1671,57 +1674,54 @@ const aarch64 = struct {
1671 .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16),1674 .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16),
1672 else => unreachable,1675 else => unreachable,
1673 };1676 };
1674 aarch64_util.writeLoadStoreRegInst(off, code);1677 util.writeLoadStoreRegInst(off, code);
1675 },1678 },
16761679
1677 .TLSLE_ADD_TPREL_HI12 => {1680 .TLSLE_ADD_TPREL_HI12 => {
1678 const value = math.cast(i12, (S + A - TP) >> 12) orelse1681 const value = math.cast(i12, (S + A - TP) >> 12) orelse
1679 return error.Overflow;1682 return error.Overflow;
1680 aarch64_util.writeAddImmInst(@bitCast(value), code);1683 util.writeAddImmInst(@bitCast(value), code);
1681 },1684 },
16821685
1683 .TLSLE_ADD_TPREL_LO12_NC => {1686 .TLSLE_ADD_TPREL_LO12_NC => {
1684 const value: i12 = @truncate(S + A - TP);1687 const value: i12 = @truncate(S + A - TP);
1685 aarch64_util.writeAddImmInst(@bitCast(value), code);1688 util.writeAddImmInst(@bitCast(value), code);
1686 },1689 },
16871690
1688 .TLSIE_ADR_GOTTPREL_PAGE21 => {1691 .TLSIE_ADR_GOTTPREL_PAGE21 => {
1689 const S_ = target.gotTpAddress(elf_file);1692 const S_ = target.gotTpAddress(elf_file);
1690 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });1693 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
1691 const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A));1694 util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code);
1692 aarch64_util.writeAdrpInst(pages, code);
1693 },1695 },
16941696
1695 .TLSIE_LD64_GOTTPREL_LO12_NC => {1697 .TLSIE_LD64_GOTTPREL_LO12_NC => {
1696 const S_ = target.gotTpAddress(elf_file);1698 const S_ = target.gotTpAddress(elf_file);
1697 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });1699 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
1698 const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8);1700 const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8);
1699 aarch64_util.writeLoadStoreRegInst(off, code);1701 util.writeLoadStoreRegInst(off, code);
1700 },1702 },
17011703
1702 .TLSGD_ADR_PAGE21 => {1704 .TLSGD_ADR_PAGE21 => {
1703 const S_ = target.tlsGdAddress(elf_file);1705 const S_ = target.tlsGdAddress(elf_file);
1704 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });1706 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
1705 const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A));1707 util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code);
1706 aarch64_util.writeAdrpInst(pages, code);
1707 },1708 },
17081709
1709 .TLSGD_ADD_LO12_NC => {1710 .TLSGD_ADD_LO12_NC => {
1710 const S_ = target.tlsGdAddress(elf_file);1711 const S_ = target.tlsGdAddress(elf_file);
1711 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });1712 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
1712 const off: u12 = @truncate(@as(u64, @bitCast(S_ + A)));1713 const off: u12 = @truncate(@as(u64, @bitCast(S_ + A)));
1713 aarch64_util.writeAddImmInst(off, code);1714 util.writeAddImmInst(off, code);
1714 },1715 },
17151716
1716 .TLSDESC_ADR_PAGE21 => {1717 .TLSDESC_ADR_PAGE21 => {
1717 if (target.flags.has_tlsdesc) {1718 if (target.flags.has_tlsdesc) {
1718 const S_ = target.tlsDescAddress(elf_file);1719 const S_ = target.tlsDescAddress(elf_file);
1719 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });1720 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
1720 const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A));1721 util.writeAdrInst(try util.calcNumberOfPages(P, S_ + A), code);
1721 aarch64_util.writeAdrpInst(pages, code);
1722 } else {1722 } else {
1723 relocs_log.debug(" relaxing adrp => nop", .{});1723 relocs_log.debug(" relaxing adrp => nop", .{});
1724 mem.writeInt(u32, code, Instruction.nop().toU32(), .little);1724 util.encoding.Instruction.nop().write(code);
1725 }1725 }
1726 },1726 },
17271727
...@@ -1730,10 +1730,10 @@ const aarch64 = struct {...@@ -1730,10 +1730,10 @@ const aarch64 = struct {
1730 const S_ = target.tlsDescAddress(elf_file);1730 const S_ = target.tlsDescAddress(elf_file);
1731 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });1731 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
1732 const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8);1732 const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8);
1733 aarch64_util.writeLoadStoreRegInst(off, code);1733 util.writeLoadStoreRegInst(off, code);
1734 } else {1734 } else {
1735 relocs_log.debug(" relaxing ldr => nop", .{});1735 relocs_log.debug(" relaxing ldr => nop", .{});
1736 mem.writeInt(u32, code, Instruction.nop().toU32(), .little);1736 util.encoding.Instruction.nop().write(code);
1737 }1737 }
1738 },1738 },
17391739
...@@ -1742,32 +1742,18 @@ const aarch64 = struct {...@@ -1742,32 +1742,18 @@ const aarch64 = struct {
1742 const S_ = target.tlsDescAddress(elf_file);1742 const S_ = target.tlsDescAddress(elf_file);
1743 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });1743 relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A });
1744 const off: u12 = @truncate(@as(u64, @bitCast(S_ + A)));1744 const off: u12 = @truncate(@as(u64, @bitCast(S_ + A)));
1745 aarch64_util.writeAddImmInst(off, code);1745 util.writeAddImmInst(off, code);
1746 } else {1746 } else {
1747 const old_inst: Instruction = .{1747 relocs_log.debug(" relaxing add => movz(x0, {x})", .{S + A - TP});
1748 .add_subtract_immediate = mem.bytesToValue(@FieldType(
1749 Instruction,
1750 @tagName(Instruction.add_subtract_immediate),
1751 ), code),
1752 };
1753 const rd: Register = @enumFromInt(old_inst.add_subtract_immediate.rd);
1754 relocs_log.debug(" relaxing add({s}) => movz(x0, {x})", .{ @tagName(rd), S + A - TP });
1755 const value: u16 = @bitCast(math.cast(i16, (S + A - TP) >> 16) orelse return error.Overflow);1748 const value: u16 = @bitCast(math.cast(i16, (S + A - TP) >> 16) orelse return error.Overflow);
1756 mem.writeInt(u32, code, Instruction.movz(.x0, value, 16).toU32(), .little);1749 util.encoding.Instruction.movz(.x0, value, .{ .lsl = .@"16" }).write(code);
1757 }1750 }
1758 },1751 },
17591752
1760 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {1753 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
1761 const old_inst: Instruction = .{1754 relocs_log.debug(" relaxing br => movk(x0, {x})", .{S + A - TP});
1762 .unconditional_branch_register = mem.bytesToValue(@FieldType(
1763 Instruction,
1764 @tagName(Instruction.unconditional_branch_register),
1765 ), code),
1766 };
1767 const rn: Register = @enumFromInt(old_inst.unconditional_branch_register.rn);
1768 relocs_log.debug(" relaxing br({s}) => movk(x0, {x})", .{ @tagName(rn), S + A - TP });
1769 const value: u16 = @bitCast(@as(i16, @truncate(S + A - TP)));1755 const value: u16 = @bitCast(@as(i16, @truncate(S + A - TP)));
1770 mem.writeInt(u32, code, Instruction.movk(.x0, value, 0).toU32(), .little);1756 util.encoding.Instruction.movk(.x0, value, .{}).write(code);
1771 },1757 },
17721758
1773 else => try atom.reportUnhandledRelocError(rel, elf_file),1759 else => try atom.reportUnhandledRelocError(rel, elf_file),
...@@ -1796,9 +1782,7 @@ const aarch64 = struct {...@@ -1796,9 +1782,7 @@ const aarch64 = struct {
1796 }1782 }
1797 }1783 }
17981784
1799 const aarch64_util = @import("../aarch64.zig");1785 const util = @import("../aarch64.zig");
1800 const Instruction = aarch64_util.Instruction;
1801 const Register = aarch64_util.Register;
1802};1786};
18031787
1804const riscv = struct {1788const riscv = struct {
src/link/Elf/Thunk.zig+9-6
...@@ -95,18 +95,21 @@ const aarch64 = struct {...@@ -95,18 +95,21 @@ const aarch64 = struct {
95 const sym = elf_file.symbol(ref).?;95 const sym = elf_file.symbol(ref).?;
96 const saddr = thunk.address(elf_file) + @as(i64, @intCast(i * trampoline_size));96 const saddr = thunk.address(elf_file) + @as(i64, @intCast(i * trampoline_size));
97 const taddr = sym.address(.{}, elf_file);97 const taddr = sym.address(.{}, elf_file);
98 const pages = try util.calcNumberOfPages(saddr, taddr);98 try writer.writeInt(u32, @bitCast(
99 try writer.writeInt(u32, Instruction.adrp(.x16, pages).toU32(), .little);99 util.encoding.Instruction.adrp(.x16, try util.calcNumberOfPages(saddr, taddr) << 12),
100 const off: u12 = @truncate(@as(u64, @bitCast(taddr)));100 ), .little);
101 try writer.writeInt(u32, Instruction.add(.x16, .x16, off, false).toU32(), .little);101 try writer.writeInt(u32, @bitCast(util.encoding.Instruction.add(
102 try writer.writeInt(u32, Instruction.br(.x16).toU32(), .little);102 .x16,
103 .x16,
104 .{ .immediate = @truncate(@as(u64, @bitCast(taddr))) },
105 )), .little);
106 try writer.writeInt(u32, @bitCast(util.encoding.Instruction.br(.x16)), .little);
103 }107 }
104 }108 }
105109
106 const trampoline_size = 3 * @sizeOf(u32);110 const trampoline_size = 3 * @sizeOf(u32);
107111
108 const util = @import("../aarch64.zig");112 const util = @import("../aarch64.zig");
109 const Instruction = util.Instruction;
110};113};
111114
112const std = @import("std");115const std = @import("std");
src/link/Elf/ZigObject.zig+7-3
...@@ -1266,9 +1266,13 @@ fn updateNavCode(...@@ -1266,9 +1266,13 @@ fn updateNavCode(
12661266
1267 log.debug("updateNavCode {f}({d})", .{ nav.fqn.fmt(ip), nav_index });1267 log.debug("updateNavCode {f}({d})", .{ nav.fqn.fmt(ip), nav_index });
12681268
1269 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;1269 const mod = zcu.navFileScope(nav_index).mod.?;
1270 const required_alignment = switch (pt.navAlignment(nav_index)) {1270 const target = &mod.resolved_target.result;
1271 .none => target_util.defaultFunctionAlignment(target),1271 const required_alignment = switch (nav.status.fully_resolved.alignment) {
1272 .none => switch (mod.optimize_mode) {
1273 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
1274 .ReleaseSmall => target_util.minFunctionAlignment(target),
1275 },
1272 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),1276 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
1273 };1277 };
12741278
src/link/Elf/relocation.zig+18-6
...@@ -94,14 +94,18 @@ pub fn encode(comptime kind: Kind, cpu_arch: std.Target.Cpu.Arch) u32 {...@@ -94,14 +94,18 @@ pub fn encode(comptime kind: Kind, cpu_arch: std.Target.Cpu.Arch) u32 {
94pub const dwarf = struct {94pub const dwarf = struct {
95 pub fn crossSectionRelocType(format: DW.Format, cpu_arch: std.Target.Cpu.Arch) u32 {95 pub fn crossSectionRelocType(format: DW.Format, cpu_arch: std.Target.Cpu.Arch) u32 {
96 return switch (cpu_arch) {96 return switch (cpu_arch) {
97 .x86_64 => @intFromEnum(switch (format) {97 .x86_64 => @intFromEnum(@as(elf.R_X86_64, switch (format) {
98 .@"32" => elf.R_X86_64.@"32",98 .@"32" => .@"32",
99 .@"64" => .@"64",99 .@"64" => .@"64",
100 }),100 })),
101 .riscv64 => @intFromEnum(switch (format) {101 .aarch64 => @intFromEnum(@as(elf.R_AARCH64, switch (format) {
102 .@"32" => elf.R_RISCV.@"32",102 .@"32" => .ABS32,
103 .@"64" => .ABS64,
104 })),
105 .riscv64 => @intFromEnum(@as(elf.R_RISCV, switch (format) {
106 .@"32" => .@"32",
103 .@"64" => .@"64",107 .@"64" => .@"64",
104 }),108 })),
105 else => @panic("TODO unhandled cpu arch"),109 else => @panic("TODO unhandled cpu arch"),
106 };110 };
107 }111 }
...@@ -121,6 +125,14 @@ pub const dwarf = struct {...@@ -121,6 +125,14 @@ pub const dwarf = struct {
121 },125 },
122 .debug_frame => .PC32,126 .debug_frame => .PC32,
123 })),127 })),
128 .aarch64 => @intFromEnum(@as(elf.R_AARCH64, switch (source_section) {
129 else => switch (address_size) {
130 .@"32" => .ABS32,
131 .@"64" => .ABS64,
132 else => unreachable,
133 },
134 .debug_frame => .PREL32,
135 })),
124 .riscv64 => @intFromEnum(@as(elf.R_RISCV, switch (source_section) {136 .riscv64 => @intFromEnum(@as(elf.R_RISCV, switch (source_section) {
125 else => switch (address_size) {137 else => switch (address_size) {
126 .@"32" => .@"32",138 .@"32" => .@"32",
src/link/Elf/synthetic_sections.zig+109-124
...@@ -94,115 +94,115 @@ pub const DynamicSection = struct {...@@ -94,115 +94,115 @@ pub const DynamicSection = struct {
94 return nentries * @sizeOf(elf.Elf64_Dyn);94 return nentries * @sizeOf(elf.Elf64_Dyn);
95 }95 }
9696
97 pub fn write(dt: DynamicSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {97 pub fn write(dt: DynamicSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
98 const shdrs = elf_file.sections.items(.shdr);98 const shdrs = elf_file.sections.items(.shdr);
9999
100 // NEEDED100 // NEEDED
101 for (dt.needed.items) |off| {101 for (dt.needed.items) |off| {
102 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off });102 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off });
103 }103 }
104104
105 if (dt.soname) |off| {105 if (dt.soname) |off| {
106 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SONAME, .d_val = off });106 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SONAME, .d_val = off });
107 }107 }
108108
109 // RUNPATH109 // RUNPATH
110 // TODO add option in Options to revert to old RPATH tag110 // TODO add option in Options to revert to old RPATH tag
111 if (dt.rpath > 0) {111 if (dt.rpath > 0) {
112 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath });112 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RUNPATH, .d_val = dt.rpath });
113 }113 }
114114
115 // INIT115 // INIT
116 if (elf_file.sectionByName(".init")) |shndx| {116 if (elf_file.sectionByName(".init")) |shndx| {
117 const addr = shdrs[shndx].sh_addr;117 const addr = shdrs[shndx].sh_addr;
118 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr });118 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr });
119 }119 }
120120
121 // FINI121 // FINI
122 if (elf_file.sectionByName(".fini")) |shndx| {122 if (elf_file.sectionByName(".fini")) |shndx| {
123 const addr = shdrs[shndx].sh_addr;123 const addr = shdrs[shndx].sh_addr;
124 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr });124 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr });
125 }125 }
126126
127 // INIT_ARRAY127 // INIT_ARRAY
128 if (elf_file.sectionByName(".init_array")) |shndx| {128 if (elf_file.sectionByName(".init_array")) |shndx| {
129 const shdr = shdrs[shndx];129 const shdr = shdrs[shndx];
130 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr });130 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr });
131 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size });131 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size });
132 }132 }
133133
134 // FINI_ARRAY134 // FINI_ARRAY
135 if (elf_file.sectionByName(".fini_array")) |shndx| {135 if (elf_file.sectionByName(".fini_array")) |shndx| {
136 const shdr = shdrs[shndx];136 const shdr = shdrs[shndx];
137 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr });137 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr });
138 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size });138 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size });
139 }139 }
140140
141 // RELA141 // RELA
142 if (elf_file.section_indexes.rela_dyn) |shndx| {142 if (elf_file.section_indexes.rela_dyn) |shndx| {
143 const shdr = shdrs[shndx];143 const shdr = shdrs[shndx];
144 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });144 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });
145 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });145 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });
146 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize });146 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize });
147 }147 }
148148
149 // JMPREL149 // JMPREL
150 if (elf_file.section_indexes.rela_plt) |shndx| {150 if (elf_file.section_indexes.rela_plt) |shndx| {
151 const shdr = shdrs[shndx];151 const shdr = shdrs[shndx];
152 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });152 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });
153 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });153 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });
154 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA });154 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA });
155 }155 }
156156
157 // PLTGOT157 // PLTGOT
158 if (elf_file.section_indexes.got_plt) |shndx| {158 if (elf_file.section_indexes.got_plt) |shndx| {
159 const addr = shdrs[shndx].sh_addr;159 const addr = shdrs[shndx].sh_addr;
160 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });160 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });
161 }161 }
162162
163 {163 {
164 assert(elf_file.section_indexes.hash != null);164 assert(elf_file.section_indexes.hash != null);
165 const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr;165 const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr;
166 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });166 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });
167 }167 }
168168
169 if (elf_file.section_indexes.gnu_hash) |shndx| {169 if (elf_file.section_indexes.gnu_hash) |shndx| {
170 const addr = shdrs[shndx].sh_addr;170 const addr = shdrs[shndx].sh_addr;
171 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });171 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });
172 }172 }
173173
174 // TEXTREL174 // TEXTREL
175 if (elf_file.has_text_reloc) {175 if (elf_file.has_text_reloc) {
176 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_TEXTREL, .d_val = 0 });176 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_TEXTREL, .d_val = 0 });
177 }177 }
178178
179 // SYMTAB + SYMENT179 // SYMTAB + SYMENT
180 {180 {
181 assert(elf_file.section_indexes.dynsymtab != null);181 assert(elf_file.section_indexes.dynsymtab != null);
182 const shdr = shdrs[elf_file.section_indexes.dynsymtab.?];182 const shdr = shdrs[elf_file.section_indexes.dynsymtab.?];
183 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });183 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });
184 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });184 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });
185 }185 }
186186
187 // STRTAB + STRSZ187 // STRTAB + STRSZ
188 {188 {
189 assert(elf_file.section_indexes.dynstrtab != null);189 assert(elf_file.section_indexes.dynstrtab != null);
190 const shdr = shdrs[elf_file.section_indexes.dynstrtab.?];190 const shdr = shdrs[elf_file.section_indexes.dynstrtab.?];
191 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });191 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });
192 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });192 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });
193 }193 }
194194
195 // VERSYM195 // VERSYM
196 if (elf_file.section_indexes.versym) |shndx| {196 if (elf_file.section_indexes.versym) |shndx| {
197 const addr = shdrs[shndx].sh_addr;197 const addr = shdrs[shndx].sh_addr;
198 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });198 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });
199 }199 }
200200
201 // VERNEED + VERNEEDNUM201 // VERNEED + VERNEEDNUM
202 if (elf_file.section_indexes.verneed) |shndx| {202 if (elf_file.section_indexes.verneed) |shndx| {
203 const addr = shdrs[shndx].sh_addr;203 const addr = shdrs[shndx].sh_addr;
204 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });204 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });
205 try bw.writeStruct(elf.Elf64_Dyn{205 try writer.writeStruct(elf.Elf64_Dyn{
206 .d_tag = elf.DT_VERNEEDNUM,206 .d_tag = elf.DT_VERNEEDNUM,
207 .d_val = elf_file.verneed.verneed.items.len,207 .d_val = elf_file.verneed.verneed.items.len,
208 });208 });
...@@ -210,18 +210,18 @@ pub const DynamicSection = struct {...@@ -210,18 +210,18 @@ pub const DynamicSection = struct {
210210
211 // FLAGS211 // FLAGS
212 if (dt.getFlags(elf_file)) |flags| {212 if (dt.getFlags(elf_file)) |flags| {
213 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS, .d_val = flags });213 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS, .d_val = flags });
214 }214 }
215 // FLAGS_1215 // FLAGS_1
216 if (dt.getFlags1(elf_file)) |flags_1| {216 if (dt.getFlags1(elf_file)) |flags_1| {
217 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS_1, .d_val = flags_1 });217 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FLAGS_1, .d_val = flags_1 });
218 }218 }
219219
220 // DEBUG220 // DEBUG
221 if (!elf_file.isEffectivelyDynLib()) try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 });221 if (!elf_file.isEffectivelyDynLib()) try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_DEBUG, .d_val = 0 });
222222
223 // NULL223 // NULL
224 try bw.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NULL, .d_val = 0 });224 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NULL, .d_val = 0 });
225 }225 }
226};226};
227227
...@@ -360,7 +360,7 @@ pub const GotSection = struct {...@@ -360,7 +360,7 @@ pub const GotSection = struct {
360 return s;360 return s;
361 }361 }
362362
363 pub fn write(got: GotSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {363 pub fn write(got: GotSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
364 const comp = elf_file.base.comp;364 const comp = elf_file.base.comp;
365 const is_dyn_lib = elf_file.isEffectivelyDynLib();365 const is_dyn_lib = elf_file.isEffectivelyDynLib();
366 const apply_relocs = true; // TODO add user option for this366 const apply_relocs = true; // TODO add user option for this
...@@ -381,47 +381,47 @@ pub const GotSection = struct {...@@ -381,47 +381,47 @@ pub const GotSection = struct {
381 }381 }
382 break :blk value;382 break :blk value;
383 };383 };
384 try writeInt(value, elf_file, bw);384 try writeInt(value, elf_file, writer);
385 },385 },
386 .tlsld => {386 .tlsld => {
387 try writeInt(if (is_dyn_lib) @as(u64, 0) else 1, elf_file, bw);387 try writeInt(if (is_dyn_lib) @as(u64, 0) else 1, elf_file, writer);
388 try writeInt(0, elf_file, bw);388 try writeInt(0, elf_file, writer);
389 },389 },
390 .tlsgd => {390 .tlsgd => {
391 if (symbol.?.flags.import) {391 if (symbol.?.flags.import) {
392 try writeInt(0, elf_file, bw);392 try writeInt(0, elf_file, writer);
393 try writeInt(0, elf_file, bw);393 try writeInt(0, elf_file, writer);
394 } else {394 } else {
395 try writeInt(if (is_dyn_lib) @as(u64, 0) else 1, elf_file, bw);395 try writeInt(if (is_dyn_lib) @as(u64, 0) else 1, elf_file, writer);
396 const offset = symbol.?.address(.{}, elf_file) - elf_file.dtpAddress();396 const offset = symbol.?.address(.{}, elf_file) - elf_file.dtpAddress();
397 try writeInt(offset, elf_file, bw);397 try writeInt(offset, elf_file, writer);
398 }398 }
399 },399 },
400 .gottp => {400 .gottp => {
401 if (symbol.?.flags.import) {401 if (symbol.?.flags.import) {
402 try writeInt(0, elf_file, bw);402 try writeInt(0, elf_file, writer);
403 } else if (is_dyn_lib) {403 } else if (is_dyn_lib) {
404 const offset = if (apply_relocs)404 const offset = if (apply_relocs)
405 symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()405 symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()
406 else406 else
407 0;407 0;
408 try writeInt(offset, elf_file, bw);408 try writeInt(offset, elf_file, writer);
409 } else {409 } else {
410 const offset = symbol.?.address(.{}, elf_file) - elf_file.tpAddress();410 const offset = symbol.?.address(.{}, elf_file) - elf_file.tpAddress();
411 try writeInt(offset, elf_file, bw);411 try writeInt(offset, elf_file, writer);
412 }412 }
413 },413 },
414 .tlsdesc => {414 .tlsdesc => {
415 if (symbol.?.flags.import) {415 if (symbol.?.flags.import) {
416 try writeInt(0, elf_file, bw);416 try writeInt(0, elf_file, writer);
417 try writeInt(0, elf_file, bw);417 try writeInt(0, elf_file, writer);
418 } else {418 } else {
419 try writeInt(0, elf_file, bw);419 try writeInt(0, elf_file, writer);
420 const offset = if (apply_relocs)420 const offset = if (apply_relocs)
421 symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()421 symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()
422 else422 else
423 0;423 0;
424 try writeInt(offset, elf_file, bw);424 try writeInt(offset, elf_file, writer);
425 }425 }
426 },426 },
427 }427 }
...@@ -671,11 +671,11 @@ pub const PltSection = struct {...@@ -671,11 +671,11 @@ pub const PltSection = struct {
671 };671 };
672 }672 }
673673
674 pub fn write(plt: PltSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {674 pub fn write(plt: PltSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
675 const cpu_arch = elf_file.getTarget().cpu.arch;675 const cpu_arch = elf_file.getTarget().cpu.arch;
676 switch (cpu_arch) {676 switch (cpu_arch) {
677 .x86_64 => try x86_64.write(plt, elf_file, bw),677 .x86_64 => try x86_64.write(plt, elf_file, writer),
678 .aarch64 => try aarch64.write(plt, elf_file, bw),678 .aarch64 => try aarch64.write(plt, elf_file, writer),
679 else => return error.UnsupportedCpuArch,679 else => return error.UnsupportedCpuArch,
680 }680 }
681 }681 }
...@@ -768,7 +768,7 @@ pub const PltSection = struct {...@@ -768,7 +768,7 @@ pub const PltSection = struct {
768 }768 }
769769
770 const x86_64 = struct {770 const x86_64 = struct {
771 fn write(plt: PltSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {771 fn write(plt: PltSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
772 const shdrs = elf_file.sections.items(.shdr);772 const shdrs = elf_file.sections.items(.shdr);
773 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;773 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;
774 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;774 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;
...@@ -782,8 +782,8 @@ pub const PltSection = struct {...@@ -782,8 +782,8 @@ pub const PltSection = struct {
782 mem.writeInt(i32, preamble[8..][0..4], @as(i32, @intCast(disp)), .little);782 mem.writeInt(i32, preamble[8..][0..4], @as(i32, @intCast(disp)), .little);
783 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;783 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;
784 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);784 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);
785 try bw.writeAll(&preamble);785 try writer.writeAll(&preamble);
786 try bw.splatByteAll(0xcc, preambleSize(.x86_64) - preamble.len);786 try writer.splatByteAll(0xcc, preambleSize(.x86_64) - preamble.len);
787787
788 for (plt.symbols.items, 0..) |ref, i| {788 for (plt.symbols.items, 0..) |ref, i| {
789 const sym = elf_file.symbol(ref).?;789 const sym = elf_file.symbol(ref).?;
...@@ -797,67 +797,56 @@ pub const PltSection = struct {...@@ -797,67 +797,56 @@ pub const PltSection = struct {
797 };797 };
798 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(i)), .little);798 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(i)), .little);
799 mem.writeInt(i32, entry[12..][0..4], @as(i32, @intCast(disp)), .little);799 mem.writeInt(i32, entry[12..][0..4], @as(i32, @intCast(disp)), .little);
800 try bw.writeAll(&entry);800 try writer.writeAll(&entry);
801 }801 }
802 }802 }
803 };803 };
804804
805 const aarch64 = struct {805 const aarch64 = struct {
806 fn write(plt: PltSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {806 fn write(plt: PltSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
807 {807 {
808 const shdrs = elf_file.sections.items(.shdr);808 const shdrs = elf_file.sections.items(.shdr);
809 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);809 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);
810 const got_plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.got_plt.?].sh_addr);810 const got_plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.got_plt.?].sh_addr);
811 // TODO: relax if possible811 // TODO: relax if possible
812 // .got.plt[2]812 // .got.plt[2]
813 const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);813 const pages = try util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);
814 const ldr_off = try math.divExact(u12, @truncate(@as(u64, @bitCast(got_plt_addr + 16))), 8);814 const ldr_off: u12 = @truncate(@as(u64, @bitCast(got_plt_addr + 16)));
815 const add_off: u12 = @truncate(@as(u64, @bitCast(got_plt_addr + 16)));815 const add_off: u12 = @truncate(@as(u64, @bitCast(got_plt_addr + 16)));
816816
817 const preamble = &[_]Instruction{817 const preamble = [_]util.encoding.Instruction{
818 Instruction.stp(818 .stp(.x16, .x30, .{ .pre_index = .{ .base = .sp, .index = -16 } }),
819 .x16,819 .adrp(.x16, pages << 12),
820 .x30,820 .ldr(.x17, .{ .unsigned_offset = .{ .base = .x16, .offset = ldr_off } }),
821 Register.sp,821 .add(.x16, .x16, .{ .immediate = add_off }),
822 Instruction.LoadStorePairOffset.pre_index(-16),822 .br(.x17),
823 ),823 .nop(),
824 Instruction.adrp(.x16, pages),824 .nop(),
825 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)),825 .nop(),
826 Instruction.add(.x16, .x16, add_off, false),
827 Instruction.br(.x17),
828 Instruction.nop(),
829 Instruction.nop(),
830 Instruction.nop(),
831 };826 };
832 comptime assert(preamble.len == 8);827 comptime assert(preamble.len == 8);
833 for (preamble) |inst| {828 for (preamble) |inst| try writer.writeInt(util.encoding.Instruction.Backing, @bitCast(inst), .little);
834 try bw.writeInt(u32, inst.toU32(), .little);
835 }
836 }829 }
837830
838 for (plt.symbols.items) |ref| {831 for (plt.symbols.items) |ref| {
839 const sym = elf_file.symbol(ref).?;832 const sym = elf_file.symbol(ref).?;
840 const target_addr = sym.gotPltAddress(elf_file);833 const target_addr = sym.gotPltAddress(elf_file);
841 const source_addr = sym.pltAddress(elf_file);834 const source_addr = sym.pltAddress(elf_file);
842 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);835 const pages = try util.calcNumberOfPages(source_addr, target_addr);
843 const ldr_off = try math.divExact(u12, @truncate(@as(u64, @bitCast(target_addr))), 8);836 const ldr_off: u12 = @truncate(@as(u64, @bitCast(target_addr)));
844 const add_off: u12 = @truncate(@as(u64, @bitCast(target_addr)));837 const add_off: u12 = @truncate(@as(u64, @bitCast(target_addr)));
845 const insts = &[_]Instruction{838 const insts = [_]util.encoding.Instruction{
846 Instruction.adrp(.x16, pages),839 .adrp(.x16, pages << 12),
847 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)),840 .ldr(.x17, .{ .unsigned_offset = .{ .base = .x16, .offset = ldr_off } }),
848 Instruction.add(.x16, .x16, add_off, false),841 .add(.x16, .x16, .{ .immediate = add_off }),
849 Instruction.br(.x17),842 .br(.x17),
850 };843 };
851 comptime assert(insts.len == 4);844 comptime assert(insts.len == 4);
852 for (insts) |inst| {845 for (insts) |inst| try writer.writeInt(util.encoding.Instruction.Backing, @bitCast(inst), .little);
853 try bw.writeInt(u32, inst.toU32(), .little);
854 }
855 }846 }
856 }847 }
857848
858 const aarch64_util = @import("../aarch64.zig");849 const util = @import("../aarch64.zig");
859 const Instruction = aarch64_util.Instruction;
860 const Register = aarch64_util.Register;
861 };850 };
862};851};
863852
...@@ -869,22 +858,22 @@ pub const GotPltSection = struct {...@@ -869,22 +858,22 @@ pub const GotPltSection = struct {
869 return preamble_size + elf_file.plt.symbols.items.len * 8;858 return preamble_size + elf_file.plt.symbols.items.len * 8;
870 }859 }
871860
872 pub fn write(got_plt: GotPltSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {861 pub fn write(got_plt: GotPltSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
873 _ = got_plt;862 _ = got_plt;
874 {863 {
875 // [0]: _DYNAMIC864 // [0]: _DYNAMIC
876 const symbol = elf_file.linkerDefinedPtr().?.dynamicSymbol(elf_file).?;865 const symbol = elf_file.linkerDefinedPtr().?.dynamicSymbol(elf_file).?;
877 try bw.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little);866 try writer.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little);
878 }867 }
879 // [1]: 0x0868 // [1]: 0x0
880 // [2]: 0x0869 // [2]: 0x0
881 try bw.writeInt(u64, 0x0, .little);870 try writer.writeInt(u64, 0x0, .little);
882 try bw.writeInt(u64, 0x0, .little);871 try writer.writeInt(u64, 0x0, .little);
883 if (elf_file.section_indexes.plt) |shndx| {872 if (elf_file.section_indexes.plt) |shndx| {
884 const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr;873 const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr;
885 for (0..elf_file.plt.symbols.items.len) |_| {874 for (0..elf_file.plt.symbols.items.len) |_| {
886 // [N]: .plt875 // [N]: .plt
887 try bw.writeInt(u64, plt_addr, .little);876 try writer.writeInt(u64, plt_addr, .little);
888 }877 }
889 }878 }
890 }879 }
...@@ -920,11 +909,11 @@ pub const PltGotSection = struct {...@@ -920,11 +909,11 @@ pub const PltGotSection = struct {
920 };909 };
921 }910 }
922911
923 pub fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {912 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
924 const cpu_arch = elf_file.getTarget().cpu.arch;913 const cpu_arch = elf_file.getTarget().cpu.arch;
925 switch (cpu_arch) {914 switch (cpu_arch) {
926 .x86_64 => try x86_64.write(plt_got, elf_file, bw),915 .x86_64 => try x86_64.write(plt_got, elf_file, writer),
927 .aarch64 => try aarch64.write(plt_got, elf_file, bw),916 .aarch64 => try aarch64.write(plt_got, elf_file, writer),
928 else => return error.UnsupportedCpuArch,917 else => return error.UnsupportedCpuArch,
929 }918 }
930 }919 }
...@@ -956,7 +945,7 @@ pub const PltGotSection = struct {...@@ -956,7 +945,7 @@ pub const PltGotSection = struct {
956 }945 }
957946
958 const x86_64 = struct {947 const x86_64 = struct {
959 pub fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {948 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
960 for (plt_got.symbols.items) |ref| {949 for (plt_got.symbols.items) |ref| {
961 const sym = elf_file.symbol(ref).?;950 const sym = elf_file.symbol(ref).?;
962 const target_addr = sym.gotAddress(elf_file);951 const target_addr = sym.gotAddress(elf_file);
...@@ -968,35 +957,31 @@ pub const PltGotSection = struct {...@@ -968,35 +957,31 @@ pub const PltGotSection = struct {
968 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,957 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
969 };958 };
970 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);959 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);
971 try bw.writeAll(&entry);960 try writer.writeAll(&entry);
972 }961 }
973 }962 }
974 };963 };
975964
976 const aarch64 = struct {965 const aarch64 = struct {
977 fn write(plt_got: PltGotSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {966 fn write(plt_got: PltGotSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
978 for (plt_got.symbols.items) |ref| {967 for (plt_got.symbols.items) |ref| {
979 const sym = elf_file.symbol(ref).?;968 const sym = elf_file.symbol(ref).?;
980 const target_addr = sym.gotAddress(elf_file);969 const target_addr = sym.gotAddress(elf_file);
981 const source_addr = sym.pltGotAddress(elf_file);970 const source_addr = sym.pltGotAddress(elf_file);
982 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);971 const pages = try util.calcNumberOfPages(source_addr, target_addr);
983 const off = try math.divExact(u12, @truncate(@as(u64, @bitCast(target_addr))), 8);972 const off: u12 = @truncate(@as(u64, @bitCast(target_addr)));
984 const insts = &[_]Instruction{973 const insts = [_]util.encoding.Instruction{
985 Instruction.adrp(.x16, pages),974 .adrp(.x16, pages << 12),
986 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)),975 .ldr(.x17, .{ .unsigned_offset = .{ .base = .x16, .offset = off } }),
987 Instruction.br(.x17),976 .br(.x17),
988 Instruction.nop(),977 .nop(),
989 };978 };
990 comptime assert(insts.len == 4);979 comptime assert(insts.len == 4);
991 for (insts) |inst| {980 for (insts) |inst| try writer.writeInt(util.encoding.Instruction.Backing, @bitCast(inst), .little);
992 try bw.writeInt(u32, inst.toU32(), .little);
993 }
994 }981 }
995 }982 }
996983
997 const aarch64_util = @import("../aarch64.zig");984 const util = @import("../aarch64.zig");
998 const Instruction = aarch64_util.Instruction;
999 const Register = aarch64_util.Register;
1000 };985 };
1001};986};
1002987
...@@ -1153,14 +1138,14 @@ pub const DynsymSection = struct {...@@ -1153,14 +1138,14 @@ pub const DynsymSection = struct {
1153 return @as(u32, @intCast(dynsym.entries.items.len + 1));1138 return @as(u32, @intCast(dynsym.entries.items.len + 1));
1154 }1139 }
11551140
1156 pub fn write(dynsym: DynsymSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {1141 pub fn write(dynsym: DynsymSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
1157 try bw.writeStruct(Elf.null_sym);1142 try writer.writeStruct(Elf.null_sym);
1158 for (dynsym.entries.items) |entry| {1143 for (dynsym.entries.items) |entry| {
1159 const sym = elf_file.symbol(entry.ref).?;1144 const sym = elf_file.symbol(entry.ref).?;
1160 var out_sym: elf.Elf64_Sym = Elf.null_sym;1145 var out_sym: elf.Elf64_Sym = Elf.null_sym;
1161 sym.setOutputSym(elf_file, &out_sym);1146 sym.setOutputSym(elf_file, &out_sym);
1162 out_sym.st_name = entry.off;1147 out_sym.st_name = entry.off;
1163 try bw.writeStruct(out_sym);1148 try writer.writeStruct(out_sym);
1164 }1149 }
1165 }1150 }
1166};1151};
...@@ -1456,9 +1441,9 @@ pub const VerneedSection = struct {...@@ -1456,9 +1441,9 @@ pub const VerneedSection = struct {
1456 return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux);1441 return vern.verneed.items.len * @sizeOf(elf.Elf64_Verneed) + vern.vernaux.items.len * @sizeOf(elf.Vernaux);
1457 }1442 }
14581443
1459 pub fn write(vern: VerneedSection, bw: *Writer) Writer.Error!void {1444 pub fn write(vern: VerneedSection, writer: *Writer) Writer.Error!void {
1460 try bw.writeAll(mem.sliceAsBytes(vern.verneed.items));1445 try writer.writeAll(mem.sliceAsBytes(vern.verneed.items));
1461 try bw.writeAll(mem.sliceAsBytes(vern.vernaux.items));1446 try writer.writeAll(mem.sliceAsBytes(vern.vernaux.items));
1462 }1447 }
1463};1448};
14641449
...@@ -1484,11 +1469,11 @@ pub const GroupSection = struct {...@@ -1484,11 +1469,11 @@ pub const GroupSection = struct {
1484 return (members.len + 1) * @sizeOf(u32);1469 return (members.len + 1) * @sizeOf(u32);
1485 }1470 }
14861471
1487 pub fn write(cgs: GroupSection, elf_file: *Elf, bw: *Writer) Writer.Error!void {1472 pub fn write(cgs: GroupSection, elf_file: *Elf, writer: *Writer) Writer.Error!void {
1488 const cg = cgs.comdatGroup(elf_file);1473 const cg = cgs.comdatGroup(elf_file);
1489 const object = cg.file(elf_file).object;1474 const object = cg.file(elf_file).object;
1490 const members = cg.members(elf_file);1475 const members = cg.members(elf_file);
1491 try bw.writeInt(u32, if (cg.is_comdat) elf.GRP_COMDAT else 0, .little);1476 try writer.writeInt(u32, if (cg.is_comdat) elf.GRP_COMDAT else 0, .little);
1492 for (members) |shndx| {1477 for (members) |shndx| {
1493 const shdr = object.shdrs.items[shndx];1478 const shdr = object.shdrs.items[shndx];
1494 switch (shdr.sh_type) {1479 switch (shdr.sh_type) {
...@@ -1500,26 +1485,26 @@ pub const GroupSection = struct {...@@ -1500,26 +1485,26 @@ pub const GroupSection = struct {
1500 atom.output_section_index == rela_shdr.sh_info)1485 atom.output_section_index == rela_shdr.sh_info)
1501 break rela_shndx;1486 break rela_shndx;
1502 } else unreachable;1487 } else unreachable;
1503 try bw.writeInt(u32, @intCast(rela_shndx), .little);1488 try writer.writeInt(u32, @intCast(rela_shndx), .little);
1504 },1489 },
1505 else => {1490 else => {
1506 const atom_index = object.atoms_indexes.items[shndx];1491 const atom_index = object.atoms_indexes.items[shndx];
1507 const atom = object.atom(atom_index).?;1492 const atom = object.atom(atom_index).?;
1508 try bw.writeInt(u32, atom.output_section_index, .little);1493 try writer.writeInt(u32, atom.output_section_index, .little);
1509 },1494 },
1510 }1495 }
1511 }1496 }
1512 }1497 }
1513};1498};
15141499
1515fn writeInt(value: anytype, elf_file: *Elf, bw: *Writer) Writer.Error!void {1500fn writeInt(value: anytype, elf_file: *Elf, writer: *Writer) Writer.Error!void {
1516 const entry_size = elf_file.archPtrWidthBytes();1501 const entry_size = elf_file.archPtrWidthBytes();
1517 const target = elf_file.getTarget();1502 const target = elf_file.getTarget();
1518 const endian = target.cpu.arch.endian();1503 const endian = target.cpu.arch.endian();
1519 switch (entry_size) {1504 switch (entry_size) {
1520 2 => try bw.writeInt(u16, @intCast(value), endian),1505 2 => try writer.writeInt(u16, @intCast(value), endian),
1521 4 => try bw.writeInt(u32, @intCast(value), endian),1506 4 => try writer.writeInt(u32, @intCast(value), endian),
1522 8 => try bw.writeInt(u64, @intCast(value), endian),1507 8 => try writer.writeInt(u64, @intCast(value), endian),
1523 else => unreachable,1508 else => unreachable,
1524 }1509 }
1525}1510}
src/link/MachO.zig+2-1
...@@ -328,6 +328,7 @@ pub fn deinit(self: *MachO) void {...@@ -328,6 +328,7 @@ pub fn deinit(self: *MachO) void {
328 self.unwind_info.deinit(gpa);328 self.unwind_info.deinit(gpa);
329 self.data_in_code.deinit(gpa);329 self.data_in_code.deinit(gpa);
330330
331 for (self.thunks.items) |*thunk| thunk.deinit(gpa);
331 self.thunks.deinit(gpa);332 self.thunks.deinit(gpa);
332}333}
333334
...@@ -5374,7 +5375,7 @@ const mem = std.mem;...@@ -5374,7 +5375,7 @@ const mem = std.mem;
5374const meta = std.meta;5375const meta = std.meta;
5375const Writer = std.io.Writer;5376const Writer = std.io.Writer;
53765377
5377const aarch64 = @import("../arch/aarch64/bits.zig");5378const aarch64 = codegen.aarch64.encoding;
5378const bind = @import("MachO/dyld_info/bind.zig");5379const bind = @import("MachO/dyld_info/bind.zig");
5379const calcUuid = @import("MachO/uuid.zig").calcUuid;5380const calcUuid = @import("MachO/uuid.zig").calcUuid;
5380const codegen = @import("../codegen.zig");5381const codegen = @import("../codegen.zig");
src/link/MachO/Atom.zig+43-85
...@@ -580,7 +580,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {...@@ -580,7 +580,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
580580
581 relocs_log.debug("{x}: {s}", .{ self.value, name });581 relocs_log.debug("{x}: {s}", .{ self.value, name });
582582
583 var bw: Writer = .fixed(buffer);583 var writer: Writer = .fixed(buffer);
584584
585 var has_error = false;585 var has_error = false;
586 var i: usize = 0;586 var i: usize = 0;
...@@ -593,8 +593,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {...@@ -593,8 +593,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
593 if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue;593 if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue;
594 }594 }
595595
596 bw.end = std.math.cast(usize, rel_offset) orelse return error.Overflow;596 writer.end = std.math.cast(usize, rel_offset) orelse return error.Overflow;
597 self.resolveRelocInner(rel, subtractor, buffer, macho_file, &bw) catch |err| switch (err) {597 self.resolveRelocInner(rel, subtractor, buffer, macho_file, &writer) catch |err| switch (err) {
598 error.RelaxFail => {598 error.RelaxFail => {
599 const target = switch (rel.tag) {599 const target = switch (rel.tag) {
600 .@"extern" => rel.getTargetSymbol(self, macho_file).getName(macho_file),600 .@"extern" => rel.getTargetSymbol(self, macho_file).getName(macho_file),
...@@ -637,7 +637,7 @@ fn resolveRelocInner(...@@ -637,7 +637,7 @@ fn resolveRelocInner(
637 subtractor: ?Relocation,637 subtractor: ?Relocation,
638 code: []u8,638 code: []u8,
639 macho_file: *MachO,639 macho_file: *MachO,
640 bw: *Writer,640 writer: *Writer,
641) Writer.Error!void {641) Writer.Error!void {
642 const t = &macho_file.base.comp.root_mod.resolved_target.result;642 const t = &macho_file.base.comp.root_mod.resolved_target.result;
643 const cpu_arch = t.cpu.arch;643 const cpu_arch = t.cpu.arch;
...@@ -689,14 +689,14 @@ fn resolveRelocInner(...@@ -689,14 +689,14 @@ fn resolveRelocInner(
689 if (rel.tag == .@"extern") {689 if (rel.tag == .@"extern") {
690 const sym = rel.getTargetSymbol(self, macho_file);690 const sym = rel.getTargetSymbol(self, macho_file);
691 if (sym.isTlvInit(macho_file)) {691 if (sym.isTlvInit(macho_file)) {
692 try bw.writeInt(u64, @intCast(S - TLS), .little);692 try writer.writeInt(u64, @intCast(S - TLS), .little);
693 return;693 return;
694 }694 }
695 if (sym.flags.import) return;695 if (sym.flags.import) return;
696 }696 }
697 try bw.writeInt(u64, @bitCast(S + A - SUB), .little);697 try writer.writeInt(u64, @bitCast(S + A - SUB), .little);
698 } else if (rel.meta.length == 2) {698 } else if (rel.meta.length == 2) {
699 try bw.writeInt(u32, @bitCast(@as(i32, @truncate(S + A - SUB))), .little);699 try writer.writeInt(u32, @bitCast(@as(i32, @truncate(S + A - SUB))), .little);
700 } else unreachable;700 } else unreachable;
701 },701 },
702702
...@@ -704,7 +704,7 @@ fn resolveRelocInner(...@@ -704,7 +704,7 @@ fn resolveRelocInner(
704 assert(rel.tag == .@"extern");704 assert(rel.tag == .@"extern");
705 assert(rel.meta.length == 2);705 assert(rel.meta.length == 2);
706 assert(rel.meta.pcrel);706 assert(rel.meta.pcrel);
707 try bw.writeInt(i32, @intCast(G + A - P), .little);707 try writer.writeInt(i32, @intCast(G + A - P), .little);
708 },708 },
709709
710 .branch => {710 .branch => {
...@@ -713,7 +713,7 @@ fn resolveRelocInner(...@@ -713,7 +713,7 @@ fn resolveRelocInner(
713 assert(rel.tag == .@"extern");713 assert(rel.tag == .@"extern");
714714
715 switch (cpu_arch) {715 switch (cpu_arch) {
716 .x86_64 => try bw.writeInt(i32, @intCast(S + A - P), .little),716 .x86_64 => try writer.writeInt(i32, @intCast(S + A - P), .little),
717 .aarch64 => {717 .aarch64 => {
718 const disp: i28 = math.cast(i28, S + A - P) orelse blk: {718 const disp: i28 = math.cast(i28, S + A - P) orelse blk: {
719 const thunk = self.getThunk(macho_file);719 const thunk = self.getThunk(macho_file);
...@@ -731,10 +731,10 @@ fn resolveRelocInner(...@@ -731,10 +731,10 @@ fn resolveRelocInner(
731 assert(rel.meta.length == 2);731 assert(rel.meta.length == 2);
732 assert(rel.meta.pcrel);732 assert(rel.meta.pcrel);
733 if (rel.getTargetSymbol(self, macho_file).getSectionFlags().has_got) {733 if (rel.getTargetSymbol(self, macho_file).getSectionFlags().has_got) {
734 try bw.writeInt(i32, @intCast(G + A - P), .little);734 try writer.writeInt(i32, @intCast(G + A - P), .little);
735 } else {735 } else {
736 try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file);736 try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file);
737 try bw.writeInt(i32, @intCast(S + A - P), .little);737 try writer.writeInt(i32, @intCast(S + A - P), .little);
738 }738 }
739 },739 },
740740
...@@ -745,17 +745,17 @@ fn resolveRelocInner(...@@ -745,17 +745,17 @@ fn resolveRelocInner(
745 const sym = rel.getTargetSymbol(self, macho_file);745 const sym = rel.getTargetSymbol(self, macho_file);
746 if (sym.getSectionFlags().tlv_ptr) {746 if (sym.getSectionFlags().tlv_ptr) {
747 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));747 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));
748 try bw.writeInt(i32, @intCast(S_ + A - P), .little);748 try writer.writeInt(i32, @intCast(S_ + A - P), .little);
749 } else {749 } else {
750 try x86_64.relaxTlv(code[rel_offset - 3 ..], t);750 try x86_64.relaxTlv(code[rel_offset - 3 ..], t);
751 try bw.writeInt(i32, @intCast(S + A - P), .little);751 try writer.writeInt(i32, @intCast(S + A - P), .little);
752 }752 }
753 },753 },
754754
755 .signed, .signed1, .signed2, .signed4 => {755 .signed, .signed1, .signed2, .signed4 => {
756 assert(rel.meta.length == 2);756 assert(rel.meta.length == 2);
757 assert(rel.meta.pcrel);757 assert(rel.meta.pcrel);
758 try bw.writeInt(i32, @intCast(S + A - P), .little);758 try writer.writeInt(i32, @intCast(S + A - P), .little);
759 },759 },
760760
761 .page,761 .page,
...@@ -779,8 +779,7 @@ fn resolveRelocInner(...@@ -779,8 +779,7 @@ fn resolveRelocInner(
779 };779 };
780 break :target math.cast(u64, target) orelse return error.Overflow;780 break :target math.cast(u64, target) orelse return error.Overflow;
781 };781 };
782 const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(@intCast(source), @intCast(target))));782 aarch64.writeAdrInst(try aarch64.calcNumberOfPages(@intCast(source), @intCast(target)), code[rel_offset..][0..aarch64.encoding.Instruction.size]);
783 aarch64.writeAdrpInst(pages, code[rel_offset..][0..4]);
784 },783 },
785784
786 .pageoff => {785 .pageoff => {
...@@ -788,26 +787,18 @@ fn resolveRelocInner(...@@ -788,26 +787,18 @@ fn resolveRelocInner(
788 assert(rel.meta.length == 2);787 assert(rel.meta.length == 2);
789 assert(!rel.meta.pcrel);788 assert(!rel.meta.pcrel);
790 const target = math.cast(u64, S + A) orelse return error.Overflow;789 const target = math.cast(u64, S + A) orelse return error.Overflow;
791 const inst_code = code[rel_offset..][0..4];790 const inst_code = code[rel_offset..][0..aarch64.encoding.Instruction.size];
792 if (aarch64.isArithmeticOp(inst_code)) {791 var inst: aarch64.encoding.Instruction = .read(inst_code);
793 aarch64.writeAddImmInst(@truncate(target), inst_code);792 switch (inst.decode()) {
794 } else {793 else => unreachable,
795 var inst = aarch64.Instruction{794 .data_processing_immediate => aarch64.writeAddImmInst(@truncate(target), inst_code),
796 .load_store_register = mem.bytesToValue(@FieldType(795 .load_store => |load_store| {
797 aarch64.Instruction,796 inst.load_store.register_unsigned_immediate.group.imm12 = switch (load_store.register_unsigned_immediate.decode()) {
798 @tagName(aarch64.Instruction.load_store_register),797 .integer => |integer| try divExact(self, rel, @truncate(target), @as(u4, 1) << @intFromEnum(integer.group.size), macho_file),
799 ), inst_code),798 .vector => |vector| try divExact(self, rel, @truncate(target), @as(u5, 1) << @intFromEnum(vector.group.opc1.decode(vector.group.size)), macho_file),
800 };799 };
801 inst.load_store_register.offset = switch (inst.load_store_register.size) {800 try writer.writeInt(u32, @bitCast(inst), .little);
802 0 => if (inst.load_store_register.v == 1)801 },
803 try divExact(self, rel, @truncate(target), 16, macho_file)
804 else
805 @truncate(target),
806 1 => try divExact(self, rel, @truncate(target), 2, macho_file),
807 2 => try divExact(self, rel, @truncate(target), 4, macho_file),
808 3 => try divExact(self, rel, @truncate(target), 8, macho_file),
809 };
810 try bw.writeInt(u32, inst.toU32(), .little);
811 }802 }
812 },803 },
813804
...@@ -833,59 +824,26 @@ fn resolveRelocInner(...@@ -833,59 +824,26 @@ fn resolveRelocInner(
833 break :target math.cast(u64, target) orelse return error.Overflow;824 break :target math.cast(u64, target) orelse return error.Overflow;
834 };825 };
835826
836 const RegInfo = struct {
837 rd: u5,
838 rn: u5,
839 size: u2,
840 };
841
842 const inst_code = code[rel_offset..][0..4];827 const inst_code = code[rel_offset..][0..4];
843 const reg_info: RegInfo = blk: {828 const rd, const rn = switch (aarch64.encoding.Instruction.read(inst_code).decode()) {
844 if (aarch64.isArithmeticOp(inst_code)) {829 else => unreachable,
845 const inst = mem.bytesToValue(@FieldType(830 .data_processing_immediate => |decoded| .{
846 aarch64.Instruction,831 decoded.add_subtract_immediate.group.Rd.decodeInteger(.doubleword, .{ .sp = true }),
847 @tagName(aarch64.Instruction.add_subtract_immediate),832 decoded.add_subtract_immediate.group.Rn.decodeInteger(.doubleword, .{ .sp = true }),
848 ), inst_code);
849 break :blk .{
850 .rd = inst.rd,
851 .rn = inst.rn,
852 .size = inst.sf,
853 };
854 } else {
855 const inst = mem.bytesToValue(@FieldType(
856 aarch64.Instruction,
857 @tagName(aarch64.Instruction.load_store_register),
858 ), inst_code);
859 break :blk .{
860 .rd = inst.rt,
861 .rn = inst.rn,
862 .size = inst.size,
863 };
864 }
865 };
866
867 var inst = if (sym.getSectionFlags().tlv_ptr) aarch64.Instruction{
868 .load_store_register = .{
869 .rt = reg_info.rd,
870 .rn = reg_info.rn,
871 .offset = try divExact(self, rel, @truncate(target), 8, macho_file),
872 .opc = 0b01,
873 .op1 = 0b01,
874 .v = 0,
875 .size = reg_info.size,
876 },833 },
877 } else aarch64.Instruction{834 .load_store => |decoded| .{
878 .add_subtract_immediate = .{835 decoded.register_unsigned_immediate.integer.group.Rt.decodeInteger(.doubleword, .{}),
879 .rd = reg_info.rd,836 decoded.register_unsigned_immediate.group.Rn.decodeInteger(.doubleword, .{ .sp = true }),
880 .rn = reg_info.rn,
881 .imm12 = @truncate(target),
882 .sh = 0,
883 .s = 0,
884 .op = 0,
885 .sf = @as(u1, @truncate(reg_info.size)),
886 },837 },
887 };838 };
888 try bw.writeInt(u32, inst.toU32(), .little);839
840 try writer.writeInt(u32, @bitCast(@as(
841 aarch64.encoding.Instruction,
842 if (sym.getSectionFlags().tlv_ptr) .ldr(rd, .{ .unsigned_offset = .{
843 .base = rn,
844 .offset = try divExact(self, rel, @truncate(target), 8, macho_file) * 8,
845 } }) else .add(rd, rn, .{ .immediate = @truncate(target) }),
846 )), .little);
889 },847 },
890 }848 }
891}849}
src/link/MachO/Thunk.zig+7-5
...@@ -20,16 +20,18 @@ pub fn getTargetAddress(thunk: Thunk, ref: MachO.Ref, macho_file: *MachO) u64 {...@@ -20,16 +20,18 @@ pub fn getTargetAddress(thunk: Thunk, ref: MachO.Ref, macho_file: *MachO) u64 {
20 return thunk.getAddress(macho_file) + thunk.symbols.getIndex(ref).? * trampoline_size;20 return thunk.getAddress(macho_file) + thunk.symbols.getIndex(ref).? * trampoline_size;
21}21}
2222
23pub fn write(thunk: Thunk, macho_file: *MachO, bw: *Writer) !void {23pub fn write(thunk: Thunk, macho_file: *MachO, writer: *Writer) !void {
24 const Instruction = aarch64.encoding.Instruction;
24 for (thunk.symbols.keys(), 0..) |ref, i| {25 for (thunk.symbols.keys(), 0..) |ref, i| {
25 const sym = ref.getSymbol(macho_file).?;26 const sym = ref.getSymbol(macho_file).?;
26 const saddr = thunk.getAddress(macho_file) + i * trampoline_size;27 const saddr = thunk.getAddress(macho_file) + i * trampoline_size;
27 const taddr = sym.getAddress(.{}, macho_file);28 const taddr = sym.getAddress(.{}, macho_file);
28 const pages = try aarch64.calcNumberOfPages(@intCast(saddr), @intCast(taddr));29 const pages = try aarch64.calcNumberOfPages(@intCast(saddr), @intCast(taddr));
29 try bw.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);30 try writer.writeInt(u32, @bitCast(Instruction.adrp(.x16, pages << 12)), .little);
30 const off: u12 = @truncate(taddr);31 try writer.writeInt(u32, @bitCast(
31 try bw.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little);32 Instruction.add(.x16, .x16, .{ .immediate = @truncate(taddr) }),
32 try bw.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);33 ), .little);
34 try writer.writeInt(u32, @bitCast(Instruction.br(.x16)), .little);
33 }35 }
34}36}
3537
src/link/MachO/ZigObject.zig+7-3
...@@ -943,9 +943,13 @@ fn updateNavCode(...@@ -943,9 +943,13 @@ fn updateNavCode(
943943
944 log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });944 log.debug("updateNavCode {f} 0x{x}", .{ nav.fqn.fmt(ip), nav_index });
945945
946 const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;946 const mod = zcu.navFileScope(nav_index).mod.?;
947 const required_alignment = switch (pt.navAlignment(nav_index)) {947 const target = &mod.resolved_target.result;
948 .none => target_util.defaultFunctionAlignment(target),948 const required_alignment = switch (nav.status.fully_resolved.alignment) {
949 .none => switch (mod.optimize_mode) {
950 .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target),
951 .ReleaseSmall => target_util.minFunctionAlignment(target),
952 },
949 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),953 else => |a| a.maxStrict(target_util.minFunctionAlignment(target)),
950 };954 };
951955
src/link/MachO/synthetic.zig+77-86
...@@ -27,13 +27,13 @@ pub const GotSection = struct {...@@ -27,13 +27,13 @@ pub const GotSection = struct {
27 return got.symbols.items.len * @sizeOf(u64);27 return got.symbols.items.len * @sizeOf(u64);
28 }28 }
2929
30 pub fn write(got: GotSection, macho_file: *MachO, bw: *Writer) !void {30 pub fn write(got: GotSection, macho_file: *MachO, writer: *Writer) !void {
31 const tracy = trace(@src());31 const tracy = trace(@src());
32 defer tracy.end();32 defer tracy.end();
33 for (got.symbols.items) |ref| {33 for (got.symbols.items) |ref| {
34 const sym = ref.getSymbol(macho_file).?;34 const sym = ref.getSymbol(macho_file).?;
35 const value = if (sym.flags.import) @as(u64, 0) else sym.getAddress(.{}, macho_file);35 const value = if (sym.flags.import) @as(u64, 0) else sym.getAddress(.{}, macho_file);
36 try bw.writeInt(u64, value, .little);36 try writer.writeInt(u64, value, .little);
37 }37 }
38 }38 }
3939
...@@ -89,7 +89,7 @@ pub const StubsSection = struct {...@@ -89,7 +89,7 @@ pub const StubsSection = struct {
89 return stubs.symbols.items.len * header.reserved2;89 return stubs.symbols.items.len * header.reserved2;
90 }90 }
9191
92 pub fn write(stubs: StubsSection, macho_file: *MachO, bw: *Writer) !void {92 pub fn write(stubs: StubsSection, macho_file: *MachO, writer: *Writer) !void {
93 const tracy = trace(@src());93 const tracy = trace(@src());
94 defer tracy.end();94 defer tracy.end();
95 const cpu_arch = macho_file.getTarget().cpu.arch;95 const cpu_arch = macho_file.getTarget().cpu.arch;
...@@ -101,20 +101,19 @@ pub const StubsSection = struct {...@@ -101,20 +101,19 @@ pub const StubsSection = struct {
101 const target = laptr_sect.addr + idx * @sizeOf(u64);101 const target = laptr_sect.addr + idx * @sizeOf(u64);
102 switch (cpu_arch) {102 switch (cpu_arch) {
103 .x86_64 => {103 .x86_64 => {
104 try bw.writeAll(&.{ 0xff, 0x25 });104 try writer.writeAll(&.{ 0xff, 0x25 });
105 try bw.writeInt(i32, @intCast(target - source - 2 - 4), .little);105 try writer.writeInt(i32, @intCast(target - source - 2 - 4), .little);
106 },106 },
107 .aarch64 => {107 .aarch64 => {
108 const Instruction = aarch64.encoding.Instruction;
108 // TODO relax if possible109 // TODO relax if possible
109 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));110 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
110 try bw.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);111 try writer.writeInt(u32, @bitCast(Instruction.adrp(.x16, pages << 12)), .little);
111 const off = try math.divExact(u12, @truncate(target), 8);112 try writer.writeInt(u32, @bitCast(Instruction.ldr(
112 try bw.writeInt(113 .x16,
113 u32,114 .{ .unsigned_offset = .{ .base = .x16, .offset = @as(u12, @truncate(target)) } },
114 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),115 )), .little);
115 .little,116 try writer.writeInt(u32, @bitCast(Instruction.br(.x16)), .little);
116 );
117 try bw.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
118 },117 },
119 else => unreachable,118 else => unreachable,
120 }119 }
...@@ -175,11 +174,11 @@ pub const StubsHelperSection = struct {...@@ -175,11 +174,11 @@ pub const StubsHelperSection = struct {
175 return s;174 return s;
176 }175 }
177176
178 pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, bw: *Writer) !void {177 pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: *Writer) !void {
179 const tracy = trace(@src());178 const tracy = trace(@src());
180 defer tracy.end();179 defer tracy.end();
181180
182 try stubs_helper.writePreamble(macho_file, bw);181 try stubs_helper.writePreamble(macho_file, writer);
183182
184 const cpu_arch = macho_file.getTarget().cpu.arch;183 const cpu_arch = macho_file.getTarget().cpu.arch;
185 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];184 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];
...@@ -195,24 +194,22 @@ pub const StubsHelperSection = struct {...@@ -195,24 +194,22 @@ pub const StubsHelperSection = struct {
195 const target: i64 = @intCast(sect.addr);194 const target: i64 = @intCast(sect.addr);
196 switch (cpu_arch) {195 switch (cpu_arch) {
197 .x86_64 => {196 .x86_64 => {
198 try bw.writeByte(0x68);197 try writer.writeByte(0x68);
199 try bw.writeInt(u32, offset, .little);198 try writer.writeInt(u32, offset, .little);
200 try bw.writeByte(0xe9);199 try writer.writeByte(0xe9);
201 try bw.writeInt(i32, @intCast(target - source - 6 - 4), .little);200 try writer.writeInt(i32, @intCast(target - source - 6 - 4), .little);
202 },201 },
203 .aarch64 => {202 .aarch64 => {
204 const literal = blk: {203 const Instruction = aarch64.encoding.Instruction;
205 const div_res = try std.math.divExact(u64, entry_size - @sizeOf(u32), 4);204 if (entry_size % Instruction.size != 0) return error.UnexpectedRemainder;
206 break :blk std.math.cast(u18, div_res) orelse return error.Overflow;205 try writer.writeInt(u32, @bitCast(
207 };206 Instruction.ldr(.w16, .{ .literal = std.math.cast(i21, entry_size - Instruction.size) orelse
208 try bw.writeInt(u32, aarch64.Instruction.ldrLiteral(207 return error.Overflow }),
209 .w16,208 ), .little);
210 literal,
211 ).toU32(), .little);
212 const disp = math.cast(i28, @as(i64, @intCast(target)) - @as(i64, @intCast(source + 4))) orelse209 const disp = math.cast(i28, @as(i64, @intCast(target)) - @as(i64, @intCast(source + 4))) orelse
213 return error.Overflow;210 return error.Overflow;
214 try bw.writeInt(u32, aarch64.Instruction.b(disp).toU32(), .little);211 try writer.writeInt(u32, @bitCast(Instruction.b(disp)), .little);
215 try bw.writeAll(&.{ 0x0, 0x0, 0x0, 0x0 });212 try writer.writeInt(u32, @bitCast(Instruction.udf(0x0)), .little);
216 },213 },
217 else => unreachable,214 else => unreachable,
218 }215 }
...@@ -220,7 +217,7 @@ pub const StubsHelperSection = struct {...@@ -220,7 +217,7 @@ pub const StubsHelperSection = struct {
220 }217 }
221 }218 }
222219
223 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, bw: *Writer) !void {220 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: *Writer) !void {
224 _ = stubs_helper;221 _ = stubs_helper;
225 const obj = macho_file.getInternalObject().?;222 const obj = macho_file.getInternalObject().?;
226 const cpu_arch = macho_file.getTarget().cpu.arch;223 const cpu_arch = macho_file.getTarget().cpu.arch;
...@@ -235,38 +232,35 @@ pub const StubsHelperSection = struct {...@@ -235,38 +232,35 @@ pub const StubsHelperSection = struct {
235 };232 };
236 switch (cpu_arch) {233 switch (cpu_arch) {
237 .x86_64 => {234 .x86_64 => {
238 try bw.writeAll(&.{ 0x4c, 0x8d, 0x1d });235 try writer.writeAll(&.{ 0x4c, 0x8d, 0x1d });
239 try bw.writeInt(i32, @intCast(dyld_private_addr - sect.addr - 3 - 4), .little);236 try writer.writeInt(i32, @intCast(dyld_private_addr - sect.addr - 3 - 4), .little);
240 try bw.writeAll(&.{ 0x41, 0x53, 0xff, 0x25 });237 try writer.writeAll(&.{ 0x41, 0x53, 0xff, 0x25 });
241 try bw.writeInt(i32, @intCast(dyld_stub_binder_addr - sect.addr - 11 - 4), .little);238 try writer.writeInt(i32, @intCast(dyld_stub_binder_addr - sect.addr - 11 - 4), .little);
242 try bw.writeByte(0x90);239 try writer.writeByte(0x90);
243 },240 },
244 .aarch64 => {241 .aarch64 => {
242 const Instruction = aarch64.encoding.Instruction;
245 {243 {
246 // TODO relax if possible244 // TODO relax if possible
247 const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr), @intCast(dyld_private_addr));245 const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr), @intCast(dyld_private_addr));
248 try bw.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little);246 try writer.writeInt(Instruction.Backing, @bitCast(Instruction.adrp(.x17, pages << 12)), .little);
249 const off: u12 = @truncate(dyld_private_addr);247 try writer.writeInt(Instruction.Backing, @bitCast(
250 try bw.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little);248 Instruction.add(.x17, .x17, .{ .immediate = @as(u12, @truncate(dyld_private_addr)) }),
249 ), .little);
251 }250 }
252 try bw.writeInt(u32, aarch64.Instruction.stp(251 try writer.writeInt(Instruction.Backing, @bitCast(
253 .x16,252 Instruction.stp(.x16, .x17, .{ .pre_index = .{ .base = .sp, .index = -16 } }),
254 .x17,253 ), .little);
255 aarch64.Register.sp,
256 aarch64.Instruction.LoadStorePairOffset.pre_index(-16),
257 ).toU32(), .little);
258 {254 {
259 // TODO relax if possible255 // TODO relax if possible
260 const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr + 12), @intCast(dyld_stub_binder_addr));256 const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr + 12), @intCast(dyld_stub_binder_addr));
261 try bw.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);257 try writer.writeInt(Instruction.Backing, @bitCast(Instruction.adrp(.x16, pages << 12)), .little);
262 const off = try math.divExact(u12, @truncate(dyld_stub_binder_addr), 8);258 try writer.writeInt(Instruction.Backing, @bitCast(Instruction.ldr(
263 try bw.writeInt(u32, aarch64.Instruction.ldr(
264 .x16,
265 .x16,259 .x16,
266 aarch64.Instruction.LoadStoreOffset.imm(off),260 .{ .unsigned_offset = .{ .base = .x16, .offset = @as(u12, @truncate(dyld_stub_binder_addr)) } },
267 ).toU32(), .little);261 )), .little);
268 }262 }
269 try bw.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);263 try writer.writeInt(Instruction.Backing, @bitCast(Instruction.br(.x16)), .little);
270 },264 },
271 else => unreachable,265 else => unreachable,
272 }266 }
...@@ -279,7 +273,7 @@ pub const LaSymbolPtrSection = struct {...@@ -279,7 +273,7 @@ pub const LaSymbolPtrSection = struct {
279 return macho_file.stubs.symbols.items.len * @sizeOf(u64);273 return macho_file.stubs.symbols.items.len * @sizeOf(u64);
280 }274 }
281275
282 pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, bw: *Writer) !void {276 pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: *Writer) !void {
283 const tracy = trace(@src());277 const tracy = trace(@src());
284 defer tracy.end();278 defer tracy.end();
285 _ = laptr;279 _ = laptr;
...@@ -290,12 +284,12 @@ pub const LaSymbolPtrSection = struct {...@@ -290,12 +284,12 @@ pub const LaSymbolPtrSection = struct {
290 const sym = ref.getSymbol(macho_file).?;284 const sym = ref.getSymbol(macho_file).?;
291 if (sym.flags.weak) {285 if (sym.flags.weak) {
292 const value = sym.getAddress(.{ .stubs = false }, macho_file);286 const value = sym.getAddress(.{ .stubs = false }, macho_file);
293 try bw.writeInt(u64, @intCast(value), .little);287 try writer.writeInt(u64, @intCast(value), .little);
294 } else {288 } else {
295 const value = sect.addr + StubsHelperSection.preambleSize(cpu_arch) +289 const value = sect.addr + StubsHelperSection.preambleSize(cpu_arch) +
296 StubsHelperSection.entrySize(cpu_arch) * stub_helper_idx;290 StubsHelperSection.entrySize(cpu_arch) * stub_helper_idx;
297 stub_helper_idx += 1;291 stub_helper_idx += 1;
298 try bw.writeInt(u64, @intCast(value), .little);292 try writer.writeInt(u64, @intCast(value), .little);
299 }293 }
300 }294 }
301 }295 }
...@@ -329,16 +323,16 @@ pub const TlvPtrSection = struct {...@@ -329,16 +323,16 @@ pub const TlvPtrSection = struct {
329 return tlv.symbols.items.len * @sizeOf(u64);323 return tlv.symbols.items.len * @sizeOf(u64);
330 }324 }
331325
332 pub fn write(tlv: TlvPtrSection, macho_file: *MachO, bw: *Writer) !void {326 pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: *Writer) !void {
333 const tracy = trace(@src());327 const tracy = trace(@src());
334 defer tracy.end();328 defer tracy.end();
335329
336 for (tlv.symbols.items) |ref| {330 for (tlv.symbols.items) |ref| {
337 const sym = ref.getSymbol(macho_file).?;331 const sym = ref.getSymbol(macho_file).?;
338 if (sym.flags.import) {332 if (sym.flags.import) {
339 try bw.writeInt(u64, 0, .little);333 try writer.writeInt(u64, 0, .little);
340 } else {334 } else {
341 try bw.writeInt(u64, sym.getAddress(.{}, macho_file), .little);335 try writer.writeInt(u64, sym.getAddress(.{}, macho_file), .little);
342 }336 }
343 }337 }
344 }338 }
...@@ -400,7 +394,7 @@ pub const ObjcStubsSection = struct {...@@ -400,7 +394,7 @@ pub const ObjcStubsSection = struct {
400 return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch);394 return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch);
401 }395 }
402396
403 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, bw: *Writer) !void {397 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: *Writer) !void {
404 const tracy = trace(@src());398 const tracy = trace(@src());
405 defer tracy.end();399 defer tracy.end();
406400
...@@ -411,50 +405,47 @@ pub const ObjcStubsSection = struct {...@@ -411,50 +405,47 @@ pub const ObjcStubsSection = struct {
411 const addr = objc.getAddress(@intCast(idx), macho_file);405 const addr = objc.getAddress(@intCast(idx), macho_file);
412 switch (macho_file.getTarget().cpu.arch) {406 switch (macho_file.getTarget().cpu.arch) {
413 .x86_64 => {407 .x86_64 => {
414 try bw.writeAll(&.{ 0x48, 0x8b, 0x35 });408 try writer.writeAll(&.{ 0x48, 0x8b, 0x35 });
415 {409 {
416 const target = sym.getObjcSelrefsAddress(macho_file);410 const target = sym.getObjcSelrefsAddress(macho_file);
417 const source = addr;411 const source = addr;
418 try bw.writeInt(i32, @intCast(target - source - 3 - 4), .little);412 try writer.writeInt(i32, @intCast(target - source - 3 - 4), .little);
419 }413 }
420 try bw.writeAll(&.{ 0xff, 0x25 });414 try writer.writeAll(&.{ 0xff, 0x25 });
421 {415 {
422 const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;416 const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;
423 const target = target_sym.getGotAddress(macho_file);417 const target = target_sym.getGotAddress(macho_file);
424 const source = addr + 7;418 const source = addr + 7;
425 try bw.writeInt(i32, @intCast(target - source - 2 - 4), .little);419 try writer.writeInt(i32, @intCast(target - source - 2 - 4), .little);
426 }420 }
427 },421 },
428 .aarch64 => {422 .aarch64 => {
423 const Instruction = aarch64.encoding.Instruction;
429 {424 {
430 const target = sym.getObjcSelrefsAddress(macho_file);425 const target = sym.getObjcSelrefsAddress(macho_file);
431 const source = addr;426 const source = addr;
432 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));427 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
433 try bw.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little);428 try writer.writeInt(u32, @bitCast(Instruction.adrp(.x1, pages << 12)), .little);
434 const off = try math.divExact(u12, @truncate(target), 8);429 try writer.writeInt(u32, @bitCast(Instruction.ldr(
435 try bw.writeInt(430 .x1,
436 u32,431 .{ .unsigned_offset = .{ .base = .x1, .offset = @as(u12, @truncate(target)) } },
437 aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),432 )), .little);
438 .little,
439 );
440 }433 }
441 {434 {
442 const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;435 const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;
443 const target = target_sym.getGotAddress(macho_file);436 const target = target_sym.getGotAddress(macho_file);
444 const source = addr + 2 * @sizeOf(u32);437 const source = addr + 2 * @sizeOf(u32);
445 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));438 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
446 try bw.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);439 try writer.writeInt(u32, @bitCast(Instruction.adrp(.x16, pages << 12)), .little);
447 const off = try math.divExact(u12, @truncate(target), 8);440 try writer.writeInt(u32, @bitCast(Instruction.ldr(
448 try bw.writeInt(441 .x16,
449 u32,442 .{ .unsigned_offset = .{ .base = .x16, .offset = @as(u12, @truncate(target)) } },
450 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),443 )), .little);
451 .little,
452 );
453 }444 }
454 try bw.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);445 try writer.writeInt(u32, @bitCast(Instruction.br(.x16)), .little);
455 try bw.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);446 try writer.writeInt(u32, @bitCast(Instruction.brk(0x1)), .little);
456 try bw.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);447 try writer.writeInt(u32, @bitCast(Instruction.brk(0x1)), .little);
457 try bw.writeInt(u32, aarch64.Instruction.brk(1).toU32(), .little);448 try writer.writeInt(u32, @bitCast(Instruction.brk(0x1)), .little);
458 },449 },
459 else => unreachable,450 else => unreachable,
460 }451 }
...@@ -496,7 +487,7 @@ pub const Indsymtab = struct {...@@ -496,7 +487,7 @@ pub const Indsymtab = struct {
496 macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file);487 macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file);
497 }488 }
498489
499 pub fn write(ind: Indsymtab, macho_file: *MachO, bw: *Writer) !void {490 pub fn write(ind: Indsymtab, macho_file: *MachO, writer: *Writer) !void {
500 const tracy = trace(@src());491 const tracy = trace(@src());
501 defer tracy.end();492 defer tracy.end();
502493
...@@ -505,21 +496,21 @@ pub const Indsymtab = struct {...@@ -505,21 +496,21 @@ pub const Indsymtab = struct {
505 for (macho_file.stubs.symbols.items) |ref| {496 for (macho_file.stubs.symbols.items) |ref| {
506 const sym = ref.getSymbol(macho_file).?;497 const sym = ref.getSymbol(macho_file).?;
507 if (sym.getOutputSymtabIndex(macho_file)) |idx| {498 if (sym.getOutputSymtabIndex(macho_file)) |idx| {
508 try bw.writeInt(u32, idx, .little);499 try writer.writeInt(u32, idx, .little);
509 }500 }
510 }501 }
511502
512 for (macho_file.got.symbols.items) |ref| {503 for (macho_file.got.symbols.items) |ref| {
513 const sym = ref.getSymbol(macho_file).?;504 const sym = ref.getSymbol(macho_file).?;
514 if (sym.getOutputSymtabIndex(macho_file)) |idx| {505 if (sym.getOutputSymtabIndex(macho_file)) |idx| {
515 try bw.writeInt(u32, idx, .little);506 try writer.writeInt(u32, idx, .little);
516 }507 }
517 }508 }
518509
519 for (macho_file.stubs.symbols.items) |ref| {510 for (macho_file.stubs.symbols.items) |ref| {
520 const sym = ref.getSymbol(macho_file).?;511 const sym = ref.getSymbol(macho_file).?;
521 if (sym.getOutputSymtabIndex(macho_file)) |idx| {512 if (sym.getOutputSymtabIndex(macho_file)) |idx| {
522 try bw.writeInt(u32, idx, .little);513 try writer.writeInt(u32, idx, .little);
523 }514 }
524 }515 }
525 }516 }
...@@ -573,7 +564,7 @@ pub const DataInCode = struct {...@@ -573,7 +564,7 @@ pub const DataInCode = struct {
573 macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow;564 macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow;
574 }565 }
575566
576 pub fn write(dice: DataInCode, macho_file: *MachO, bw: *Writer) !void {567 pub fn write(dice: DataInCode, macho_file: *MachO, writer: *Writer) !void {
577 const base_address = if (!macho_file.base.isRelocatable())568 const base_address = if (!macho_file.base.isRelocatable())
578 macho_file.getTextSegment().vmaddr569 macho_file.getTextSegment().vmaddr
579 else570 else
...@@ -581,7 +572,7 @@ pub const DataInCode = struct {...@@ -581,7 +572,7 @@ pub const DataInCode = struct {
581 for (dice.entries.items) |entry| {572 for (dice.entries.items) |entry| {
582 const atom_address = entry.atom_ref.getAtom(macho_file).?.getAddress(macho_file);573 const atom_address = entry.atom_ref.getAtom(macho_file).?.getAddress(macho_file);
583 const offset = atom_address + entry.offset - base_address;574 const offset = atom_address + entry.offset - base_address;
584 try bw.writeStruct(macho.data_in_code_entry{575 try writer.writeStruct(macho.data_in_code_entry{
585 .offset = @intCast(offset),576 .offset = @intCast(offset),
586 .length = entry.length,577 .length = entry.length,
587 .kind = entry.kind,578 .kind = entry.kind,
src/link/aarch64.zig+17-47
...@@ -1,66 +1,36 @@...@@ -1,66 +1,36 @@
1pub inline fn isArithmeticOp(inst: *const [4]u8) bool {1pub const encoding = @import("../codegen.zig").aarch64.encoding;
2 const group_decode = @as(u5, @truncate(inst[3]));
3 return ((group_decode >> 2) == 4);
4}
52
6pub fn writeAddImmInst(value: u12, code: *[4]u8) void {3pub fn writeAddImmInst(value: u12, code: *[4]u8) void {
7 var inst: Instruction = .{4 var inst: encoding.Instruction = .read(code);
8 .add_subtract_immediate = mem.bytesToValue(@FieldType(5 inst.data_processing_immediate.add_subtract_immediate.group.imm12 = value;
9 Instruction,6 inst.write(code);
10 @tagName(Instruction.add_subtract_immediate),
11 ), code),
12 };
13 inst.add_subtract_immediate.imm12 = value;
14 mem.writeInt(u32, code, inst.toU32(), .little);
15}7}
168
17pub fn writeLoadStoreRegInst(value: u12, code: *[4]u8) void {9pub fn writeLoadStoreRegInst(value: u12, code: *[4]u8) void {
18 var inst: Instruction = .{10 var inst: encoding.Instruction = .read(code);
19 .load_store_register = mem.bytesToValue(@FieldType(11 inst.load_store.register_unsigned_immediate.group.imm12 = value;
20 Instruction,12 inst.write(code);
21 @tagName(Instruction.load_store_register),
22 ), code),
23 };
24 inst.load_store_register.offset = value;
25 mem.writeInt(u32, code, inst.toU32(), .little);
26}13}
2714
28pub fn calcNumberOfPages(saddr: i64, taddr: i64) error{Overflow}!i21 {15pub fn calcNumberOfPages(saddr: i64, taddr: i64) error{Overflow}!i33 {
29 const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow;16 return math.cast(i21, (taddr >> 12) - (saddr >> 12)) orelse error.Overflow;
30 const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow;
31 const pages = math.cast(i21, tpage - spage) orelse return error.Overflow;
32 return pages;
33}17}
3418
35pub fn writeAdrpInst(pages: u21, code: *[4]u8) void {19pub fn writeAdrInst(imm: i33, code: *[4]u8) void {
36 var inst: Instruction = .{20 var inst: encoding.Instruction = .read(code);
37 .pc_relative_address = mem.bytesToValue(@FieldType(21 inst.data_processing_immediate.pc_relative_addressing.group.immhi = @intCast(imm >> 2);
38 Instruction,22 inst.data_processing_immediate.pc_relative_addressing.group.immlo = @bitCast(@as(i2, @truncate(imm)));
39 @tagName(Instruction.pc_relative_address),23 inst.write(code);
40 ), code),
41 };
42 inst.pc_relative_address.immhi = @as(u19, @truncate(pages >> 2));
43 inst.pc_relative_address.immlo = @as(u2, @truncate(pages));
44 mem.writeInt(u32, code, inst.toU32(), .little);
45}24}
4625
47pub fn writeBranchImm(disp: i28, code: *[4]u8) void {26pub fn writeBranchImm(disp: i28, code: *[4]u8) void {
48 var inst: Instruction = .{27 var inst: encoding.Instruction = .read(code);
49 .unconditional_branch_immediate = mem.bytesToValue(@FieldType(28 inst.branch_exception_generating_system.unconditional_branch_immediate.group.imm26 = @intCast(@shrExact(disp, 2));
50 Instruction,29 inst.write(code);
51 @tagName(Instruction.unconditional_branch_immediate),
52 ), code),
53 };
54 inst.unconditional_branch_immediate.imm26 = @as(u26, @truncate(@as(u28, @bitCast(disp >> 2))));
55 mem.writeInt(u32, code, inst.toU32(), .little);
56}30}
5731
58const assert = std.debug.assert;32const assert = std.debug.assert;
59const bits = @import("../arch/aarch64/bits.zig");
60const builtin = @import("builtin");33const builtin = @import("builtin");
61const math = std.math;34const math = std.math;
62const mem = std.mem;35const mem = std.mem;
63const std = @import("std");36const std = @import("std");
64
65pub const Instruction = bits.Instruction;
66pub const Register = bits.Register;
src/main.zig+1
...@@ -37,6 +37,7 @@ const dev = @import("dev.zig");...@@ -37,6 +37,7 @@ const dev = @import("dev.zig");
3737
38test {38test {
39 _ = Package;39 _ = Package;
40 _ = @import("codegen.zig");
40}41}
4142
42const thread_stack_size = 60 << 20;43const thread_stack_size = 60 << 20;
src/target.zig+14-4
...@@ -347,7 +347,7 @@ pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.builtin.Opti...@@ -347,7 +347,7 @@ pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.builtin.Opti
347 }347 }
348}348}
349349
350pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool {350pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool {
351 switch (target.os.tag) {351 switch (target.os.tag) {
352 .plan9 => return false,352 .plan9 => return false,
353 else => {},353 else => {},
...@@ -359,6 +359,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llv...@@ -359,6 +359,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llv
359 else => {},359 else => {},
360 }360 }
361 return switch (zigBackend(target, use_llvm)) {361 return switch (zigBackend(target, use_llvm)) {
362 .stage2_aarch64 => true,
362 .stage2_llvm => true,363 .stage2_llvm => true,
363 .stage2_x86_64 => switch (target.ofmt) {364 .stage2_x86_64 => switch (target.ofmt) {
364 .elf, .macho => true,365 .elf, .macho => true,
...@@ -368,13 +369,21 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llv...@@ -368,13 +369,21 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llv
368 };369 };
369}370}
370371
371pub fn canBuildLibUbsanRt(target: *const std.Target) bool {372pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool {
372 switch (target.cpu.arch) {373 switch (target.cpu.arch) {
373 .spirv32, .spirv64 => return false,374 .spirv32, .spirv64 => return false,
374 // Remove this once https://github.com/ziglang/zig/issues/23715 is fixed375 // Remove this once https://github.com/ziglang/zig/issues/23715 is fixed
375 .nvptx, .nvptx64 => return false,376 .nvptx, .nvptx64 => return false,
376 else => return true,377 else => {},
377 }378 }
379 return switch (zigBackend(target, use_llvm)) {
380 .stage2_llvm => true,
381 .stage2_x86_64 => switch (target.ofmt) {
382 .elf, .macho => true,
383 else => have_llvm,
384 },
385 else => have_llvm,
386 };
378}387}
379388
380pub fn hasRedZone(target: *const std.Target) bool {389pub fn hasRedZone(target: *const std.Target) bool {
...@@ -767,6 +776,7 @@ pub fn supportsTailCall(target: *const std.Target, backend: std.builtin.Compiler...@@ -767,6 +776,7 @@ pub fn supportsTailCall(target: *const std.Target, backend: std.builtin.Compiler
767776
768pub fn supportsThreads(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {777pub fn supportsThreads(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {
769 return switch (backend) {778 return switch (backend) {
779 .stage2_aarch64 => false,
770 .stage2_powerpc => true,780 .stage2_powerpc => true,
771 .stage2_x86_64 => target.ofmt == .macho or target.ofmt == .elf,781 .stage2_x86_64 => target.ofmt == .macho or target.ofmt == .elf,
772 else => true,782 else => true,
...@@ -864,7 +874,7 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt...@@ -864,7 +874,7 @@ pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, compt
864 else => false,874 else => false,
865 },875 },
866 .field_reordering => switch (backend) {876 .field_reordering => switch (backend) {
867 .stage2_c, .stage2_llvm, .stage2_x86_64 => true,877 .stage2_aarch64, .stage2_c, .stage2_llvm, .stage2_x86_64 => true,
868 else => false,878 else => false,
869 },879 },
870 .separate_thread => switch (backend) {880 .separate_thread => switch (backend) {
stage1/zig1.wasm
Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ
test/behavior.zig+2-2
...@@ -123,7 +123,6 @@ test {...@@ -123,7 +123,6 @@ test {
123 }123 }
124124
125 if (builtin.zig_backend != .stage2_arm and125 if (builtin.zig_backend != .stage2_arm and
126 builtin.zig_backend != .stage2_aarch64 and
127 builtin.zig_backend != .stage2_spirv)126 builtin.zig_backend != .stage2_spirv)
128 {127 {
129 _ = @import("behavior/export_keyword.zig");128 _ = @import("behavior/export_keyword.zig");
...@@ -141,7 +140,8 @@ test {...@@ -141,7 +140,8 @@ test {
141}140}
142141
143// This bug only repros in the root file142// This bug only repros in the root file
144test "deference @embedFile() of a file full of zero bytes" {143test "dereference @embedFile() of a file full of zero bytes" {
144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
145 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;145 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
146146
147 const contents = @embedFile("behavior/zero.bin").*;147 const contents = @embedFile("behavior/zero.bin").*;
test/behavior/abs.zig+3-7
...@@ -3,7 +3,6 @@ const std = @import("std");...@@ -3,7 +3,6 @@ const std = @import("std");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "@abs integers" {5test "@abs integers" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -50,7 +49,6 @@ fn testAbsIntegers() !void {...@@ -50,7 +49,6 @@ fn testAbsIntegers() !void {
50}49}
5150
52test "@abs unsigned integers" {51test "@abs unsigned integers" {
53 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
54 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO53 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5654
...@@ -90,7 +88,6 @@ fn testAbsUnsignedIntegers() !void {...@@ -90,7 +88,6 @@ fn testAbsUnsignedIntegers() !void {
90}88}
9189
92test "@abs big int <= 128 bits" {90test "@abs big int <= 128 bits" {
93 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO91 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
95 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO92 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
96 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO93 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
...@@ -153,7 +150,6 @@ fn testAbsUnsignedBigInt() !void {...@@ -153,7 +150,6 @@ fn testAbsUnsignedBigInt() !void {
153}150}
154151
155test "@abs floats" {152test "@abs floats" {
156 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO154 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159155
...@@ -207,9 +203,9 @@ fn testAbsFloats(comptime T: type) !void {...@@ -207,9 +203,9 @@ fn testAbsFloats(comptime T: type) !void {
207}203}
208204
209test "@abs int vectors" {205test "@abs int vectors" {
206 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
210 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO207 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
211 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO208 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
213 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
214 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO210 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
215 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;211 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -275,8 +271,8 @@ fn testAbsIntVectors(comptime len: comptime_int) !void {...@@ -275,8 +271,8 @@ fn testAbsIntVectors(comptime len: comptime_int) !void {
275}271}
276272
277test "@abs unsigned int vectors" {273test "@abs unsigned int vectors" {
274 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
278 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO275 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
279 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO276 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO277 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
282 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;278 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -334,8 +330,8 @@ fn testAbsUnsignedIntVectors(comptime len: comptime_int) !void {...@@ -334,8 +330,8 @@ fn testAbsUnsignedIntVectors(comptime len: comptime_int) !void {
334}330}
335331
336test "@abs float vectors" {332test "@abs float vectors" {
333 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
337 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO334 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
338 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO335 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
340 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO336 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
341 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;337 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/align.zig+1-19
...@@ -16,7 +16,6 @@ test "global variable alignment" {...@@ -16,7 +16,6 @@ test "global variable alignment" {
16}16}
1717
18test "large alignment of local constant" {18test "large alignment of local constant" {
19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky20 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky
2221
...@@ -25,7 +24,6 @@ test "large alignment of local constant" {...@@ -25,7 +24,6 @@ test "large alignment of local constant" {
25}24}
2625
27test "slicing array of length 1 can not assume runtime index is always zero" {26test "slicing array of length 1 can not assume runtime index is always zero" {
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO27 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky28 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky
3129
...@@ -74,7 +72,6 @@ test "alignment of struct with pointer has same alignment as usize" {...@@ -74,7 +72,6 @@ test "alignment of struct with pointer has same alignment as usize" {
7472
75test "alignment and size of structs with 128-bit fields" {73test "alignment and size of structs with 128-bit fields" {
76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO74 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7976
80 const A = struct {77 const A = struct {
...@@ -160,7 +157,6 @@ test "alignment and size of structs with 128-bit fields" {...@@ -160,7 +157,6 @@ test "alignment and size of structs with 128-bit fields" {
160}157}
161158
162test "implicitly decreasing slice alignment" {159test "implicitly decreasing slice alignment" {
163 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO160 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
165 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;161 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
166162
...@@ -173,7 +169,6 @@ fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {...@@ -173,7 +169,6 @@ fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
173}169}
174170
175test "specifying alignment allows pointer cast" {171test "specifying alignment allows pointer cast" {
176 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
177 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO172 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
178 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;173 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
179174
...@@ -186,7 +181,6 @@ fn testBytesAlign(b: u8) !void {...@@ -186,7 +181,6 @@ fn testBytesAlign(b: u8) !void {
186}181}
187182
188test "@alignCast slices" {183test "@alignCast slices" {
189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
190 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;184 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
191 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO185 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
192 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;186 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -205,7 +199,6 @@ fn sliceExpects4(slice: []align(4) u32) void {...@@ -205,7 +199,6 @@ fn sliceExpects4(slice: []align(4) u32) void {
205199
206test "return error union with 128-bit integer" {200test "return error union with 128-bit integer" {
207 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO201 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
208 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
210 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
211 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;204 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -218,7 +211,6 @@ fn give() anyerror!u128 {...@@ -218,7 +211,6 @@ fn give() anyerror!u128 {
218211
219test "page aligned array on stack" {212test "page aligned array on stack" {
220 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO213 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
221 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;214 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
223 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
224 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;216 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -238,7 +230,6 @@ test "page aligned array on stack" {...@@ -238,7 +230,6 @@ test "page aligned array on stack" {
238}230}
239231
240test "function alignment" {232test "function alignment" {
241 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
242 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;233 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
243 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO234 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
244 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;235 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -268,7 +259,6 @@ test "function alignment" {...@@ -268,7 +259,6 @@ test "function alignment" {
268}259}
269260
270test "implicitly decreasing fn alignment" {261test "implicitly decreasing fn alignment" {
271 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
272 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
273 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
274 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;264 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -292,7 +282,6 @@ fn alignedBig() align(16) i32 {...@@ -292,7 +282,6 @@ fn alignedBig() align(16) i32 {
292}282}
293283
294test "@alignCast functions" {284test "@alignCast functions" {
295 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
296 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;285 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
297 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO286 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
298 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;287 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -376,7 +365,6 @@ const DefaultAligned = struct {...@@ -376,7 +365,6 @@ const DefaultAligned = struct {
376365
377test "read 128-bit field from default aligned struct in stack memory" {366test "read 128-bit field from default aligned struct in stack memory" {
378 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO367 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
379 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
380 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;368 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
381 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO369 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
382 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;370 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -396,7 +384,6 @@ var default_aligned_global = DefaultAligned{...@@ -396,7 +384,6 @@ var default_aligned_global = DefaultAligned{
396384
397test "read 128-bit field from default aligned struct in global memory" {385test "read 128-bit field from default aligned struct in global memory" {
398 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO386 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
399 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
400 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;387 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
401 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO388 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
402 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;389 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -405,8 +392,8 @@ test "read 128-bit field from default aligned struct in global memory" {...@@ -405,8 +392,8 @@ test "read 128-bit field from default aligned struct in global memory" {
405}392}
406393
407test "struct field explicit alignment" {394test "struct field explicit alignment" {
408 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
409 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;395 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
396 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
410 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO397 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
411 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky398 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky
412 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO399 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
...@@ -426,7 +413,6 @@ test "struct field explicit alignment" {...@@ -426,7 +413,6 @@ test "struct field explicit alignment" {
426}413}
427414
428test "align(N) on functions" {415test "align(N) on functions" {
429 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
430 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO416 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
431 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO417 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
432 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;418 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -455,7 +441,6 @@ test "comptime alloc alignment" {...@@ -455,7 +441,6 @@ test "comptime alloc alignment" {
455 // TODO: it's impossible to test this in Zig today, since comptime vars do not have runtime addresses.441 // TODO: it's impossible to test this in Zig today, since comptime vars do not have runtime addresses.
456 if (true) return error.SkipZigTest;442 if (true) return error.SkipZigTest;
457 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO443 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
458 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
459 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO444 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
460 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky445 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // flaky
461446
...@@ -468,7 +453,6 @@ test "comptime alloc alignment" {...@@ -468,7 +453,6 @@ test "comptime alloc alignment" {
468}453}
469454
470test "@alignCast null" {455test "@alignCast null" {
471 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
472 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO456 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;457 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
474458
...@@ -484,7 +468,6 @@ test "alignment of slice element" {...@@ -484,7 +468,6 @@ test "alignment of slice element" {
484}468}
485469
486test "sub-aligned pointer field access" {470test "sub-aligned pointer field access" {
487 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
488 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;471 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
489 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;472 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
490 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;473 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -538,7 +521,6 @@ test "alignment of zero-bit types is respected" {...@@ -538,7 +521,6 @@ test "alignment of zero-bit types is respected" {
538521
539test "zero-bit fields in extern struct pad fields appropriately" {522test "zero-bit fields in extern struct pad fields appropriately" {
540 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO523 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
541 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
542 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;524 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
543 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;525 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
544 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;526 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/array.zig+5-37
...@@ -19,7 +19,6 @@ test "array to slice" {...@@ -19,7 +19,6 @@ test "array to slice" {
19}19}
2020
21test "arrays" {21test "arrays" {
22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2524
...@@ -47,7 +46,6 @@ fn getArrayLen(a: []const u32) usize {...@@ -47,7 +46,6 @@ fn getArrayLen(a: []const u32) usize {
47}46}
4847
49test "array concat with undefined" {48test "array concat with undefined" {
50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO49 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
52 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;50 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
5351
...@@ -73,7 +71,6 @@ test "array concat with undefined" {...@@ -73,7 +71,6 @@ test "array concat with undefined" {
73test "array concat with tuple" {71test "array concat with tuple" {
74 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;72 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
75 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO74 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7875
79 const array: [2]u8 = .{ 1, 2 };76 const array: [2]u8 = .{ 1, 2 };
...@@ -89,7 +86,6 @@ test "array concat with tuple" {...@@ -89,7 +86,6 @@ test "array concat with tuple" {
8986
90test "array init with concat" {87test "array init with concat" {
91 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;88 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
92 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9389
94 const a = 'a';90 const a = 'a';
95 var i: [4]u8 = [2]u8{ a, 'b' } ++ [2]u8{ 'c', 'd' };91 var i: [4]u8 = [2]u8{ a, 'b' } ++ [2]u8{ 'c', 'd' };
...@@ -98,7 +94,6 @@ test "array init with concat" {...@@ -98,7 +94,6 @@ test "array init with concat" {
9894
99test "array init with mult" {95test "array init with mult" {
100 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;96 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO97 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10398
104 const a = 'a';99 const a = 'a';
...@@ -110,7 +105,6 @@ test "array init with mult" {...@@ -110,7 +105,6 @@ test "array init with mult" {
110}105}
111106
112test "array literal with explicit type" {107test "array literal with explicit type" {
113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
115109
116 const hex_mult: [4]u16 = .{ 4096, 256, 16, 1 };110 const hex_mult: [4]u16 = .{ 4096, 256, 16, 1 };
...@@ -138,7 +132,6 @@ const ArrayDotLenConstExpr = struct {...@@ -138,7 +132,6 @@ const ArrayDotLenConstExpr = struct {
138const some_array = [_]u8{ 0, 1, 2, 3 };132const some_array = [_]u8{ 0, 1, 2, 3 };
139133
140test "array literal with specified size" {134test "array literal with specified size" {
141 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
142 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;135 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
143 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
144137
...@@ -162,7 +155,6 @@ test "array len field" {...@@ -162,7 +155,6 @@ test "array len field" {
162155
163test "array with sentinels" {156test "array with sentinels" {
164 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;157 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
165 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
166 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
167159
168 const S = struct {160 const S = struct {
...@@ -200,7 +192,6 @@ test "void arrays" {...@@ -200,7 +192,6 @@ test "void arrays" {
200192
201test "nested arrays of strings" {193test "nested arrays of strings" {
202 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;194 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
203 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;195 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO196 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206197
...@@ -215,7 +206,6 @@ test "nested arrays of strings" {...@@ -215,7 +206,6 @@ test "nested arrays of strings" {
215}206}
216207
217test "nested arrays of integers" {208test "nested arrays of integers" {
218 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
219 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
220210
221 const array_of_numbers = [_][2]u8{211 const array_of_numbers = [_][2]u8{
...@@ -230,7 +220,6 @@ test "nested arrays of integers" {...@@ -230,7 +220,6 @@ test "nested arrays of integers" {
230}220}
231221
232test "implicit comptime in array type size" {222test "implicit comptime in array type size" {
233 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
234 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO223 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
235224
236 var arr: [plusOne(10)]bool = undefined;225 var arr: [plusOne(10)]bool = undefined;
...@@ -243,7 +232,6 @@ fn plusOne(x: u32) u32 {...@@ -243,7 +232,6 @@ fn plusOne(x: u32) u32 {
243}232}
244233
245test "single-item pointer to array indexing and slicing" {234test "single-item pointer to array indexing and slicing" {
246 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO235 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
248 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;236 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
249237
...@@ -285,7 +273,6 @@ test "implicit cast zero sized array ptr to slice" {...@@ -285,7 +273,6 @@ test "implicit cast zero sized array ptr to slice" {
285}273}
286274
287test "anonymous list literal syntax" {275test "anonymous list literal syntax" {
288 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
289 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;276 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
290 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO277 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
291278
...@@ -308,7 +295,6 @@ const Sub = struct { b: u8 };...@@ -308,7 +295,6 @@ const Sub = struct { b: u8 };
308const Str = struct { a: []Sub };295const Str = struct { a: []Sub };
309test "set global var array via slice embedded in struct" {296test "set global var array via slice embedded in struct" {
310 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;297 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
311 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO298 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
313299
314 var s = Str{ .a = s_array[0..] };300 var s = Str{ .a = s_array[0..] };
...@@ -323,7 +309,6 @@ test "set global var array via slice embedded in struct" {...@@ -323,7 +309,6 @@ test "set global var array via slice embedded in struct" {
323}309}
324310
325test "read/write through global variable array of struct fields initialized via array mult" {311test "read/write through global variable array of struct fields initialized via array mult" {
326 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
327 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO312 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
328 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO313 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
329314
...@@ -345,7 +330,6 @@ test "read/write through global variable array of struct fields initialized via...@@ -345,7 +330,6 @@ test "read/write through global variable array of struct fields initialized via
345330
346test "implicit cast single-item pointer" {331test "implicit cast single-item pointer" {
347 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;332 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
348 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
349 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO333 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
350334
351 try testImplicitCastSingleItemPtr();335 try testImplicitCastSingleItemPtr();
...@@ -364,7 +348,6 @@ fn testArrayByValAtComptime(b: [2]u8) u8 {...@@ -364,7 +348,6 @@ fn testArrayByValAtComptime(b: [2]u8) u8 {
364}348}
365349
366test "comptime evaluating function that takes array by value" {350test "comptime evaluating function that takes array by value" {
367 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
368 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO351 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
369352
370 const arr = [_]u8{ 1, 2 };353 const arr = [_]u8{ 1, 2 };
...@@ -376,7 +359,6 @@ test "comptime evaluating function that takes array by value" {...@@ -376,7 +359,6 @@ test "comptime evaluating function that takes array by value" {
376359
377test "runtime initialize array elem and then implicit cast to slice" {360test "runtime initialize array elem and then implicit cast to slice" {
378 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;361 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
379 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO362 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
381363
382 var two: i32 = 2;364 var two: i32 = 2;
...@@ -387,7 +369,6 @@ test "runtime initialize array elem and then implicit cast to slice" {...@@ -387,7 +369,6 @@ test "runtime initialize array elem and then implicit cast to slice" {
387369
388test "array literal as argument to function" {370test "array literal as argument to function" {
389 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;371 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
390 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
391 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO372 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
392373
393 const S = struct {374 const S = struct {
...@@ -414,8 +395,8 @@ test "array literal as argument to function" {...@@ -414,8 +395,8 @@ test "array literal as argument to function" {
414}395}
415396
416test "double nested array to const slice cast in array literal" {397test "double nested array to const slice cast in array literal" {
417 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
418 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;398 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
399 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
419 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO400 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
420 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO401 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
421402
...@@ -476,7 +457,6 @@ test "double nested array to const slice cast in array literal" {...@@ -476,7 +457,6 @@ test "double nested array to const slice cast in array literal" {
476}457}
477458
478test "anonymous literal in array" {459test "anonymous literal in array" {
479 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
480 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO460 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
481 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO461 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
482462
...@@ -502,7 +482,6 @@ test "anonymous literal in array" {...@@ -502,7 +482,6 @@ test "anonymous literal in array" {
502}482}
503483
504test "access the null element of a null terminated array" {484test "access the null element of a null terminated array" {
505 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
506 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO485 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
507486
508 const S = struct {487 const S = struct {
...@@ -520,7 +499,6 @@ test "access the null element of a null terminated array" {...@@ -520,7 +499,6 @@ test "access the null element of a null terminated array" {
520}499}
521500
522test "type deduction for array subscript expression" {501test "type deduction for array subscript expression" {
523 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
524 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO502 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
525 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO503 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
526504
...@@ -540,7 +518,6 @@ test "type deduction for array subscript expression" {...@@ -540,7 +518,6 @@ test "type deduction for array subscript expression" {
540518
541test "sentinel element count towards the ABI size calculation" {519test "sentinel element count towards the ABI size calculation" {
542 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;520 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
543 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
544 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO521 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
545 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO522 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
546523
...@@ -564,7 +541,7 @@ test "sentinel element count towards the ABI size calculation" {...@@ -564,7 +541,7 @@ test "sentinel element count towards the ABI size calculation" {
564}541}
565542
566test "zero-sized array with recursive type definition" {543test "zero-sized array with recursive type definition" {
567 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO544 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
568 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO545 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
569 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;546 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
570547
...@@ -587,8 +564,8 @@ test "zero-sized array with recursive type definition" {...@@ -587,8 +564,8 @@ test "zero-sized array with recursive type definition" {
587}564}
588565
589test "type coercion of anon struct literal to array" {566test "type coercion of anon struct literal to array" {
567 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
590 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;568 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
591 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
592 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO569 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
593 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO570 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
594571
...@@ -628,7 +605,6 @@ test "array with comptime-only element type" {...@@ -628,7 +605,6 @@ test "array with comptime-only element type" {
628}605}
629606
630test "tuple to array handles sentinel" {607test "tuple to array handles sentinel" {
631 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
632 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO608 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
633 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO609 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
634610
...@@ -641,7 +617,6 @@ test "tuple to array handles sentinel" {...@@ -641,7 +617,6 @@ test "tuple to array handles sentinel" {
641617
642test "array init of container level array variable" {618test "array init of container level array variable" {
643 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;619 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
644 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
645 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO620 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
646 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO621 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
647622
...@@ -675,8 +650,8 @@ test "runtime initialized sentinel-terminated array literal" {...@@ -675,8 +650,8 @@ test "runtime initialized sentinel-terminated array literal" {
675}650}
676651
677test "array of array agregate init" {652test "array of array agregate init" {
653 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
678 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO654 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
679 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
680 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO655 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
681656
682 var a = [1]u32{11} ** 10;657 var a = [1]u32{11} ** 10;
...@@ -725,7 +700,6 @@ test "array init with no result location has result type" {...@@ -725,7 +700,6 @@ test "array init with no result location has result type" {
725}700}
726701
727test "slicing array of zero-sized values" {702test "slicing array of zero-sized values" {
728 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
729 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;703 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
730 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;704 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
731 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;705 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -890,7 +864,6 @@ test "tuple initialized through reference to anonymous array init provides resul...@@ -890,7 +864,6 @@ test "tuple initialized through reference to anonymous array init provides resul
890864
891test "copied array element doesn't alias source" {865test "copied array element doesn't alias source" {
892 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO866 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
893 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
894 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO867 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
895868
896 var x: [10][10]u32 = undefined;869 var x: [10][10]u32 = undefined;
...@@ -945,7 +918,6 @@ test "array initialized with array with sentinel" {...@@ -945,7 +918,6 @@ test "array initialized with array with sentinel" {
945}918}
946919
947test "store array of array of structs at comptime" {920test "store array of array of structs at comptime" {
948 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
949 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO921 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
950 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO922 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
951923
...@@ -970,7 +942,6 @@ test "store array of array of structs at comptime" {...@@ -970,7 +942,6 @@ test "store array of array of structs at comptime" {
970}942}
971943
972test "accessing multidimensional global array at comptime" {944test "accessing multidimensional global array at comptime" {
973 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
974 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO945 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
975 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;946 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
976947
...@@ -986,8 +957,8 @@ test "accessing multidimensional global array at comptime" {...@@ -986,8 +957,8 @@ test "accessing multidimensional global array at comptime" {
986}957}
987958
988test "union that needs padding bytes inside an array" {959test "union that needs padding bytes inside an array" {
989 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
990 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;960 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
961 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
991 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;962 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
992 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO963 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
993964
...@@ -1023,7 +994,6 @@ test "runtime index of array of zero-bit values" {...@@ -1023,7 +994,6 @@ test "runtime index of array of zero-bit values" {
1023}994}
1024995
1025test "@splat array" {996test "@splat array" {
1026 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1027 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;997 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1028 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO998 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1029999
...@@ -1046,7 +1016,6 @@ test "@splat array" {...@@ -1046,7 +1016,6 @@ test "@splat array" {
10461016
1047test "@splat array with sentinel" {1017test "@splat array with sentinel" {
1048 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1018 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1049 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1050 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1019 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1051 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1020 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10521021
...@@ -1070,7 +1039,6 @@ test "@splat array with sentinel" {...@@ -1070,7 +1039,6 @@ test "@splat array with sentinel" {
10701039
1071test "@splat zero-length array" {1040test "@splat zero-length array" {
1072 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1041 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1073 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1074 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1042 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1075 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1043 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10761044
test/behavior/asm.zig+2-7
...@@ -7,7 +7,6 @@ const is_x86_64_linux = builtin.cpu.arch == .x86_64 and builtin.os.tag == .linux...@@ -7,7 +7,6 @@ const is_x86_64_linux = builtin.cpu.arch == .x86_64 and builtin.os.tag == .linux
77
8comptime {8comptime {
9 if (builtin.zig_backend != .stage2_arm and9 if (builtin.zig_backend != .stage2_arm and
10 builtin.zig_backend != .stage2_aarch64 and
11 !(builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) and // MSVC doesn't support inline assembly10 !(builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) and // MSVC doesn't support inline assembly
12 is_x86_64_linux)11 is_x86_64_linux)
13 {12 {
...@@ -30,7 +29,6 @@ test "module level assembly" {...@@ -30,7 +29,6 @@ test "module level assembly" {
30 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3533
36 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly34 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
...@@ -41,9 +39,9 @@ test "module level assembly" {...@@ -41,9 +39,9 @@ test "module level assembly" {
41}39}
4240
43test "output constraint modifiers" {41test "output constraint modifiers" {
42 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
44 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO43 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO44 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
46 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
47 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO45 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
48 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;46 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
49 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;47 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -63,9 +61,9 @@ test "output constraint modifiers" {...@@ -63,9 +61,9 @@ test "output constraint modifiers" {
63}61}
6462
65test "alternative constraints" {63test "alternative constraints" {
64 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO65 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
68 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO67 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
70 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;68 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;69 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -83,7 +81,6 @@ test "alternative constraints" {...@@ -83,7 +81,6 @@ test "alternative constraints" {
83test "sized integer/float in asm input" {81test "sized integer/float in asm input" {
84 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO82 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
86 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;85 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
89 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;86 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -127,7 +124,6 @@ test "sized integer/float in asm input" {...@@ -127,7 +124,6 @@ test "sized integer/float in asm input" {
127test "struct/array/union types as input values" {124test "struct/array/union types as input values" {
128 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO125 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
129 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO126 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
130 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
131 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
132 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;128 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
133129
...@@ -167,7 +163,6 @@ test "rw constraint (x86_64)" {...@@ -167,7 +163,6 @@ test "rw constraint (x86_64)" {
167163
168test "asm modifiers (AArch64)" {164test "asm modifiers (AArch64)" {
169 if (!builtin.target.cpu.arch.isAARCH64()) return error.SkipZigTest;165 if (!builtin.target.cpu.arch.isAARCH64()) return error.SkipZigTest;
170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
171166
172 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly167 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
173168
test/behavior/atomics.zig+12-13
...@@ -12,7 +12,7 @@ const supports_128_bit_atomics = switch (builtin.cpu.arch) {...@@ -12,7 +12,7 @@ const supports_128_bit_atomics = switch (builtin.cpu.arch) {
12};12};
1313
14test "cmpxchg" {14test "cmpxchg" {
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
16 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -39,7 +39,7 @@ fn testCmpxchg() !void {...@@ -39,7 +39,7 @@ fn testCmpxchg() !void {
39}39}
4040
41test "atomicrmw and atomicload" {41test "atomicrmw and atomicload" {
42 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO42 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
43 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO43 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO44 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;45 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -68,7 +68,7 @@ fn testAtomicLoad(ptr: *u8) !void {...@@ -68,7 +68,7 @@ fn testAtomicLoad(ptr: *u8) !void {
68}68}
6969
70test "cmpxchg with ptr" {70test "cmpxchg with ptr" {
71 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO71 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
72 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO72 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
74 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;74 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -94,7 +94,7 @@ test "cmpxchg with ptr" {...@@ -94,7 +94,7 @@ test "cmpxchg with ptr" {
94}94}
9595
96test "cmpxchg with ignored result" {96test "cmpxchg with ignored result" {
97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
98 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO98 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO99 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;100 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -110,8 +110,8 @@ test "128-bit cmpxchg" {...@@ -110,8 +110,8 @@ test "128-bit cmpxchg" {
110 // TODO: this must appear first110 // TODO: this must appear first
111 if (!supports_128_bit_atomics) return error.SkipZigTest;111 if (!supports_128_bit_atomics) return error.SkipZigTest;
112112
113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
113 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO114 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
116 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO116 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
117117
...@@ -139,7 +139,7 @@ fn test_u128_cmpxchg() !void {...@@ -139,7 +139,7 @@ fn test_u128_cmpxchg() !void {
139var a_global_variable = @as(u32, 1234);139var a_global_variable = @as(u32, 1234);
140140
141test "cmpxchg on a global variable" {141test "cmpxchg on a global variable" {
142 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO142 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
143 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO143 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;145 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -149,7 +149,7 @@ test "cmpxchg on a global variable" {...@@ -149,7 +149,7 @@ test "cmpxchg on a global variable" {
149}149}
150150
151test "atomic load and rmw with enum" {151test "atomic load and rmw with enum" {
152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
153 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO153 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;155 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -167,7 +167,7 @@ test "atomic load and rmw with enum" {...@@ -167,7 +167,7 @@ test "atomic load and rmw with enum" {
167}167}
168168
169test "atomic store" {169test "atomic store" {
170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
171 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO171 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
172 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO172 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
173 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;173 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -185,7 +185,7 @@ fn testAtomicStore() !void {...@@ -185,7 +185,7 @@ fn testAtomicStore() !void {
185}185}
186186
187test "atomicrmw with floats" {187test "atomicrmw with floats" {
188 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO188 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
189 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO189 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
190 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO190 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
191 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;191 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -211,7 +211,7 @@ fn testAtomicRmwFloat() !void {...@@ -211,7 +211,7 @@ fn testAtomicRmwFloat() !void {
211}211}
212212
213test "atomicrmw with ints" {213test "atomicrmw with ints" {
214 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO214 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
216 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO216 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
217 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;217 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -290,7 +290,7 @@ test "atomicrmw with 128-bit ints" {...@@ -290,7 +290,7 @@ test "atomicrmw with 128-bit ints" {
290 // TODO: this must appear first290 // TODO: this must appear first
291 if (!supports_128_bit_atomics) return error.SkipZigTest;291 if (!supports_128_bit_atomics) return error.SkipZigTest;
292292
293 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO293 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
294294
295 try testAtomicRmwInt128(.signed);295 try testAtomicRmwInt128(.signed);
296 try testAtomicRmwInt128(.unsigned);296 try testAtomicRmwInt128(.unsigned);
...@@ -359,7 +359,7 @@ fn testAtomicRmwInt128(comptime signedness: std.builtin.Signedness) !void {...@@ -359,7 +359,7 @@ fn testAtomicRmwInt128(comptime signedness: std.builtin.Signedness) !void {
359}359}
360360
361test "atomics with different types" {361test "atomics with different types" {
362 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO362 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
365 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;365 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -409,7 +409,6 @@ fn testAtomicsWithPackedStruct(comptime T: type, a: T, b: T) !void {...@@ -409,7 +409,6 @@ fn testAtomicsWithPackedStruct(comptime T: type, a: T, b: T) !void {
409}409}
410410
411test "return @atomicStore, using it as a void value" {411test "return @atomicStore, using it as a void value" {
412 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
413 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO412 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
414 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO413 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
415 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;414 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/basic.zig+1-18
...@@ -39,7 +39,6 @@ test "truncate to non-power-of-two integers" {...@@ -39,7 +39,6 @@ test "truncate to non-power-of-two integers" {
39}39}
4040
41test "truncate to non-power-of-two integers from 128-bit" {41test "truncate to non-power-of-two integers from 128-bit" {
42 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
43 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO43 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;44 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -422,7 +421,6 @@ fn copy(src: *const u64, dst: *u64) void {...@@ -422,7 +421,6 @@ fn copy(src: *const u64, dst: *u64) void {
422}421}
423422
424test "call result of if else expression" {423test "call result of if else expression" {
425 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
426 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;424 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
427 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO425 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
428 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;426 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -448,7 +446,6 @@ fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {...@@ -448,7 +446,6 @@ fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
448}446}
449447
450test "take address of parameter" {448test "take address of parameter" {
451 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
452 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
453 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
454451
...@@ -536,7 +533,6 @@ fn nine() u8 {...@@ -536,7 +533,6 @@ fn nine() u8 {
536}533}
537534
538test "struct inside function" {535test "struct inside function" {
539 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
540 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO536 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
541537
542 try testStructInFn();538 try testStructInFn();
...@@ -588,7 +584,6 @@ test "global variable assignment with optional unwrapping with var initialized t...@@ -588,7 +584,6 @@ test "global variable assignment with optional unwrapping with var initialized t
588var global_foo: *i32 = undefined;584var global_foo: *i32 = undefined;
589585
590test "peer result location with typed parent, runtime condition, comptime prongs" {586test "peer result location with typed parent, runtime condition, comptime prongs" {
591 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
592 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO587 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
593588
594 const S = struct {589 const S = struct {
...@@ -719,7 +714,6 @@ test "global constant is loaded with a runtime-known index" {...@@ -719,7 +714,6 @@ test "global constant is loaded with a runtime-known index" {
719}714}
720715
721test "multiline string literal is null terminated" {716test "multiline string literal is null terminated" {
722 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
723 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;717 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
724718
725 const s1 =719 const s1 =
...@@ -732,7 +726,6 @@ test "multiline string literal is null terminated" {...@@ -732,7 +726,6 @@ test "multiline string literal is null terminated" {
732}726}
733727
734test "string escapes" {728test "string escapes" {
735 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
736 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;729 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
737 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO730 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
738 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;731 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -764,7 +757,6 @@ fn ptrEql(a: *const []const u8, b: *const []const u8) bool {...@@ -764,7 +757,6 @@ fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
764}757}
765758
766test "string concatenation" {759test "string concatenation" {
767 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
768 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;760 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
769 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO761 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
770762
...@@ -787,7 +779,6 @@ test "string concatenation" {...@@ -787,7 +779,6 @@ test "string concatenation" {
787}779}
788780
789test "result location is optional inside error union" {781test "result location is optional inside error union" {
790 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
791 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO782 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
792 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO783 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
793784
...@@ -803,7 +794,6 @@ fn maybe(x: bool) anyerror!?u32 {...@@ -803,7 +794,6 @@ fn maybe(x: bool) anyerror!?u32 {
803}794}
804795
805test "auto created variables have correct alignment" {796test "auto created variables have correct alignment" {
806 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
807 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO797 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
808 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;798 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
809799
...@@ -821,7 +811,6 @@ test "auto created variables have correct alignment" {...@@ -821,7 +811,6 @@ test "auto created variables have correct alignment" {
821811
822test "extern variable with non-pointer opaque type" {812test "extern variable with non-pointer opaque type" {
823 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO813 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
824 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
825 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO814 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
826 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO815 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
827 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO816 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
...@@ -866,7 +855,6 @@ test "if expression type coercion" {...@@ -866,7 +855,6 @@ test "if expression type coercion" {
866}855}
867856
868test "discarding the result of various expressions" {857test "discarding the result of various expressions" {
869 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
870 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO858 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
871 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO859 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
872860
...@@ -908,7 +896,6 @@ test "labeled block implicitly ends in a break" {...@@ -908,7 +896,6 @@ test "labeled block implicitly ends in a break" {
908}896}
909897
910test "catch in block has correct result location" {898test "catch in block has correct result location" {
911 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
912 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO899 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
913900
914 const S = struct {901 const S = struct {
...@@ -964,7 +951,6 @@ test "vector initialized with array init syntax has proper type" {...@@ -964,7 +951,6 @@ test "vector initialized with array init syntax has proper type" {
964}951}
965952
966test "weird array and tuple initializations" {953test "weird array and tuple initializations" {
967 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
968 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO954 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
969 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO955 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
970956
...@@ -1010,7 +996,6 @@ test "generic function uses return type of other generic function" {...@@ -1010,7 +996,6 @@ test "generic function uses return type of other generic function" {
1010 // https://github.com/ziglang/zig/issues/12208996 // https://github.com/ziglang/zig/issues/12208
1011 return error.SkipZigTest;997 return error.SkipZigTest;
1012 }998 }
1013 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1014999
1015 const S = struct {1000 const S = struct {
1016 fn call(1001 fn call(
...@@ -1128,7 +1113,6 @@ test "returning an opaque type from a function" {...@@ -1128,7 +1113,6 @@ test "returning an opaque type from a function" {
1128}1113}
11291114
1130test "orelse coercion as function argument" {1115test "orelse coercion as function argument" {
1131 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1132 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1116 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11331117
1134 const Loc = struct { start: i32 = -1 };1118 const Loc = struct { start: i32 = -1 };
...@@ -1378,7 +1362,6 @@ test "copy array of self-referential struct" {...@@ -1378,7 +1362,6 @@ test "copy array of self-referential struct" {
13781362
1379test "break out of block based on comptime known values" {1363test "break out of block based on comptime known values" {
1380 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1382 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1365 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13831366
1384 const S = struct {1367 const S = struct {
...@@ -1412,8 +1395,8 @@ test "break out of block based on comptime known values" {...@@ -1412,8 +1395,8 @@ test "break out of block based on comptime known values" {
1412}1395}
14131396
1414test "allocation and looping over 3-byte integer" {1397test "allocation and looping over 3-byte integer" {
1398 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1415 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1399 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1416 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1417 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1400 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1418 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1401 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1419 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1402 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/bit_shifting.zig+2-1
...@@ -112,7 +112,7 @@ test "comptime shift safety check" {...@@ -112,7 +112,7 @@ test "comptime shift safety check" {
112}112}
113113
114test "Saturating Shift Left where lhs is of a computed type" {114test "Saturating Shift Left where lhs is of a computed type" {
115 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO115 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
116 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO116 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
117 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO117 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
118 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;118 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -161,6 +161,7 @@ comptime {...@@ -161,6 +161,7 @@ comptime {
161}161}
162162
163test "Saturating Shift Left" {163test "Saturating Shift Left" {
164 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;165 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;166 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
166 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;167 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/bitcast.zig+9-12
...@@ -20,7 +20,6 @@ test "@bitCast iX -> uX (32, 64)" {...@@ -20,7 +20,6 @@ test "@bitCast iX -> uX (32, 64)" {
20}20}
2121
22test "@bitCast iX -> uX (8, 16, 128)" {22test "@bitCast iX -> uX (8, 16, 128)" {
23 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;25 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -35,8 +34,8 @@ test "@bitCast iX -> uX (8, 16, 128)" {...@@ -35,8 +34,8 @@ test "@bitCast iX -> uX (8, 16, 128)" {
35}34}
3635
37test "@bitCast iX -> uX exotic integers" {36test "@bitCast iX -> uX exotic integers" {
38 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
40 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;39 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
41 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO40 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
42 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;41 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -80,8 +79,8 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe...@@ -80,8 +79,8 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe
80}79}
8180
82test "bitcast uX to bytes" {81test "bitcast uX to bytes" {
83 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;82 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
85 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
86 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO85 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
87 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;86 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -296,9 +295,9 @@ test "triple level result location with bitcast sandwich passed as tuple element...@@ -296,9 +295,9 @@ test "triple level result location with bitcast sandwich passed as tuple element
296}295}
297296
298test "@bitCast packed struct of floats" {297test "@bitCast packed struct of floats" {
298 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
299 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;299 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
300 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;300 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
301 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;301 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO302 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
304 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;303 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -334,9 +333,9 @@ test "@bitCast packed struct of floats" {...@@ -334,9 +333,9 @@ test "@bitCast packed struct of floats" {
334}333}
335334
336test "comptime @bitCast packed struct to int and back" {335test "comptime @bitCast packed struct to int and back" {
336 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
337 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;337 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
338 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;338 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
339 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
340 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
341 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO340 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
342 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;341 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -379,7 +378,6 @@ test "comptime bitcast with fields following f80" {...@@ -379,7 +378,6 @@ test "comptime bitcast with fields following f80" {
379 }378 }
380379
381 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;380 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
383 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;381 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
384 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO382 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
385383
...@@ -393,7 +391,7 @@ test "comptime bitcast with fields following f80" {...@@ -393,7 +391,7 @@ test "comptime bitcast with fields following f80" {
393}391}
394392
395test "bitcast vector to integer and back" {393test "bitcast vector to integer and back" {
396 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO394 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO395 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
398 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
399 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO397 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
...@@ -420,7 +418,6 @@ fn bitCastWrapper128(x: f128) u128 {...@@ -420,7 +418,6 @@ fn bitCastWrapper128(x: f128) u128 {
420 return @as(u128, @bitCast(x));418 return @as(u128, @bitCast(x));
421}419}
422test "bitcast nan float does not modify signaling bit" {420test "bitcast nan float does not modify signaling bit" {
423 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
424 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO421 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
425 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO422 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
426 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;423 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -473,7 +470,7 @@ test "bitcast nan float does not modify signaling bit" {...@@ -473,7 +470,7 @@ test "bitcast nan float does not modify signaling bit" {
473}470}
474471
475test "@bitCast of packed struct of bools all true" {472test "@bitCast of packed struct of bools all true" {
476 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO473 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
477 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO474 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
478 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO475 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
479 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO476 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -494,7 +491,7 @@ test "@bitCast of packed struct of bools all true" {...@@ -494,7 +491,7 @@ test "@bitCast of packed struct of bools all true" {
494}491}
495492
496test "@bitCast of packed struct of bools all false" {493test "@bitCast of packed struct of bools all false" {
497 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO494 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
498 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO495 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
499 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO496 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
500 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO497 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -514,7 +511,7 @@ test "@bitCast of packed struct of bools all false" {...@@ -514,7 +511,7 @@ test "@bitCast of packed struct of bools all false" {
514}511}
515512
516test "@bitCast of packed struct containing pointer" {513test "@bitCast of packed struct containing pointer" {
517 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
518 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
519 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO516 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
520 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO517 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
...@@ -544,7 +541,7 @@ test "@bitCast of packed struct containing pointer" {...@@ -544,7 +541,7 @@ test "@bitCast of packed struct containing pointer" {
544}541}
545542
546test "@bitCast of extern struct containing pointer" {543test "@bitCast of extern struct containing pointer" {
547 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO544 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
548 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO545 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
549 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO546 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
550 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO547 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/bitreverse.zig+4-4
...@@ -8,8 +8,8 @@ test "@bitReverse large exotic integer" {...@@ -8,8 +8,8 @@ test "@bitReverse large exotic integer" {
8}8}
99
10test "@bitReverse" {10test "@bitReverse" {
11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO13 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;14 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;15 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -121,9 +121,9 @@ fn vector8() !void {...@@ -121,9 +121,9 @@ fn vector8() !void {
121}121}
122122
123test "bitReverse vectors u8" {123test "bitReverse vectors u8" {
124 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
124 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;125 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
125 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;126 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
126 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
128 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;128 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
129 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;129 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -141,9 +141,9 @@ fn vector16() !void {...@@ -141,9 +141,9 @@ fn vector16() !void {
141}141}
142142
143test "bitReverse vectors u16" {143test "bitReverse vectors u16" {
144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
144 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;145 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;146 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
146 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
147 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO147 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
148 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;148 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
149 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;149 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -161,9 +161,9 @@ fn vector24() !void {...@@ -161,9 +161,9 @@ fn vector24() !void {
161}161}
162162
163test "bitReverse vectors u24" {163test "bitReverse vectors u24" {
164 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;165 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
165 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;166 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
166 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
167 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO167 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
168 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;168 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
169 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;169 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/builtin_functions_returning_void_or_noreturn.zig-1
...@@ -7,7 +7,6 @@ var x: u8 = 1;...@@ -7,7 +7,6 @@ var x: u8 = 1;
7// This excludes builtin functions that return void or noreturn that cannot be tested.7// This excludes builtin functions that return void or noreturn that cannot be tested.
8test {8test {
9 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/byteswap.zig+32-43
...@@ -3,40 +3,8 @@ const builtin = @import("builtin");...@@ -3,40 +3,8 @@ const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "@byteSwap integers" {5test "@byteSwap integers" {
6 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7
8 if (builtin.zig_backend == .stage2_wasm) {
9 // TODO: Remove when self-hosted wasm supports more types for byteswap
10 const ByteSwapIntTest = struct {
11 fn run() !void {
12 try t(u8, 0x12, 0x12);
13 try t(u16, 0x1234, 0x3412);
14 try t(u24, 0x123456, 0x563412);
15 try t(i24, @as(i24, @bitCast(@as(u24, 0xf23456))), 0x5634f2);
16 try t(i24, 0x1234f6, @as(i24, @bitCast(@as(u24, 0xf63412))));
17 try t(u32, 0x12345678, 0x78563412);
18 try t(i32, @as(i32, @bitCast(@as(u32, 0xf2345678))), 0x785634f2);
19 try t(i32, 0x123456f8, @as(i32, @bitCast(@as(u32, 0xf8563412))));
20 try t(u64, 0x123456789abcdef1, 0xf1debc9a78563412);
21
22 try t(u0, @as(u0, 0), 0);
23 try t(i8, @as(i8, -50), -50);
24 try t(i16, @as(i16, @bitCast(@as(u16, 0x1234))), @as(i16, @bitCast(@as(u16, 0x3412))));
25 try t(i24, @as(i24, @bitCast(@as(u24, 0x123456))), @as(i24, @bitCast(@as(u24, 0x563412))));
26 try t(i32, @as(i32, @bitCast(@as(u32, 0x12345678))), @as(i32, @bitCast(@as(u32, 0x78563412))));
27 try t(i64, @as(i64, @bitCast(@as(u64, 0x123456789abcdef1))), @as(i64, @bitCast(@as(u64, 0xf1debc9a78563412))));
28 }
29 fn t(comptime I: type, input: I, expected_output: I) !void {
30 try std.testing.expect(expected_output == @byteSwap(input));
31 }
32 };
33 try comptime ByteSwapIntTest.run();
34 try ByteSwapIntTest.run();
35 return;
36 }
37
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
40 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
41 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
4210
...@@ -51,23 +19,44 @@ test "@byteSwap integers" {...@@ -51,23 +19,44 @@ test "@byteSwap integers" {
51 try t(u32, 0x12345678, 0x78563412);19 try t(u32, 0x12345678, 0x78563412);
52 try t(i32, @as(i32, @bitCast(@as(u32, 0xf2345678))), 0x785634f2);20 try t(i32, @as(i32, @bitCast(@as(u32, 0xf2345678))), 0x785634f2);
53 try t(i32, 0x123456f8, @as(i32, @bitCast(@as(u32, 0xf8563412))));21 try t(i32, 0x123456f8, @as(i32, @bitCast(@as(u32, 0xf8563412))));
54 try t(u40, 0x123456789a, 0x9a78563412);
55 try t(i48, 0x123456789abc, @as(i48, @bitCast(@as(u48, 0xbc9a78563412))));
56 try t(u56, 0x123456789abcde, 0xdebc9a78563412);
57 try t(u64, 0x123456789abcdef1, 0xf1debc9a78563412);22 try t(u64, 0x123456789abcdef1, 0xf1debc9a78563412);
58 try t(u88, 0x123456789abcdef1112131, 0x312111f1debc9a78563412);
59 try t(u96, 0x123456789abcdef111213141, 0x41312111f1debc9a78563412);
60 try t(u128, 0x123456789abcdef11121314151617181, 0x8171615141312111f1debc9a78563412);
6123
62 try t(u0, @as(u0, 0), 0);24 try t(u0, @as(u0, 0), 0);
63 try t(i8, @as(i8, -50), -50);25 try t(i8, @as(i8, -50), -50);
64 try t(i16, @as(i16, @bitCast(@as(u16, 0x1234))), @as(i16, @bitCast(@as(u16, 0x3412))));26 try t(i16, @as(i16, @bitCast(@as(u16, 0x1234))), @as(i16, @bitCast(@as(u16, 0x3412))));
65 try t(i24, @as(i24, @bitCast(@as(u24, 0x123456))), @as(i24, @bitCast(@as(u24, 0x563412))));27 try t(i24, @as(i24, @bitCast(@as(u24, 0x123456))), @as(i24, @bitCast(@as(u24, 0x563412))));
66 try t(i32, @as(i32, @bitCast(@as(u32, 0x12345678))), @as(i32, @bitCast(@as(u32, 0x78563412))));28 try t(i32, @as(i32, @bitCast(@as(u32, 0x12345678))), @as(i32, @bitCast(@as(u32, 0x78563412))));
29 try t(i64, @as(i64, @bitCast(@as(u64, 0x123456789abcdef1))), @as(i64, @bitCast(@as(u64, 0xf1debc9a78563412))));
30 }
31 fn t(comptime I: type, input: I, expected_output: I) !void {
32 try std.testing.expect(expected_output == @byteSwap(input));
33 }
34 };
35 try comptime ByteSwapIntTest.run();
36 try ByteSwapIntTest.run();
37}
38
39test "@byteSwap exotic integers" {
40 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
41 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
42 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
43 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
44 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
45 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
46
47 const ByteSwapIntTest = struct {
48 fn run() !void {
49 try t(u0, 0, 0);
50 try t(u40, 0x123456789a, 0x9a78563412);
51 try t(i48, 0x123456789abc, @as(i48, @bitCast(@as(u48, 0xbc9a78563412))));
52 try t(u56, 0x123456789abcde, 0xdebc9a78563412);
53 try t(u88, 0x123456789abcdef1112131, 0x312111f1debc9a78563412);
54 try t(u96, 0x123456789abcdef111213141, 0x41312111f1debc9a78563412);
55 try t(u128, 0x123456789abcdef11121314151617181, 0x8171615141312111f1debc9a78563412);
56
67 try t(u40, @as(i40, @bitCast(@as(u40, 0x123456789a))), @as(u40, 0x9a78563412));57 try t(u40, @as(i40, @bitCast(@as(u40, 0x123456789a))), @as(u40, 0x9a78563412));
68 try t(i48, @as(i48, @bitCast(@as(u48, 0x123456789abc))), @as(i48, @bitCast(@as(u48, 0xbc9a78563412))));58 try t(i48, @as(i48, @bitCast(@as(u48, 0x123456789abc))), @as(i48, @bitCast(@as(u48, 0xbc9a78563412))));
69 try t(i56, @as(i56, @bitCast(@as(u56, 0x123456789abcde))), @as(i56, @bitCast(@as(u56, 0xdebc9a78563412))));59 try t(i56, @as(i56, @bitCast(@as(u56, 0x123456789abcde))), @as(i56, @bitCast(@as(u56, 0xdebc9a78563412))));
70 try t(i64, @as(i64, @bitCast(@as(u64, 0x123456789abcdef1))), @as(i64, @bitCast(@as(u64, 0xf1debc9a78563412))));
71 try t(i88, @as(i88, @bitCast(@as(u88, 0x123456789abcdef1112131))), @as(i88, @bitCast(@as(u88, 0x312111f1debc9a78563412))));60 try t(i88, @as(i88, @bitCast(@as(u88, 0x123456789abcdef1112131))), @as(i88, @bitCast(@as(u88, 0x312111f1debc9a78563412))));
72 try t(i96, @as(i96, @bitCast(@as(u96, 0x123456789abcdef111213141))), @as(i96, @bitCast(@as(u96, 0x41312111f1debc9a78563412))));61 try t(i96, @as(i96, @bitCast(@as(u96, 0x123456789abcdef111213141))), @as(i96, @bitCast(@as(u96, 0x41312111f1debc9a78563412))));
73 try t(62 try t(
...@@ -93,9 +82,9 @@ fn vector8() !void {...@@ -93,9 +82,9 @@ fn vector8() !void {
93}82}
9483
95test "@byteSwap vectors u8" {84test "@byteSwap vectors u8" {
85 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
96 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;86 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
97 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;87 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
98 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO88 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;89 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
101 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;90 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -113,9 +102,9 @@ fn vector16() !void {...@@ -113,9 +102,9 @@ fn vector16() !void {
113}102}
114103
115test "@byteSwap vectors u16" {104test "@byteSwap vectors u16" {
105 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
116 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;106 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
120 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;109 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
121 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;110 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -133,9 +122,9 @@ fn vector24() !void {...@@ -133,9 +122,9 @@ fn vector24() !void {
133}122}
134123
135test "@byteSwap vectors u24" {124test "@byteSwap vectors u24" {
125 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
136 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;126 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;127 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO128 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;129 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
141 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;130 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/call.zig+6-13
...@@ -20,8 +20,8 @@ test "super basic invocations" {...@@ -20,8 +20,8 @@ test "super basic invocations" {
20}20}
2121
22test "basic invocations" {22test "basic invocations" {
23 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
27 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;27 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -60,7 +60,6 @@ test "basic invocations" {...@@ -60,7 +60,6 @@ test "basic invocations" {
60}60}
6161
62test "tuple parameters" {62test "tuple parameters" {
63 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
64 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO63 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
65 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO64 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;65 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -95,7 +94,6 @@ test "tuple parameters" {...@@ -95,7 +94,6 @@ test "tuple parameters" {
9594
96test "result location of function call argument through runtime condition and struct init" {95test "result location of function call argument through runtime condition and struct init" {
97 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO96 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO97 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10098
101 const E = enum { a, b };99 const E = enum { a, b };
...@@ -115,6 +113,7 @@ test "result location of function call argument through runtime condition and st...@@ -115,6 +113,7 @@ test "result location of function call argument through runtime condition and st
115}113}
116114
117test "function call with 40 arguments" {115test "function call with 40 arguments" {
116 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO117 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
119 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;118 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
120119
...@@ -270,7 +269,7 @@ test "arguments to comptime parameters generated in comptime blocks" {...@@ -270,7 +269,7 @@ test "arguments to comptime parameters generated in comptime blocks" {
270}269}
271270
272test "forced tail call" {271test "forced tail call" {
273 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO272 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
274 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO273 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
275 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO274 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
276 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO275 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -305,7 +304,7 @@ test "forced tail call" {...@@ -305,7 +304,7 @@ test "forced tail call" {
305}304}
306305
307test "inline call preserves tail call" {306test "inline call preserves tail call" {
308 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO307 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
309 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO308 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
310 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO309 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
311 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO310 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -342,7 +341,6 @@ test "inline call preserves tail call" {...@@ -342,7 +341,6 @@ test "inline call preserves tail call" {
342}341}
343342
344test "inline call doesn't re-evaluate non generic struct" {343test "inline call doesn't re-evaluate non generic struct" {
345 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO344 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
347 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;345 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
348346
...@@ -409,7 +407,6 @@ test "recursive inline call with comptime known argument" {...@@ -409,7 +407,6 @@ test "recursive inline call with comptime known argument" {
409}407}
410408
411test "inline while with @call" {409test "inline while with @call" {
412 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
413 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO410 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
414411
415 const S = struct {412 const S = struct {
...@@ -439,7 +436,6 @@ test "method call as parameter type" {...@@ -439,7 +436,6 @@ test "method call as parameter type" {
439}436}
440437
441test "non-anytype generic parameters provide result type" {438test "non-anytype generic parameters provide result type" {
442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
443 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO439 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
444 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO440 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
445441
...@@ -468,7 +464,6 @@ test "non-anytype generic parameters provide result type" {...@@ -468,7 +464,6 @@ test "non-anytype generic parameters provide result type" {
468}464}
469465
470test "argument to generic function has correct result type" {466test "argument to generic function has correct result type" {
471 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO467 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO468 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
474469
...@@ -521,7 +516,6 @@ test "call function in comptime field" {...@@ -521,7 +516,6 @@ test "call function in comptime field" {
521516
522test "call function pointer in comptime field" {517test "call function pointer in comptime field" {
523 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO518 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
524 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
525 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO519 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
526 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;520 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
527521
...@@ -573,7 +567,6 @@ test "value returned from comptime function is comptime known" {...@@ -573,7 +567,6 @@ test "value returned from comptime function is comptime known" {
573}567}
574568
575test "registers get overwritten when ignoring return" {569test "registers get overwritten when ignoring return" {
576 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
577 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;570 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
578 if (builtin.cpu.arch != .x86_64 or builtin.os.tag != .linux) return error.SkipZigTest;571 if (builtin.cpu.arch != .x86_64 or builtin.os.tag != .linux) return error.SkipZigTest;
579572
...@@ -619,7 +612,6 @@ test "call with union with zero sized field is not memorized incorrectly" {...@@ -619,7 +612,6 @@ test "call with union with zero sized field is not memorized incorrectly" {
619}612}
620613
621test "function call with cast to anyopaque pointer" {614test "function call with cast to anyopaque pointer" {
622 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
623 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO615 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
624 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO616 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
625 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;617 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -637,6 +629,7 @@ test "function call with cast to anyopaque pointer" {...@@ -637,6 +629,7 @@ test "function call with cast to anyopaque pointer" {
637}629}
638630
639test "arguments pointed to on stack into tailcall" {631test "arguments pointed to on stack into tailcall" {
632 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
640 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;633 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
641 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;634 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
642 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;635 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -708,7 +701,7 @@ test "arguments pointed to on stack into tailcall" {...@@ -708,7 +701,7 @@ test "arguments pointed to on stack into tailcall" {
708}701}
709702
710test "tail call function pointer" {703test "tail call function pointer" {
711 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO704 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
712 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO705 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
713 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO706 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
714 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO707 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/behavior/cast.zig+19-100
...@@ -21,7 +21,6 @@ test "integer literal to pointer cast" {...@@ -21,7 +21,6 @@ test "integer literal to pointer cast" {
21}21}
2222
23test "peer type resolution: ?T and T" {23test "peer type resolution: ?T and T" {
24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO25 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2726
...@@ -100,7 +99,6 @@ test "comptime_int @floatFromInt" {...@@ -100,7 +99,6 @@ test "comptime_int @floatFromInt" {
100}99}
101100
102test "@floatFromInt" {101test "@floatFromInt" {
103 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
105 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;103 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO104 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -121,7 +119,6 @@ test "@floatFromInt" {...@@ -121,7 +119,6 @@ test "@floatFromInt" {
121}119}
122120
123test "@floatFromInt(f80)" {121test "@floatFromInt(f80)" {
124 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO122 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO123 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
127 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;124 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -157,7 +154,6 @@ test "@floatFromInt(f80)" {...@@ -157,7 +154,6 @@ test "@floatFromInt(f80)" {
157}154}
158155
159test "@intFromFloat" {156test "@intFromFloat" {
160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;159 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -181,7 +177,6 @@ fn expectIntFromFloat(comptime F: type, f: F, comptime I: type, i: I) !void {...@@ -181,7 +177,6 @@ fn expectIntFromFloat(comptime F: type, f: F, comptime I: type, i: I) !void {
181}177}
182178
183test "implicitly cast indirect pointer to maybe-indirect pointer" {179test "implicitly cast indirect pointer to maybe-indirect pointer" {
184 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO180 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
186 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;181 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
187182
...@@ -241,7 +236,6 @@ test "@floatCast comptime_int and comptime_float" {...@@ -241,7 +236,6 @@ test "@floatCast comptime_int and comptime_float" {
241}236}
242237
243test "coerce undefined to optional" {238test "coerce undefined to optional" {
244 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
245 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;239 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
246 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO240 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
247241
...@@ -262,7 +256,6 @@ fn MakeType(comptime T: type) type {...@@ -262,7 +256,6 @@ fn MakeType(comptime T: type) type {
262}256}
263257
264test "implicit cast from *[N]T to [*c]T" {258test "implicit cast from *[N]T to [*c]T" {
265 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
266 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
267 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;260 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
268261
...@@ -299,7 +292,6 @@ test "@intCast to u0 and use the result" {...@@ -299,7 +292,6 @@ test "@intCast to u0 and use the result" {
299}292}
300293
301test "peer result null and comptime_int" {294test "peer result null and comptime_int" {
302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;295 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO296 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
305297
...@@ -324,7 +316,6 @@ test "peer result null and comptime_int" {...@@ -324,7 +316,6 @@ test "peer result null and comptime_int" {
324}316}
325317
326test "*const ?[*]const T to [*c]const [*c]const T" {318test "*const ?[*]const T to [*c]const [*c]const T" {
327 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
328 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO319 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
329 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;320 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
330 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;321 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -338,7 +329,6 @@ test "*const ?[*]const T to [*c]const [*c]const T" {...@@ -338,7 +329,6 @@ test "*const ?[*]const T to [*c]const [*c]const T" {
338}329}
339330
340test "array coercion to undefined at runtime" {331test "array coercion to undefined at runtime" {
341 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO332 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
343 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;333 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
344334
...@@ -368,7 +358,6 @@ fn implicitIntLitToOptional() void {...@@ -368,7 +358,6 @@ fn implicitIntLitToOptional() void {
368}358}
369359
370test "return u8 coercing into ?u32 return type" {360test "return u8 coercing into ?u32 return type" {
371 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
372 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;361 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
373 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO362 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
374363
...@@ -390,7 +379,6 @@ test "cast from ?[*]T to ??[*]T" {...@@ -390,7 +379,6 @@ test "cast from ?[*]T to ??[*]T" {
390}379}
391380
392test "peer type unsigned int to signed" {381test "peer type unsigned int to signed" {
393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
394 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO382 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
395383
396 var w: u31 = 5;384 var w: u31 = 5;
...@@ -403,7 +391,6 @@ test "peer type unsigned int to signed" {...@@ -403,7 +391,6 @@ test "peer type unsigned int to signed" {
403}391}
404392
405test "expected [*c]const u8, found [*:0]const u8" {393test "expected [*c]const u8, found [*:0]const u8" {
406 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
407 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO394 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
408 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;395 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
409396
...@@ -415,7 +402,6 @@ test "expected [*c]const u8, found [*:0]const u8" {...@@ -415,7 +402,6 @@ test "expected [*c]const u8, found [*:0]const u8" {
415}402}
416403
417test "explicit cast from integer to error type" {404test "explicit cast from integer to error type" {
418 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
419 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO405 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
420 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO406 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
421 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;407 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -431,7 +417,6 @@ fn testCastIntToErr(err: anyerror) !void {...@@ -431,7 +417,6 @@ fn testCastIntToErr(err: anyerror) !void {
431}417}
432418
433test "peer resolve array and const slice" {419test "peer resolve array and const slice" {
434 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
435 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
436 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO421 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
437 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;422 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -447,7 +432,6 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {...@@ -447,7 +432,6 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {
447}432}
448433
449test "implicitly cast from T to anyerror!?T" {434test "implicitly cast from T to anyerror!?T" {
450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;435 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO436 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
453437
...@@ -473,7 +457,6 @@ fn castToOptionalTypeError(z: i32) !void {...@@ -473,7 +457,6 @@ fn castToOptionalTypeError(z: i32) !void {
473}457}
474458
475test "implicitly cast from [0]T to anyerror![]T" {459test "implicitly cast from [0]T to anyerror![]T" {
476 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
477 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO460 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
478461
479 try testCastZeroArrayToErrSliceMut();462 try testCastZeroArrayToErrSliceMut();
...@@ -489,7 +472,6 @@ fn gimmeErrOrSlice() anyerror![]u8 {...@@ -489,7 +472,6 @@ fn gimmeErrOrSlice() anyerror![]u8 {
489}472}
490473
491test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {474test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
492 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO475 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
494 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO476 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
495 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;477 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -522,7 +504,6 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {...@@ -522,7 +504,6 @@ fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
522}504}
523505
524test "implicit cast from *const [N]T to []const T" {506test "implicit cast from *const [N]T to []const T" {
525 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
526 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
527 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;508 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
528509
...@@ -548,7 +529,6 @@ fn testCastConstArrayRefToConstSlice() !void {...@@ -548,7 +529,6 @@ fn testCastConstArrayRefToConstSlice() !void {
548}529}
549530
550test "peer type resolution: error and [N]T" {531test "peer type resolution: error and [N]T" {
551 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
552 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO532 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
553 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;533 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
554534
...@@ -573,7 +553,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {...@@ -573,7 +553,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
573}553}
574554
575test "single-item pointer of array to slice to unknown length pointer" {555test "single-item pointer of array to slice to unknown length pointer" {
576 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
577 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO556 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
578 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;557 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
579558
...@@ -603,7 +582,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void {...@@ -603,7 +582,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void {
603}582}
604583
605test "cast *[1][*]const u8 to [*]const ?[*]const u8" {584test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
606 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
607 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO585 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
608 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;586 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
609587
...@@ -613,8 +591,8 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" {...@@ -613,8 +591,8 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
613}591}
614592
615test "@intCast on vector" {593test "@intCast on vector" {
594 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
616 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO595 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
617 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
618 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO596 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
619 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO597 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
620 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;598 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -651,7 +629,6 @@ test "@intCast on vector" {...@@ -651,7 +629,6 @@ test "@intCast on vector" {
651}629}
652630
653test "@floatCast cast down" {631test "@floatCast cast down" {
654 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
655 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO632 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
656 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO633 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
657 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;634 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -670,7 +647,6 @@ test "@floatCast cast down" {...@@ -670,7 +647,6 @@ test "@floatCast cast down" {
670}647}
671648
672test "peer type resolution: unreachable, error set, unreachable" {649test "peer type resolution: unreachable, error set, unreachable" {
673 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
674 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO650 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
675651
676 const Error = error{652 const Error = error{
...@@ -704,7 +680,6 @@ test "peer cast: error set any anyerror" {...@@ -704,7 +680,6 @@ test "peer cast: error set any anyerror" {
704}680}
705681
706test "peer type resolution: error set supersets" {682test "peer type resolution: error set supersets" {
707 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
708 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO683 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
709 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO684 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
710 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;685 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -735,7 +710,6 @@ test "peer type resolution: error set supersets" {...@@ -735,7 +710,6 @@ test "peer type resolution: error set supersets" {
735710
736test "peer type resolution: disjoint error sets" {711test "peer type resolution: disjoint error sets" {
737 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO712 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
738 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
739 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO713 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
740 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;714 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
741715
...@@ -765,7 +739,6 @@ test "peer type resolution: disjoint error sets" {...@@ -765,7 +739,6 @@ test "peer type resolution: disjoint error sets" {
765739
766test "peer type resolution: error union and error set" {740test "peer type resolution: error union and error set" {
767 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO741 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
768 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
769 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO742 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
770 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;743 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
771744
...@@ -799,7 +772,6 @@ test "peer type resolution: error union and error set" {...@@ -799,7 +772,6 @@ test "peer type resolution: error union and error set" {
799772
800test "peer type resolution: error union after non-error" {773test "peer type resolution: error union after non-error" {
801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO774 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO775 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
804 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;776 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
805777
...@@ -833,7 +805,6 @@ test "peer type resolution: error union after non-error" {...@@ -833,7 +805,6 @@ test "peer type resolution: error union after non-error" {
833805
834test "peer cast *[0]T to E![]const T" {806test "peer cast *[0]T to E![]const T" {
835 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;807 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
836 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
837 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO808 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
838 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;809 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
839810
...@@ -849,7 +820,6 @@ test "peer cast *[0]T to E![]const T" {...@@ -849,7 +820,6 @@ test "peer cast *[0]T to E![]const T" {
849820
850test "peer cast *[0]T to []const T" {821test "peer cast *[0]T to []const T" {
851 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;822 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
852 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
853 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO823 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
854 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;824 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
855825
...@@ -872,7 +842,6 @@ test "peer cast *[N]T to [*]T" {...@@ -872,7 +842,6 @@ test "peer cast *[N]T to [*]T" {
872}842}
873843
874test "peer resolution of string literals" {844test "peer resolution of string literals" {
875 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
876 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO845 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
877 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO846 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
878 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;847 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -895,7 +864,6 @@ test "peer resolution of string literals" {...@@ -895,7 +864,6 @@ test "peer resolution of string literals" {
895}864}
896865
897test "peer cast [:x]T to []T" {866test "peer cast [:x]T to []T" {
898 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
899 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO867 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
900 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;868 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
901869
...@@ -912,7 +880,6 @@ test "peer cast [:x]T to []T" {...@@ -912,7 +880,6 @@ test "peer cast [:x]T to []T" {
912}880}
913881
914test "peer cast [N:x]T to [N]T" {882test "peer cast [N:x]T to [N]T" {
915 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
916 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO883 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
917 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;884 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
918885
...@@ -929,7 +896,6 @@ test "peer cast [N:x]T to [N]T" {...@@ -929,7 +896,6 @@ test "peer cast [N:x]T to [N]T" {
929}896}
930897
931test "peer cast *[N:x]T to *[N]T" {898test "peer cast *[N:x]T to *[N]T" {
932 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
933 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO899 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
934 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;900 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
935901
...@@ -945,7 +911,6 @@ test "peer cast *[N:x]T to *[N]T" {...@@ -945,7 +911,6 @@ test "peer cast *[N:x]T to *[N]T" {
945}911}
946912
947test "peer cast [*:x]T to [*]T" {913test "peer cast [*:x]T to [*]T" {
948 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
949 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO914 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
950 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;915 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
951 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;916 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -966,7 +931,6 @@ test "peer cast [*:x]T to [*]T" {...@@ -966,7 +931,6 @@ test "peer cast [*:x]T to [*]T" {
966}931}
967932
968test "peer cast [:x]T to [*:x]T" {933test "peer cast [:x]T to [*:x]T" {
969 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
970 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO934 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
971 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO935 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
972 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;936 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -988,7 +952,6 @@ test "peer cast [:x]T to [*:x]T" {...@@ -988,7 +952,6 @@ test "peer cast [:x]T to [*:x]T" {
988}952}
989953
990test "peer type resolution implicit cast to return type" {954test "peer type resolution implicit cast to return type" {
991 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
992 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO955 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
993 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;956 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
994957
...@@ -1009,7 +972,6 @@ test "peer type resolution implicit cast to return type" {...@@ -1009,7 +972,6 @@ test "peer type resolution implicit cast to return type" {
1009}972}
1010973
1011test "peer type resolution implicit cast to variable type" {974test "peer type resolution implicit cast to variable type" {
1012 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1013 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO975 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1014 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;976 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1015977
...@@ -1035,7 +997,6 @@ test "variable initialization uses result locations properly with regards to the...@@ -1035,7 +997,6 @@ test "variable initialization uses result locations properly with regards to the
1035}997}
1036998
1037test "cast between C pointer with different but compatible types" {999test "cast between C pointer with different but compatible types" {
1038 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1039 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1000 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1040 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1001 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10411002
...@@ -1053,7 +1014,6 @@ test "cast between C pointer with different but compatible types" {...@@ -1053,7 +1014,6 @@ test "cast between C pointer with different but compatible types" {
1053}1014}
10541015
1055test "peer type resolve string lit with sentinel-terminated mutable slice" {1016test "peer type resolve string lit with sentinel-terminated mutable slice" {
1056 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1057 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1017 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1058 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1018 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10591019
...@@ -1104,7 +1064,6 @@ test "comptime float casts" {...@@ -1104,7 +1064,6 @@ test "comptime float casts" {
1104}1064}
11051065
1106test "pointer reinterpret const float to int" {1066test "pointer reinterpret const float to int" {
1107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1067 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11091068
1110 // The hex representation is 0x3fe3333333333303.1069 // The hex representation is 0x3fe3333333333303.
...@@ -1119,7 +1078,6 @@ test "pointer reinterpret const float to int" {...@@ -1119,7 +1078,6 @@ test "pointer reinterpret const float to int" {
1119}1078}
11201079
1121test "implicit cast from [*]T to ?*anyopaque" {1080test "implicit cast from [*]T to ?*anyopaque" {
1122 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1081 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1082 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1125 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1083 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1184,7 +1142,6 @@ test "cast function with an opaque parameter" {...@@ -1184,7 +1142,6 @@ test "cast function with an opaque parameter" {
1184}1142}
11851143
1186test "implicit ptr to *anyopaque" {1144test "implicit ptr to *anyopaque" {
1187 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1188 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1189 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1146 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1190 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1147 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1199,7 +1156,6 @@ test "implicit ptr to *anyopaque" {...@@ -1199,7 +1156,6 @@ test "implicit ptr to *anyopaque" {
1199}1156}
12001157
1201test "return null from fn () anyerror!?&T" {1158test "return null from fn () anyerror!?&T" {
1202 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1159 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1204 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1160 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12051161
...@@ -1216,7 +1172,6 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {...@@ -1216,7 +1172,6 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
1216}1172}
12171173
1218test "peer type resolution: [0]u8 and []const u8" {1174test "peer type resolution: [0]u8 and []const u8" {
1219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1220 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1221 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1176 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1222 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1177 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1237,7 +1192,6 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {...@@ -1237,7 +1192,6 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
1237}1192}
12381193
1239test "implicitly cast from [N]T to ?[]const T" {1194test "implicitly cast from [N]T to ?[]const T" {
1240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1195 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1242 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1196 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1243 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1197 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1251,7 +1205,6 @@ fn castToOptionalSlice() ?[]const u8 {...@@ -1251,7 +1205,6 @@ fn castToOptionalSlice() ?[]const u8 {
1251}1205}
12521206
1253test "cast u128 to f128 and back" {1207test "cast u128 to f128 and back" {
1254 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1255 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1208 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1256 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1257 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1210 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1274,7 +1227,6 @@ fn cast128Float(x: u128) f128 {...@@ -1274,7 +1227,6 @@ fn cast128Float(x: u128) f128 {
1274}1227}
12751228
1276test "implicit cast from *[N]T to ?[*]T" {1229test "implicit cast from *[N]T to ?[*]T" {
1277 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1278 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1230 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1279 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1231 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1280 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1232 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1291,7 +1243,6 @@ test "implicit cast from *[N]T to ?[*]T" {...@@ -1291,7 +1243,6 @@ test "implicit cast from *[N]T to ?[*]T" {
1291}1243}
12921244
1293test "implicit cast from *T to ?*anyopaque" {1245test "implicit cast from *T to ?*anyopaque" {
1294 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1295 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1296 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1297 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1248 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1306,7 +1257,6 @@ fn incrementVoidPtrValue(value: ?*anyopaque) void {...@@ -1306,7 +1257,6 @@ fn incrementVoidPtrValue(value: ?*anyopaque) void {
1306}1257}
13071258
1308test "implicit cast *[0]T to E![]const u8" {1259test "implicit cast *[0]T to E![]const u8" {
1309 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1310 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1260 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13111261
1312 var x = @as(anyerror![]const u8, &[0]u8{});1262 var x = @as(anyerror![]const u8, &[0]u8{});
...@@ -1330,7 +1280,6 @@ test "cast from array reference to fn: runtime fn ptr" {...@@ -1330,7 +1280,6 @@ test "cast from array reference to fn: runtime fn ptr" {
1330}1280}
13311281
1332test "*const [N]null u8 to ?[]const u8" {1282test "*const [N]null u8 to ?[]const u8" {
1333 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1334 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1335 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1336 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1285 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1367,7 +1316,6 @@ test "cast between [*c]T and ?[*:0]T on fn parameter" {...@@ -1367,7 +1316,6 @@ test "cast between [*c]T and ?[*:0]T on fn parameter" {
13671316
1368var global_struct: struct { f0: usize } = undefined;1317var global_struct: struct { f0: usize } = undefined;
1369test "assignment to optional pointer result loc" {1318test "assignment to optional pointer result loc" {
1370 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1371 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1319 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1372 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1320 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1373 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1321 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1386,7 +1334,6 @@ test "cast between *[N]void and []void" {...@@ -1386,7 +1334,6 @@ test "cast between *[N]void and []void" {
1386}1334}
13871335
1388test "peer resolve arrays of different size to const slice" {1336test "peer resolve arrays of different size to const slice" {
1389 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1390 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1337 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1391 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1338 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13921339
...@@ -1400,7 +1347,6 @@ fn boolToStr(b: bool) []const u8 {...@@ -1400,7 +1347,6 @@ fn boolToStr(b: bool) []const u8 {
1400}1347}
14011348
1402test "cast f16 to wider types" {1349test "cast f16 to wider types" {
1403 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1350 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1351 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1406 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1352 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1421,7 +1367,6 @@ test "cast f16 to wider types" {...@@ -1421,7 +1367,6 @@ test "cast f16 to wider types" {
1421}1367}
14221368
1423test "cast f128 to narrower types" {1369test "cast f128 to narrower types" {
1424 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1425 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1370 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1426 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1371 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1427 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1372 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1441,7 +1386,6 @@ test "cast f128 to narrower types" {...@@ -1441,7 +1386,6 @@ test "cast f128 to narrower types" {
1441}1386}
14421387
1443test "peer type resolution: unreachable, null, slice" {1388test "peer type resolution: unreachable, null, slice" {
1444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1445 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1389 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1446 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1390 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1447 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1391 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1460,7 +1404,6 @@ test "peer type resolution: unreachable, null, slice" {...@@ -1460,7 +1404,6 @@ test "peer type resolution: unreachable, null, slice" {
1460}1404}
14611405
1462test "cast i8 fn call peers to i32 result" {1406test "cast i8 fn call peers to i32 result" {
1463 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1464 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1407 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14651408
1466 const S = struct {1409 const S = struct {
...@@ -1482,7 +1425,6 @@ test "cast i8 fn call peers to i32 result" {...@@ -1482,7 +1425,6 @@ test "cast i8 fn call peers to i32 result" {
1482}1425}
14831426
1484test "cast compatible optional types" {1427test "cast compatible optional types" {
1485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1486 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1428 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1487 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1429 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1488 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1430 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1494,7 +1436,6 @@ test "cast compatible optional types" {...@@ -1494,7 +1436,6 @@ test "cast compatible optional types" {
1494}1436}
14951437
1496test "coerce undefined single-item pointer of array to error union of slice" {1438test "coerce undefined single-item pointer of array to error union of slice" {
1497 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1439 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14991440
1500 const a = @as([*]u8, undefined)[0..0];1441 const a = @as([*]u8, undefined)[0..0];
...@@ -1513,7 +1454,6 @@ test "pointer to empty struct literal to mutable slice" {...@@ -1513,7 +1454,6 @@ test "pointer to empty struct literal to mutable slice" {
1513}1454}
15141455
1515test "coerce between pointers of compatible differently-named floats" {1456test "coerce between pointers of compatible differently-named floats" {
1516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1517 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1457 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1518 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest;1458 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest;
1519 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1459 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1548,7 +1488,6 @@ test "peer type resolution of const and non-const pointer to array" {...@@ -1548,7 +1488,6 @@ test "peer type resolution of const and non-const pointer to array" {
1548}1488}
15491489
1550test "intFromFloat to zero-bit int" {1490test "intFromFloat to zero-bit int" {
1551 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1552 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1491 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1553 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1492 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15541493
...@@ -1573,8 +1512,6 @@ test "cast typed undefined to int" {...@@ -1573,8 +1512,6 @@ test "cast typed undefined to int" {
1573}1512}
15741513
1575// test "implicit cast from [:0]T to [*c]T" {1514// test "implicit cast from [:0]T to [*c]T" {
1576// if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1577
1578// var a: [:0]const u8 = "foo";1515// var a: [:0]const u8 = "foo";
1579// _ = &a;1516// _ = &a;
1580// const b: [*c]const u8 = a;1517// const b: [*c]const u8 = a;
...@@ -1584,7 +1521,6 @@ test "cast typed undefined to int" {...@@ -1584,7 +1521,6 @@ test "cast typed undefined to int" {
1584// }1521// }
15851522
1586test "bitcast packed struct with u0" {1523test "bitcast packed struct with u0" {
1587 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1588 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1524 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
15891525
1590 const S = packed struct(u2) { a: u0, b: u2 };1526 const S = packed struct(u2) { a: u0, b: u2 };
...@@ -1691,7 +1627,6 @@ test "coercion from single-item pointer to @as to slice" {...@@ -1691,7 +1627,6 @@ test "coercion from single-item pointer to @as to slice" {
1691}1627}
16921628
1693test "peer type resolution: const sentinel slice and mutable non-sentinel slice" {1629test "peer type resolution: const sentinel slice and mutable non-sentinel slice" {
1694 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1695 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1630 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1696 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1631 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1697 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1632 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1721,7 +1656,6 @@ test "peer type resolution: const sentinel slice and mutable non-sentinel slice"...@@ -1721,7 +1656,6 @@ test "peer type resolution: const sentinel slice and mutable non-sentinel slice"
1721}1656}
17221657
1723test "peer type resolution: float and comptime-known fixed-width integer" {1658test "peer type resolution: float and comptime-known fixed-width integer" {
1724 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1725 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1659 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1726 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1660 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17271661
...@@ -1743,7 +1677,7 @@ test "peer type resolution: float and comptime-known fixed-width integer" {...@@ -1743,7 +1677,7 @@ test "peer type resolution: float and comptime-known fixed-width integer" {
1743}1677}
17441678
1745test "peer type resolution: same array type with sentinel" {1679test "peer type resolution: same array type with sentinel" {
1746 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1680 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1747 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1681 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1748 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1682 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1749 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1683 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1766,7 +1700,6 @@ test "peer type resolution: same array type with sentinel" {...@@ -1766,7 +1700,6 @@ test "peer type resolution: same array type with sentinel" {
1766}1700}
17671701
1768test "peer type resolution: array with sentinel and array without sentinel" {1702test "peer type resolution: array with sentinel and array without sentinel" {
1769 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1770 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1703 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1771 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1704 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1772 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1705 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1789,7 +1722,7 @@ test "peer type resolution: array with sentinel and array without sentinel" {...@@ -1789,7 +1722,7 @@ test "peer type resolution: array with sentinel and array without sentinel" {
1789}1722}
17901723
1791test "peer type resolution: array and vector with same child type" {1724test "peer type resolution: array and vector with same child type" {
1792 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1725 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1793 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1726 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1794 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1727 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1795 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1728 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1813,7 +1746,7 @@ test "peer type resolution: array and vector with same child type" {...@@ -1813,7 +1746,7 @@ test "peer type resolution: array and vector with same child type" {
1813}1746}
18141747
1815test "peer type resolution: array with smaller child type and vector with larger child type" {1748test "peer type resolution: array with smaller child type and vector with larger child type" {
1816 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1749 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1817 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1750 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1818 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1751 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1819 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1752 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1837,7 +1770,7 @@ test "peer type resolution: array with smaller child type and vector with larger...@@ -1837,7 +1770,7 @@ test "peer type resolution: array with smaller child type and vector with larger
1837}1770}
18381771
1839test "peer type resolution: error union and optional of same type" {1772test "peer type resolution: error union and optional of same type" {
1840 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1773 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1841 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1774 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1842 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1775 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1843 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1776 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1861,7 +1794,6 @@ test "peer type resolution: error union and optional of same type" {...@@ -1861,7 +1794,6 @@ test "peer type resolution: error union and optional of same type" {
1861}1794}
18621795
1863test "peer type resolution: C pointer and @TypeOf(null)" {1796test "peer type resolution: C pointer and @TypeOf(null)" {
1864 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1865 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1797 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1866 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1798 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1867 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1799 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1884,7 +1816,7 @@ test "peer type resolution: C pointer and @TypeOf(null)" {...@@ -1884,7 +1816,7 @@ test "peer type resolution: C pointer and @TypeOf(null)" {
1884}1816}
18851817
1886test "peer type resolution: three-way resolution combines error set and optional" {1818test "peer type resolution: three-way resolution combines error set and optional" {
1887 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1819 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1888 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1820 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1889 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1821 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1890 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1822 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1927,7 +1859,7 @@ test "peer type resolution: three-way resolution combines error set and optional...@@ -1927,7 +1859,7 @@ test "peer type resolution: three-way resolution combines error set and optional
1927}1859}
19281860
1929test "peer type resolution: vector and optional vector" {1861test "peer type resolution: vector and optional vector" {
1930 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1862 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1931 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1863 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1932 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1864 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1933 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1865 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1952,7 +1884,6 @@ test "peer type resolution: vector and optional vector" {...@@ -1952,7 +1884,6 @@ test "peer type resolution: vector and optional vector" {
1952}1884}
19531885
1954test "peer type resolution: optional fixed-width int and comptime_int" {1886test "peer type resolution: optional fixed-width int and comptime_int" {
1955 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1956 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1887 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1957 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1888 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
19581889
...@@ -1974,7 +1905,7 @@ test "peer type resolution: optional fixed-width int and comptime_int" {...@@ -1974,7 +1905,7 @@ test "peer type resolution: optional fixed-width int and comptime_int" {
1974}1905}
19751906
1976test "peer type resolution: array and tuple" {1907test "peer type resolution: array and tuple" {
1977 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1908 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1978 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1909 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1979 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1910 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1980 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1911 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1998,7 +1929,7 @@ test "peer type resolution: array and tuple" {...@@ -1998,7 +1929,7 @@ test "peer type resolution: array and tuple" {
1998}1929}
19991930
2000test "peer type resolution: vector and tuple" {1931test "peer type resolution: vector and tuple" {
2001 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1932 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2002 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1933 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2003 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1934 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2004 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1935 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -2022,7 +1953,7 @@ test "peer type resolution: vector and tuple" {...@@ -2022,7 +1953,7 @@ test "peer type resolution: vector and tuple" {
2022}1953}
20231954
2024test "peer type resolution: vector and array and tuple" {1955test "peer type resolution: vector and array and tuple" {
2025 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1956 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2026 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1957 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2027 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1958 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2028 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1959 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -2066,7 +1997,6 @@ test "peer type resolution: vector and array and tuple" {...@@ -2066,7 +1997,6 @@ test "peer type resolution: vector and array and tuple" {
2066}1997}
20671998
2068test "peer type resolution: empty tuple pointer and slice" {1999test "peer type resolution: empty tuple pointer and slice" {
2069 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2070 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2000 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2071 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2001 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2072 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2002 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2088,7 +2018,6 @@ test "peer type resolution: empty tuple pointer and slice" {...@@ -2088,7 +2018,6 @@ test "peer type resolution: empty tuple pointer and slice" {
2088}2018}
20892019
2090test "peer type resolution: tuple pointer and slice" {2020test "peer type resolution: tuple pointer and slice" {
2091 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2092 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2021 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2093 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2022 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2094 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2023 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2110,7 +2039,6 @@ test "peer type resolution: tuple pointer and slice" {...@@ -2110,7 +2039,6 @@ test "peer type resolution: tuple pointer and slice" {
2110}2039}
21112040
2112test "peer type resolution: tuple pointer and optional slice" {2041test "peer type resolution: tuple pointer and optional slice" {
2113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2114 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2042 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2043 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2116 // Miscompilation on Intel's OpenCL CPU runtime.2044 // Miscompilation on Intel's OpenCL CPU runtime.
...@@ -2133,7 +2061,6 @@ test "peer type resolution: tuple pointer and optional slice" {...@@ -2133,7 +2061,6 @@ test "peer type resolution: tuple pointer and optional slice" {
2133}2061}
21342062
2135test "peer type resolution: many compatible pointers" {2063test "peer type resolution: many compatible pointers" {
2136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2064 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2065 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2139 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2066 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2200,7 +2127,6 @@ test "peer type resolution: many compatible pointers" {...@@ -2200,7 +2127,6 @@ test "peer type resolution: many compatible pointers" {
2200}2127}
22012128
2202test "peer type resolution: tuples with comptime fields" {2129test "peer type resolution: tuples with comptime fields" {
2203 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2131 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2206 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO2132 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -2232,7 +2158,6 @@ test "peer type resolution: tuples with comptime fields" {...@@ -2232,7 +2158,6 @@ test "peer type resolution: tuples with comptime fields" {
2232}2158}
22332159
2234test "peer type resolution: C pointer and many pointer" {2160test "peer type resolution: C pointer and many pointer" {
2235 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2236 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2237 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2238 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2256,7 +2181,6 @@ test "peer type resolution: C pointer and many pointer" {...@@ -2256,7 +2181,6 @@ test "peer type resolution: C pointer and many pointer" {
2256}2181}
22572182
2258test "peer type resolution: pointer attributes are combined correctly" {2183test "peer type resolution: pointer attributes are combined correctly" {
2259 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2260 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2184 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2261 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2185 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2262 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2186 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2338,7 +2262,7 @@ test "peer type resolution: pointer attributes are combined correctly" {...@@ -2338,7 +2262,7 @@ test "peer type resolution: pointer attributes are combined correctly" {
2338}2262}
23392263
2340test "peer type resolution: arrays of compatible types" {2264test "peer type resolution: arrays of compatible types" {
2341 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2265 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2342 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2266 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2343 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2267 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2344 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2268 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2356,7 +2280,6 @@ test "peer type resolution: arrays of compatible types" {...@@ -2356,7 +2280,6 @@ test "peer type resolution: arrays of compatible types" {
2356}2280}
23572281
2358test "cast builtins can wrap result in optional" {2282test "cast builtins can wrap result in optional" {
2359 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2360 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2361 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2362 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2285 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2394,7 +2317,6 @@ test "cast builtins can wrap result in optional" {...@@ -2394,7 +2317,6 @@ test "cast builtins can wrap result in optional" {
2394}2317}
23952318
2396test "cast builtins can wrap result in error union" {2319test "cast builtins can wrap result in error union" {
2397 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2398 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2399 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
24002322
...@@ -2432,7 +2354,6 @@ test "cast builtins can wrap result in error union" {...@@ -2432,7 +2354,6 @@ test "cast builtins can wrap result in error union" {
2432}2354}
24332355
2434test "cast builtins can wrap result in error union and optional" {2356test "cast builtins can wrap result in error union and optional" {
2435 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2436 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2357 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2437 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2358 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2438 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2359 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2471,8 +2392,8 @@ test "cast builtins can wrap result in error union and optional" {...@@ -2471,8 +2392,8 @@ test "cast builtins can wrap result in error union and optional" {
2471}2392}
24722393
2473test "@floatCast on vector" {2394test "@floatCast on vector" {
2395 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2474 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2396 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2475 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2477 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2398 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2478 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2399 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -2512,8 +2433,8 @@ test "@floatCast on vector" {...@@ -2512,8 +2433,8 @@ test "@floatCast on vector" {
2512}2433}
25132434
2514test "@ptrFromInt on vector" {2435test "@ptrFromInt on vector" {
2436 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2515 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2437 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2517 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2438 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2518 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2439 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2519 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2440 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -2537,8 +2458,8 @@ test "@ptrFromInt on vector" {...@@ -2537,8 +2458,8 @@ test "@ptrFromInt on vector" {
2537}2458}
25382459
2539test "@intFromPtr on vector" {2460test "@intFromPtr on vector" {
2461 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2540 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2462 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2541 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2542 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2543 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2464 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2544 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2465 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -2562,8 +2483,8 @@ test "@intFromPtr on vector" {...@@ -2562,8 +2483,8 @@ test "@intFromPtr on vector" {
2562}2483}
25632484
2564test "@floatFromInt on vector" {2485test "@floatFromInt on vector" {
2486 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2565 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2487 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2566 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2567 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2488 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2568 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2489 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2569 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2490 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -2582,8 +2503,8 @@ test "@floatFromInt on vector" {...@@ -2582,8 +2503,8 @@ test "@floatFromInt on vector" {
2582}2503}
25832504
2584test "@intFromFloat on vector" {2505test "@intFromFloat on vector" {
2506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2585 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2507 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2586 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2587 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2508 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2588 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2509 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2589 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2510 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -2602,8 +2523,8 @@ test "@intFromFloat on vector" {...@@ -2602,8 +2523,8 @@ test "@intFromFloat on vector" {
2602}2523}
26032524
2604test "@intFromBool on vector" {2525test "@intFromBool on vector" {
2526 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2605 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2527 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2606 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2607 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2528 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2608 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2529 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2609 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2530 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -2639,7 +2560,6 @@ test "15-bit int to float" {...@@ -2639,7 +2560,6 @@ test "15-bit int to float" {
2639}2560}
26402561
2641test "@as does not corrupt values with incompatible representations" {2562test "@as does not corrupt values with incompatible representations" {
2642 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2643 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2563 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2644 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2564 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
26452565
...@@ -2654,7 +2574,6 @@ test "@as does not corrupt values with incompatible representations" {...@@ -2654,7 +2574,6 @@ test "@as does not corrupt values with incompatible representations" {
2654}2574}
26552575
2656test "result information is preserved through many nested structures" {2576test "result information is preserved through many nested structures" {
2657 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2658 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2577 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2659 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2578 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2660 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2579 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2679,7 +2598,7 @@ test "result information is preserved through many nested structures" {...@@ -2679,7 +2598,7 @@ test "result information is preserved through many nested structures" {
2679}2598}
26802599
2681test "@intCast vector of signed integer" {2600test "@intCast vector of signed integer" {
2682 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2601 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2683 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2602 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2684 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2603 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2685 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2604 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -2703,7 +2622,6 @@ test "result type is preserved into comptime block" {...@@ -2703,7 +2622,6 @@ test "result type is preserved into comptime block" {
2703}2622}
27042623
2705test "bitcast vector" {2624test "bitcast vector" {
2706 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2707 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2625 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
27082626
2709 const u8x32 = @Vector(32, u8);2627 const u8x32 = @Vector(32, u8);
...@@ -2766,6 +2684,7 @@ test "@intFromFloat boundary cases" {...@@ -2766,6 +2684,7 @@ test "@intFromFloat boundary cases" {
2766}2684}
27672685
2768test "@intFromFloat vector boundary cases" {2686test "@intFromFloat vector boundary cases" {
2687 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2769 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2688 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2770 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;2689 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
2771 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;2690 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
test/behavior/cast_int.zig+4-3
...@@ -5,7 +5,6 @@ const expectEqual = std.testing.expectEqual;...@@ -5,7 +5,6 @@ const expectEqual = std.testing.expectEqual;
5const maxInt = std.math.maxInt;5const maxInt = std.math.maxInt;
66
7test "@intCast i32 to u7" {7test "@intCast i32 to u7" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -19,7 +18,6 @@ test "@intCast i32 to u7" {...@@ -19,7 +18,6 @@ test "@intCast i32 to u7" {
19}18}
2019
21test "coerce i8 to i32 and @intCast back" {20test "coerce i8 to i32 and @intCast back" {
22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2523
...@@ -36,6 +34,7 @@ test "coerce i8 to i32 and @intCast back" {...@@ -36,6 +34,7 @@ test "coerce i8 to i32 and @intCast back" {
3634
37test "coerce non byte-sized integers accross 32bits boundary" {35test "coerce non byte-sized integers accross 32bits boundary" {
38 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO36 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
37
39 {38 {
40 var v: u21 = 6417;39 var v: u21 = 6417;
41 _ = &v;40 _ = &v;
...@@ -164,8 +163,9 @@ const Piece = packed struct {...@@ -164,8 +163,9 @@ const Piece = packed struct {
164 }163 }
165};164};
166165
166// Originally reported at https://github.com/ziglang/zig/issues/14200
167test "load non byte-sized optional value" {167test "load non byte-sized optional value" {
168 // Originally reported at https://github.com/ziglang/zig/issues/14200168 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
169 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;169 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
170 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO170 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
171171
...@@ -181,6 +181,7 @@ test "load non byte-sized optional value" {...@@ -181,6 +181,7 @@ test "load non byte-sized optional value" {
181}181}
182182
183test "load non byte-sized value in struct" {183test "load non byte-sized value in struct" {
184 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
184 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;185 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
185 if (builtin.cpu.arch.endian() != .little) return error.SkipZigTest; // packed struct TODO186 if (builtin.cpu.arch.endian() != .little) return error.SkipZigTest; // packed struct TODO
186 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO187 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
test/behavior/comptime_memory.zig-2
...@@ -66,7 +66,6 @@ fn bigToNativeEndian(comptime T: type, v: T) T {...@@ -66,7 +66,6 @@ fn bigToNativeEndian(comptime T: type, v: T) T {
66 return if (endian == .big) v else @byteSwap(v);66 return if (endian == .big) v else @byteSwap(v);
67}67}
68test "type pun endianness" {68test "type pun endianness" {
69 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
70 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7170
72 comptime {71 comptime {
...@@ -360,7 +359,6 @@ test "offset field ptr by enclosing array element size" {...@@ -360,7 +359,6 @@ test "offset field ptr by enclosing array element size" {
360}359}
361360
362test "accessing reinterpreted memory of parent object" {361test "accessing reinterpreted memory of parent object" {
363 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
364 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO362 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
365363
366 const S = extern struct {364 const S = extern struct {
test/behavior/const_slice_child.zig-1
...@@ -7,7 +7,6 @@ const expect = testing.expect;...@@ -7,7 +7,6 @@ const expect = testing.expect;
7var argv: [*]const [*]const u8 = undefined;7var argv: [*]const [*]const u8 = undefined;
88
9test "const slice child" {9test "const slice child" {
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/decl_literals.zig+2-1
...@@ -33,9 +33,9 @@ test "decl literal with pointer" {...@@ -33,9 +33,9 @@ test "decl literal with pointer" {
33}33}
3434
35test "call decl literal with optional" {35test "call decl literal with optional" {
36 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;39 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
4040
41 const S = struct {41 const S = struct {
...@@ -74,6 +74,7 @@ test "call decl literal" {...@@ -74,6 +74,7 @@ test "call decl literal" {
74}74}
7575
76test "call decl literal with error union" {76test "call decl literal with error union" {
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
7879
79 const S = struct {80 const S = struct {
test/behavior/defer.zig+2-6
...@@ -32,7 +32,6 @@ test "defer and labeled break" {...@@ -32,7 +32,6 @@ test "defer and labeled break" {
32}32}
3333
34test "errdefer does not apply to fn inside fn" {34test "errdefer does not apply to fn inside fn" {
35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO35 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3736
38 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);37 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);
...@@ -51,7 +50,6 @@ fn testNestedFnErrDefer() anyerror!void {...@@ -51,7 +50,6 @@ fn testNestedFnErrDefer() anyerror!void {
5150
52test "return variable while defer expression in scope to modify it" {51test "return variable while defer expression in scope to modify it" {
53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO53 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5654
57 const S = struct {55 const S = struct {
...@@ -91,7 +89,6 @@ fn runSomeErrorDefers(x: bool) !bool {...@@ -91,7 +89,6 @@ fn runSomeErrorDefers(x: bool) !bool {
91}89}
9290
93test "mixing normal and error defers" {91test "mixing normal and error defers" {
94 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
95 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO92 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
96 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO93 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9794
...@@ -110,7 +107,7 @@ test "mixing normal and error defers" {...@@ -110,7 +107,7 @@ test "mixing normal and error defers" {
110}107}
111108
112test "errdefer with payload" {109test "errdefer with payload" {
113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO110 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
114 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO111 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO112 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
116 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;113 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -132,8 +129,8 @@ test "errdefer with payload" {...@@ -132,8 +129,8 @@ test "errdefer with payload" {
132}129}
133130
134test "reference to errdefer payload" {131test "reference to errdefer payload" {
132 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
135 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO133 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
138 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;136 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -157,7 +154,6 @@ test "reference to errdefer payload" {...@@ -157,7 +154,6 @@ test "reference to errdefer payload" {
157}154}
158155
159test "simple else prong doesn't emit an error for unreachable else prong" {156test "simple else prong doesn't emit an error for unreachable else prong" {
160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO157 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;158 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
163159
test/behavior/enum.zig+10-18
...@@ -25,7 +25,6 @@ fn testEnumFromIntEval(x: i32) !void {...@@ -25,7 +25,6 @@ fn testEnumFromIntEval(x: i32) !void {
25const EnumFromIntNumber = enum { Zero, One, Two, Three, Four };25const EnumFromIntNumber = enum { Zero, One, Two, Three, Four };
2626
27test "int to enum" {27test "int to enum" {
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO28 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3029
31 try testEnumFromIntEval(3);30 try testEnumFromIntEval(3);
...@@ -608,7 +607,6 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {...@@ -608,7 +607,6 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
608}607}
609608
610test "enum with specified tag values" {609test "enum with specified tag values" {
611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
612 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO610 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
613611
614 try testEnumWithSpecifiedTagValues(MultipleChoice.C);612 try testEnumWithSpecifiedTagValues(MultipleChoice.C);
...@@ -616,7 +614,6 @@ test "enum with specified tag values" {...@@ -616,7 +614,6 @@ test "enum with specified tag values" {
616}614}
617615
618test "non-exhaustive enum" {616test "non-exhaustive enum" {
619 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
620 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO617 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
621618
622 const S = struct {619 const S = struct {
...@@ -680,7 +677,6 @@ test "empty non-exhaustive enum" {...@@ -680,7 +677,6 @@ test "empty non-exhaustive enum" {
680}677}
681678
682test "single field non-exhaustive enum" {679test "single field non-exhaustive enum" {
683 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
684 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO680 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
685681
686 const S = struct {682 const S = struct {
...@@ -744,7 +740,6 @@ test "cast integer literal to enum" {...@@ -744,7 +740,6 @@ test "cast integer literal to enum" {
744}740}
745741
746test "enum with specified and unspecified tag values" {742test "enum with specified and unspecified tag values" {
747 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
748 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO743 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
749744
750 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);745 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
...@@ -904,8 +899,8 @@ test "enum value allocation" {...@@ -904,8 +899,8 @@ test "enum value allocation" {
904}899}
905900
906test "enum literal casting to tagged union" {901test "enum literal casting to tagged union" {
907 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
908 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;902 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
903 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
909 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO904 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
910905
911 const Arch = union(enum) {906 const Arch = union(enum) {
...@@ -941,8 +936,8 @@ test "enum literal casting to error union with payload enum" {...@@ -941,8 +936,8 @@ test "enum literal casting to error union with payload enum" {
941}936}
942937
943test "constant enum initialization with differing sizes" {938test "constant enum initialization with differing sizes" {
944 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
945 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;939 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
940 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
946 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO941 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
947 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;942 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
948 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;943 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -985,8 +980,8 @@ fn test3_2(f: Test3Foo) !void {...@@ -985,8 +980,8 @@ fn test3_2(f: Test3Foo) !void {
985}980}
986981
987test "@tagName" {982test "@tagName" {
988 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
989 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;983 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
984 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
990 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO985 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
991 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;986 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
992 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;987 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1002,8 +997,8 @@ fn testEnumTagNameBare(n: anytype) []const u8 {...@@ -1002,8 +997,8 @@ fn testEnumTagNameBare(n: anytype) []const u8 {
1002const BareNumber = enum { One, Two, Three };997const BareNumber = enum { One, Two, Three };
1003998
1004test "@tagName non-exhaustive enum" {999test "@tagName non-exhaustive enum" {
1005 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1006 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1000 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1001 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1007 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1002 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1008 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1003 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1009 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1004 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1014,8 +1009,8 @@ test "@tagName non-exhaustive enum" {...@@ -1014,8 +1009,8 @@ test "@tagName non-exhaustive enum" {
1014const NonExhaustive = enum(u8) { A, B, _ };1009const NonExhaustive = enum(u8) { A, B, _ };
10151010
1016test "@tagName is null-terminated" {1011test "@tagName is null-terminated" {
1017 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1018 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1012 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1013 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1019 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1014 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1020 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1015 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1021 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1016 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1030,8 +1025,8 @@ test "@tagName is null-terminated" {...@@ -1030,8 +1025,8 @@ test "@tagName is null-terminated" {
1030}1025}
10311026
1032test "tag name with assigned enum values" {1027test "tag name with assigned enum values" {
1033 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1034 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1028 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1035 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1030 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1036 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1031 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1037 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1032 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1046,7 +1041,6 @@ test "tag name with assigned enum values" {...@@ -1046,7 +1041,6 @@ test "tag name with assigned enum values" {
1046}1041}
10471042
1048test "@tagName on enum literals" {1043test "@tagName on enum literals" {
1049 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1050 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1044 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1051 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1045 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10521046
...@@ -1055,8 +1049,8 @@ test "@tagName on enum literals" {...@@ -1055,8 +1049,8 @@ test "@tagName on enum literals" {
1055}1049}
10561050
1057test "tag name with signed enum values" {1051test "tag name with signed enum values" {
1058 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1059 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1052 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1053 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1060 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1054 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1061 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1055 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1062 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1056 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1073,8 +1067,8 @@ test "tag name with signed enum values" {...@@ -1073,8 +1067,8 @@ test "tag name with signed enum values" {
1073}1067}
10741068
1075test "@tagName in callconv(.c) function" {1069test "@tagName in callconv(.c) function" {
1076 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1077 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1070 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1071 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1078 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;1072 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
1079 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1073 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1080 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1074 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1091,7 +1085,6 @@ fn testEnumTagNameCallconvC() callconv(.c) [*:0]const u8 {...@@ -1091,7 +1085,6 @@ fn testEnumTagNameCallconvC() callconv(.c) [*:0]const u8 {
10911085
1092test "enum literal casting to optional" {1086test "enum literal casting to optional" {
1093 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1087 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1094 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1095 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1088 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10961089
1097 var bar: ?Bar = undefined;1090 var bar: ?Bar = undefined;
...@@ -1117,8 +1110,8 @@ const bit_field_1 = BitFieldOfEnums{...@@ -1117,8 +1110,8 @@ const bit_field_1 = BitFieldOfEnums{
1117};1110};
11181111
1119test "bit field access with enum fields" {1112test "bit field access with enum fields" {
1120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1121 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1114 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1122 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1123 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1116 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1124 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO1117 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
...@@ -1158,8 +1151,8 @@ test "enum literal in array literal" {...@@ -1158,8 +1151,8 @@ test "enum literal in array literal" {
1158}1151}
11591152
1160test "tag name functions are unique" {1153test "tag name functions are unique" {
1161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1162 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1154 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1155 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1163 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1156 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1164 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1157 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1165 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1158 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1179,7 +1172,6 @@ test "tag name functions are unique" {...@@ -1179,7 +1172,6 @@ test "tag name functions are unique" {
1179}1172}
11801173
1181test "size of enum with only one tag which has explicit integer tag type" {1174test "size of enum with only one tag which has explicit integer tag type" {
1182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11841176
1185 const E = enum(u8) { nope = 10 };1177 const E = enum(u8) { nope = 10 };
test/behavior/error.zig+19-22
...@@ -145,11 +145,14 @@ test "implicit cast to optional to error union to return result loc" {...@@ -145,11 +145,14 @@ test "implicit cast to optional to error union to return result loc" {
145}145}
146146
147test "fn returning empty error set can be passed as fn returning any error" {147test "fn returning empty error set can be passed as fn returning any error" {
148 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
149
148 entry();150 entry();
149 comptime entry();151 comptime entry();
150}152}
151153
152test "fn returning empty error set can be passed as fn returning any error - pointer" {154test "fn returning empty error set can be passed as fn returning any error - pointer" {
155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
153 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;156 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
154157
155 entryPtr();158 entryPtr();
...@@ -401,8 +404,8 @@ fn intLiteral(str: []const u8) !?i64 {...@@ -401,8 +404,8 @@ fn intLiteral(str: []const u8) !?i64 {
401}404}
402405
403test "nested error union function call in optional unwrap" {406test "nested error union function call in optional unwrap" {
407 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO408 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
406 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO409 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
407410
408 const S = struct {411 const S = struct {
...@@ -448,7 +451,6 @@ test "nested error union function call in optional unwrap" {...@@ -448,7 +451,6 @@ test "nested error union function call in optional unwrap" {
448}451}
449452
450test "return function call to error set from error union function" {453test "return function call to error set from error union function" {
451 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO454 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
453455
454 const S = struct {456 const S = struct {
...@@ -465,7 +467,6 @@ test "return function call to error set from error union function" {...@@ -465,7 +467,6 @@ test "return function call to error set from error union function" {
465}467}
466468
467test "optional error set is the same size as error set" {469test "optional error set is the same size as error set" {
468 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
469 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO470 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
470 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO471 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
471472
...@@ -481,7 +482,7 @@ test "optional error set is the same size as error set" {...@@ -481,7 +482,7 @@ test "optional error set is the same size as error set" {
481}482}
482483
483test "nested catch" {484test "nested catch" {
484 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
485 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO486 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
486487
487 const S = struct {488 const S = struct {
...@@ -530,7 +531,7 @@ test "function pointer with return type that is error union with payload which i...@@ -530,7 +531,7 @@ test "function pointer with return type that is error union with payload which i
530}531}
531532
532test "return result loc as peer result loc in inferred error set function" {533test "return result loc as peer result loc in inferred error set function" {
533 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO534 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
534 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO535 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
535 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO536 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
536537
...@@ -562,7 +563,6 @@ test "return result loc as peer result loc in inferred error set function" {...@@ -562,7 +563,6 @@ test "return result loc as peer result loc in inferred error set function" {
562563
563test "error payload type is correctly resolved" {564test "error payload type is correctly resolved" {
564 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO565 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
565 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
566 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO566 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
567567
568 const MyIntWrapper = struct {568 const MyIntWrapper = struct {
...@@ -590,8 +590,8 @@ test "error union comptime caching" {...@@ -590,8 +590,8 @@ test "error union comptime caching" {
590}590}
591591
592test "@errorName" {592test "@errorName" {
593 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
594 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;593 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
594 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
595 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO595 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
596 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;596 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
597 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;597 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -605,8 +605,8 @@ fn gimmeItBroke() anyerror {...@@ -605,8 +605,8 @@ fn gimmeItBroke() anyerror {
605}605}
606606
607test "@errorName sentinel length matches slice length" {607test "@errorName sentinel length matches slice length" {
608 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
609 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;608 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
609 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
610 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO610 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
611 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;611 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
612 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;612 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -700,8 +700,8 @@ test "coerce error set to the current inferred error set" {...@@ -700,8 +700,8 @@ test "coerce error set to the current inferred error set" {
700}700}
701701
702test "error union payload is properly aligned" {702test "error union payload is properly aligned" {
703 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
703 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO704 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
704 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
705 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO705 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
706 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;706 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
707 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;707 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -719,7 +719,6 @@ test "error union payload is properly aligned" {...@@ -719,7 +719,6 @@ test "error union payload is properly aligned" {
719}719}
720720
721test "ret_ptr doesn't cause own inferred error set to be resolved" {721test "ret_ptr doesn't cause own inferred error set to be resolved" {
722 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
723 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO722 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
724723
725 const S = struct {724 const S = struct {
...@@ -760,7 +759,7 @@ test "simple else prong allowed even when all errors handled" {...@@ -760,7 +759,7 @@ test "simple else prong allowed even when all errors handled" {
760}759}
761760
762test "pointer to error union payload" {761test "pointer to error union payload" {
763 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO762 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
764 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO763 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
765 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO764 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
766 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;765 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -794,7 +793,6 @@ const NoReturn = struct {...@@ -794,7 +793,6 @@ const NoReturn = struct {
794};793};
795794
796test "error union of noreturn used with if" {795test "error union of noreturn used with if" {
797 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
798 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO796 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
799 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO797 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
800 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;798 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -809,7 +807,6 @@ test "error union of noreturn used with if" {...@@ -809,7 +807,6 @@ test "error union of noreturn used with if" {
809}807}
810808
811test "error union of noreturn used with try" {809test "error union of noreturn used with try" {
812 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
813 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO810 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
814 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO811 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
815 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;812 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -821,7 +818,6 @@ test "error union of noreturn used with try" {...@@ -821,7 +818,6 @@ test "error union of noreturn used with try" {
821}818}
822819
823test "error union of noreturn used with catch" {820test "error union of noreturn used with catch" {
824 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
825 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO821 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
826 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO822 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
827 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;823 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -833,7 +829,6 @@ test "error union of noreturn used with catch" {...@@ -833,7 +829,6 @@ test "error union of noreturn used with catch" {
833}829}
834830
835test "alignment of wrapping an error union payload" {831test "alignment of wrapping an error union payload" {
836 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
837 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;832 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
838 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO833 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
839 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;834 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -852,6 +847,7 @@ test "alignment of wrapping an error union payload" {...@@ -852,6 +847,7 @@ test "alignment of wrapping an error union payload" {
852}847}
853848
854test "compare error union and error set" {849test "compare error union and error set" {
850 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
855 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO851 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
856852
857 var a: anyerror = error.Foo;853 var a: anyerror = error.Foo;
...@@ -887,7 +883,7 @@ test "catch within a function that calls no errorable functions" {...@@ -887,7 +883,7 @@ test "catch within a function that calls no errorable functions" {
887}883}
888884
889test "error from comptime string" {885test "error from comptime string" {
890 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO886 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
891 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO887 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
892 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO888 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
893 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;889 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -913,7 +909,6 @@ test "field access of anyerror results in smaller error set" {...@@ -913,7 +909,6 @@ test "field access of anyerror results in smaller error set" {
913}909}
914910
915test "optional error union return type" {911test "optional error union return type" {
916 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
917 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO912 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
918913
919 const S = struct {914 const S = struct {
...@@ -928,7 +923,6 @@ test "optional error union return type" {...@@ -928,7 +923,6 @@ test "optional error union return type" {
928923
929test "optional error set return type" {924test "optional error set return type" {
930 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO925 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
931 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
932926
933 const E = error{ A, B };927 const E = error{ A, B };
934 const S = struct {928 const S = struct {
...@@ -952,8 +946,8 @@ test "optional error set function parameter" {...@@ -952,8 +946,8 @@ test "optional error set function parameter" {
952}946}
953947
954test "returning an error union containing a type with no runtime bits" {948test "returning an error union containing a type with no runtime bits" {
949 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
955 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO950 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
956 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
957 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;951 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
958952
959 const ZeroByteType = struct {953 const ZeroByteType = struct {
...@@ -969,7 +963,7 @@ test "returning an error union containing a type with no runtime bits" {...@@ -969,7 +963,7 @@ test "returning an error union containing a type with no runtime bits" {
969}963}
970964
971test "try used in recursive function with inferred error set" {965test "try used in recursive function with inferred error set" {
972 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO966 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
973 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO967 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
974 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;968 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
975969
...@@ -1010,7 +1004,6 @@ test "generic inline function returns inferred error set" {...@@ -1010,7 +1004,6 @@ test "generic inline function returns inferred error set" {
1010}1004}
10111005
1012test "function called at runtime is properly analyzed for inferred error set" {1006test "function called at runtime is properly analyzed for inferred error set" {
1013 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1014 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1007 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1015 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1008 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10161009
...@@ -1045,6 +1038,8 @@ test "errorCast to adhoc inferred error set" {...@@ -1045,6 +1038,8 @@ test "errorCast to adhoc inferred error set" {
1045}1038}
10461039
1047test "@errorCast from error set to error union" {1040test "@errorCast from error set to error union" {
1041 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1042
1048 const S = struct {1043 const S = struct {
1049 fn doTheTest(set: error{ A, B }) error{A}!i32 {1044 fn doTheTest(set: error{ A, B }) error{A}!i32 {
1050 return @errorCast(set);1045 return @errorCast(set);
...@@ -1055,6 +1050,8 @@ test "@errorCast from error set to error union" {...@@ -1055,6 +1050,8 @@ test "@errorCast from error set to error union" {
1055}1050}
10561051
1057test "@errorCast from error union to error union" {1052test "@errorCast from error union to error union" {
1053 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1054
1058 const S = struct {1055 const S = struct {
1059 fn doTheTest(set: error{ A, B }!i32) error{A}!i32 {1056 fn doTheTest(set: error{ A, B }!i32) error{A}!i32 {
1060 return @errorCast(set);1057 return @errorCast(set);
...@@ -1065,8 +1062,8 @@ test "@errorCast from error union to error union" {...@@ -1065,8 +1062,8 @@ test "@errorCast from error union to error union" {
1065}1062}
10661063
1067test "result location initialization of error union with OPV payload" {1064test "result location initialization of error union with OPV payload" {
1065 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1068 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1066 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1069 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1070 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1067 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1071 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1068 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1072 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO1069 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
test/behavior/eval.zig+2-34
...@@ -18,7 +18,6 @@ fn unwrapAndAddOne(blah: ?i32) i32 {...@@ -18,7 +18,6 @@ fn unwrapAndAddOne(blah: ?i32) i32 {
18}18}
19const should_be_1235 = unwrapAndAddOne(1234);19const should_be_1235 = unwrapAndAddOne(1234);
20test "static add one" {20test "static add one" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2423
...@@ -71,7 +70,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {...@@ -71,7 +70,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
71}70}
7271
73test "constant expressions" {72test "constant expressions" {
74 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO73 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7674
77 var array: [array_size]u8 = undefined;75 var array: [array_size]u8 = undefined;
...@@ -93,7 +91,6 @@ fn letsTryToCompareBools(a: bool, b: bool) bool {...@@ -93,7 +91,6 @@ fn letsTryToCompareBools(a: bool, b: bool) bool {
93 return max(bool, a, b);91 return max(bool, a, b);
94}92}
95test "inlined block and runtime block phi" {93test "inlined block and runtime block phi" {
96 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
97 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO94 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9895
99 try expect(letsTryToCompareBools(true, true));96 try expect(letsTryToCompareBools(true, true));
...@@ -140,7 +137,6 @@ test "pointer to type" {...@@ -140,7 +137,6 @@ test "pointer to type" {
140}137}
141138
142test "a type constructed in a global expression" {139test "a type constructed in a global expression" {
143 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO140 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;141 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;142 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -236,7 +232,6 @@ const vertices = [_]Vertex{...@@ -236,7 +232,6 @@ const vertices = [_]Vertex{
236};232};
237233
238test "statically initialized list" {234test "statically initialized list" {
239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
240 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO235 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
241236
242 try expect(static_point_list[0].x == 1);237 try expect(static_point_list[0].x == 1);
...@@ -342,7 +337,6 @@ fn doesAlotT(comptime T: type, value: usize) T {...@@ -342,7 +337,6 @@ fn doesAlotT(comptime T: type, value: usize) T {
342}337}
343338
344test "@setEvalBranchQuota at same scope as generic function call" {339test "@setEvalBranchQuota at same scope as generic function call" {
345 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO340 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
347341
348 try expect(doesAlotT(u32, 2) == 2);342 try expect(doesAlotT(u32, 2) == 2);
...@@ -394,7 +388,6 @@ test "return 0 from function that has u0 return type" {...@@ -394,7 +388,6 @@ test "return 0 from function that has u0 return type" {
394}388}
395389
396test "statically initialized struct" {390test "statically initialized struct" {
397 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
398 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO391 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
399392
400 st_init_str_foo.x += 1;393 st_init_str_foo.x += 1;
...@@ -444,7 +437,6 @@ fn copyWithPartialInline(s: []u32, b: []u8) void {...@@ -444,7 +437,6 @@ fn copyWithPartialInline(s: []u32, b: []u8) void {
444437
445test "binary math operator in partially inlined function" {438test "binary math operator in partially inlined function" {
446 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO439 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
447 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO440 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
449 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;441 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
450442
...@@ -462,7 +454,6 @@ test "binary math operator in partially inlined function" {...@@ -462,7 +454,6 @@ test "binary math operator in partially inlined function" {
462}454}
463455
464test "comptime shl" {456test "comptime shl" {
465 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
466 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO457 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
467 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO458 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
468 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;459 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -491,6 +482,7 @@ test "comptime bitwise operators" {...@@ -491,6 +482,7 @@ test "comptime bitwise operators" {
491}482}
492483
493test "comptime shlWithOverflow" {484test "comptime shlWithOverflow" {
485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
494 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO486 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
495 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;487 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
496488
...@@ -503,7 +495,6 @@ test "comptime shlWithOverflow" {...@@ -503,7 +495,6 @@ test "comptime shlWithOverflow" {
503}495}
504496
505test "const ptr to variable data changes at runtime" {497test "const ptr to variable data changes at runtime" {
506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;499 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
509500
...@@ -521,7 +512,6 @@ const foo_ref = &foo_contents;...@@ -521,7 +512,6 @@ const foo_ref = &foo_contents;
521512
522test "runtime 128 bit integer division" {513test "runtime 128 bit integer division" {
523 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
524 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
525 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
526 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO516 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
527 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;517 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -536,7 +526,6 @@ test "runtime 128 bit integer division" {...@@ -536,7 +526,6 @@ test "runtime 128 bit integer division" {
536}526}
537527
538test "@tagName of @typeInfo" {528test "@tagName of @typeInfo" {
539 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
540 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO529 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
541 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;530 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
542531
...@@ -545,7 +534,6 @@ test "@tagName of @typeInfo" {...@@ -545,7 +534,6 @@ test "@tagName of @typeInfo" {
545}534}
546535
547test "static eval list init" {536test "static eval list init" {
548 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
549 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO537 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
550 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO538 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
551539
...@@ -578,7 +566,6 @@ test "inlined loop has array literal with elided runtime scope on first iteratio...@@ -578,7 +566,6 @@ test "inlined loop has array literal with elided runtime scope on first iteratio
578}566}
579567
580test "ptr to local array argument at comptime" {568test "ptr to local array argument at comptime" {
581 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
582 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO569 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
583570
584 comptime {571 comptime {
...@@ -741,7 +728,6 @@ test "*align(1) u16 is the same as *align(1:0:2) u16" {...@@ -741,7 +728,6 @@ test "*align(1) u16 is the same as *align(1:0:2) u16" {
741728
742test "array concatenation of function calls" {729test "array concatenation of function calls" {
743 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;730 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
744 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
745 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO731 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
746 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;732 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
747733
...@@ -751,7 +737,6 @@ test "array concatenation of function calls" {...@@ -751,7 +737,6 @@ test "array concatenation of function calls" {
751737
752test "array multiplication of function calls" {738test "array multiplication of function calls" {
753 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;739 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
754 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
755 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO740 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
756 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;741 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
757742
...@@ -769,7 +754,6 @@ fn scalar(x: u32) u32 {...@@ -769,7 +754,6 @@ fn scalar(x: u32) u32 {
769754
770test "array concatenation peer resolves element types - value" {755test "array concatenation peer resolves element types - value" {
771 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;756 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
772 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
773 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO757 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
774758
775 var a = [2]u3{ 1, 7 };759 var a = [2]u3{ 1, 7 };
...@@ -786,7 +770,6 @@ test "array concatenation peer resolves element types - value" {...@@ -786,7 +770,6 @@ test "array concatenation peer resolves element types - value" {
786770
787test "array concatenation peer resolves element types - pointer" {771test "array concatenation peer resolves element types - pointer" {
788 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;772 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
789 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
790 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO773 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
791 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;774 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
792775
...@@ -803,7 +786,6 @@ test "array concatenation peer resolves element types - pointer" {...@@ -803,7 +786,6 @@ test "array concatenation peer resolves element types - pointer" {
803786
804test "array concatenation sets the sentinel - value" {787test "array concatenation sets the sentinel - value" {
805 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;788 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
806 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
807 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO789 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
808 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;790 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
809 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;791 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -823,7 +805,6 @@ test "array concatenation sets the sentinel - value" {...@@ -823,7 +805,6 @@ test "array concatenation sets the sentinel - value" {
823}805}
824806
825test "array concatenation sets the sentinel - pointer" {807test "array concatenation sets the sentinel - pointer" {
826 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
827 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO808 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
828 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;809 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
829 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;810 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -843,7 +824,6 @@ test "array concatenation sets the sentinel - pointer" {...@@ -843,7 +824,6 @@ test "array concatenation sets the sentinel - pointer" {
843824
844test "array multiplication sets the sentinel - value" {825test "array multiplication sets the sentinel - value" {
845 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;826 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
846 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
847 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO827 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
848 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;828 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
849 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;829 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -862,7 +842,6 @@ test "array multiplication sets the sentinel - value" {...@@ -862,7 +842,6 @@ test "array multiplication sets the sentinel - value" {
862842
863test "array multiplication sets the sentinel - pointer" {843test "array multiplication sets the sentinel - pointer" {
864 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;844 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
865 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
866 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO845 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
867 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;846 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
868 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;847 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -889,7 +868,6 @@ test "comptime assign int to optional int" {...@@ -889,7 +868,6 @@ test "comptime assign int to optional int" {
889868
890test "two comptime calls with array default initialized to undefined" {869test "two comptime calls with array default initialized to undefined" {
891 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO870 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
892 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
893 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO871 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
894872
895 const S = struct {873 const S = struct {
...@@ -976,7 +954,6 @@ test "const local with comptime init through array init" {...@@ -976,7 +954,6 @@ test "const local with comptime init through array init" {
976}954}
977955
978test "closure capture type of runtime-known parameter" {956test "closure capture type of runtime-known parameter" {
979 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
980 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO957 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
981958
982 const S = struct {959 const S = struct {
...@@ -992,7 +969,6 @@ test "closure capture type of runtime-known parameter" {...@@ -992,7 +969,6 @@ test "closure capture type of runtime-known parameter" {
992}969}
993970
994test "closure capture type of runtime-known var" {971test "closure capture type of runtime-known var" {
995 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
996 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO972 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
997973
998 var x: u32 = 1234;974 var x: u32 = 1234;
...@@ -1035,7 +1011,6 @@ test "comptime break passing through runtime condition converted to runtime brea...@@ -1035,7 +1011,6 @@ test "comptime break passing through runtime condition converted to runtime brea
1035}1011}
10361012
1037test "comptime break to outer loop passing through runtime condition converted to runtime break" {1013test "comptime break to outer loop passing through runtime condition converted to runtime break" {
1038 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1039 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1014 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1040 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1015 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10411016
...@@ -1088,7 +1063,6 @@ test "comptime break operand passing through runtime condition converted to runt...@@ -1088,7 +1063,6 @@ test "comptime break operand passing through runtime condition converted to runt
1088}1063}
10891064
1090test "comptime break operand passing through runtime switch converted to runtime break" {1065test "comptime break operand passing through runtime switch converted to runtime break" {
1091 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1092 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1066 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10931067
1094 const S = struct {1068 const S = struct {
...@@ -1108,7 +1082,6 @@ test "comptime break operand passing through runtime switch converted to runtime...@@ -1108,7 +1082,6 @@ test "comptime break operand passing through runtime switch converted to runtime
1108}1082}
11091083
1110test "no dependency loop for alignment of self struct" {1084test "no dependency loop for alignment of self struct" {
1111 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1112 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1085 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1113 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1086 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1114 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1087 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1147,7 +1120,6 @@ test "no dependency loop for alignment of self struct" {...@@ -1147,7 +1120,6 @@ test "no dependency loop for alignment of self struct" {
1147}1120}
11481121
1149test "no dependency loop for alignment of self bare union" {1122test "no dependency loop for alignment of self bare union" {
1150 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1151 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1123 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1152 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1124 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1153 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1125 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1186,7 +1158,6 @@ test "no dependency loop for alignment of self bare union" {...@@ -1186,7 +1158,6 @@ test "no dependency loop for alignment of self bare union" {
1186}1158}
11871159
1188test "no dependency loop for alignment of self tagged union" {1160test "no dependency loop for alignment of self tagged union" {
1189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1190 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1191 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1162 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1192 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1230,7 +1201,6 @@ test "equality of pointers to comptime const" {...@@ -1230,7 +1201,6 @@ test "equality of pointers to comptime const" {
1230}1201}
12311202
1232test "storing an array of type in a field" {1203test "storing an array of type in a field" {
1233 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1234 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1235 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1236 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1206 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1260,7 +1230,6 @@ test "storing an array of type in a field" {...@@ -1260,7 +1230,6 @@ test "storing an array of type in a field" {
1260}1230}
12611231
1262test "pass pointer to field of comptime-only type as a runtime parameter" {1232test "pass pointer to field of comptime-only type as a runtime parameter" {
1263 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1265 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1234 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12661235
...@@ -1387,7 +1356,6 @@ test "lazy sizeof union tag size in compare" {...@@ -1387,7 +1356,6 @@ test "lazy sizeof union tag size in compare" {
1387}1356}
13881357
1389test "lazy value is resolved as slice operand" {1358test "lazy value is resolved as slice operand" {
1390 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1391 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1392 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1360 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1393 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1361 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1568,7 +1536,7 @@ test "x or true is comptime-known true" {...@@ -1568,7 +1536,7 @@ test "x or true is comptime-known true" {
1568}1536}
15691537
1570test "non-optional and optional array elements concatenated" {1538test "non-optional and optional array elements concatenated" {
1571 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1539 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1540 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1573 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1541 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15741542
test/behavior/export_builtin.zig-4
...@@ -4,7 +4,6 @@ const expect = std.testing.expect;...@@ -4,7 +4,6 @@ const expect = std.testing.expect;
44
5test "exporting enum value" {5test "exporting enum value" {
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
87
9 if (builtin.cpu.arch.isWasm()) {8 if (builtin.cpu.arch.isWasm()) {
10 // https://github.com/ziglang/zig/issues/48669 // https://github.com/ziglang/zig/issues/4866
...@@ -23,7 +22,6 @@ test "exporting enum value" {...@@ -23,7 +22,6 @@ test "exporting enum value" {
2322
24test "exporting with internal linkage" {23test "exporting with internal linkage" {
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
26 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2725
28 const S = struct {26 const S = struct {
29 fn foo() callconv(.c) void {}27 fn foo() callconv(.c) void {}
...@@ -36,7 +34,6 @@ test "exporting with internal linkage" {...@@ -36,7 +34,6 @@ test "exporting with internal linkage" {
3634
37test "exporting using namespace access" {35test "exporting using namespace access" {
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
4037
41 if (builtin.cpu.arch.isWasm()) {38 if (builtin.cpu.arch.isWasm()) {
42 // https://github.com/ziglang/zig/issues/486639 // https://github.com/ziglang/zig/issues/4866
...@@ -57,7 +54,6 @@ test "exporting using namespace access" {...@@ -57,7 +54,6 @@ test "exporting using namespace access" {
5754
58test "exporting comptime-known value" {55test "exporting comptime-known value" {
59 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;56 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
60 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
61 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;57 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
62 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;58 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
6359
test/behavior/field_parent_ptr.zig+5
...@@ -2,6 +2,7 @@ const expect = @import("std").testing.expect;...@@ -2,6 +2,7 @@ const expect = @import("std").testing.expect;
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4test "@fieldParentPtr struct" {4test "@fieldParentPtr struct" {
5 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
5 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
6 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
78
...@@ -586,6 +587,7 @@ test "@fieldParentPtr extern struct last zero-bit field" {...@@ -586,6 +587,7 @@ test "@fieldParentPtr extern struct last zero-bit field" {
586}587}
587588
588test "@fieldParentPtr unaligned packed struct" {589test "@fieldParentPtr unaligned packed struct" {
590 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
589 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;591 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
590 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;592 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
591 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;593 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -724,6 +726,7 @@ test "@fieldParentPtr unaligned packed struct" {...@@ -724,6 +726,7 @@ test "@fieldParentPtr unaligned packed struct" {
724}726}
725727
726test "@fieldParentPtr aligned packed struct" {728test "@fieldParentPtr aligned packed struct" {
729 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
727 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;730 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
728 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;731 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
729 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;732 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1339,6 +1342,7 @@ test "@fieldParentPtr packed struct last zero-bit field" {...@@ -1339,6 +1342,7 @@ test "@fieldParentPtr packed struct last zero-bit field" {
1339}1342}
13401343
1341test "@fieldParentPtr tagged union" {1344test "@fieldParentPtr tagged union" {
1345 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1342 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1346 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1343 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1347 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13441348
...@@ -1475,6 +1479,7 @@ test "@fieldParentPtr tagged union" {...@@ -1475,6 +1479,7 @@ test "@fieldParentPtr tagged union" {
1475}1479}
14761480
1477test "@fieldParentPtr untagged union" {1481test "@fieldParentPtr untagged union" {
1482 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1478 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1483 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1479 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1484 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14801485
test/behavior/floatop.zig+18-68
...@@ -143,7 +143,6 @@ test "cmp f64" {...@@ -143,7 +143,6 @@ test "cmp f64" {
143}143}
144144
145test "cmp f128" {145test "cmp f128" {
146 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
147 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO146 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
148 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;147 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
149 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;148 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -154,7 +153,6 @@ test "cmp f128" {...@@ -154,7 +153,6 @@ test "cmp f128" {
154}153}
155154
156test "cmp f80/c_longdouble" {155test "cmp f80/c_longdouble" {
157 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
158 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO156 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;157 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;158 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
...@@ -223,6 +221,7 @@ fn testCmp(comptime T: type) !void {...@@ -223,6 +221,7 @@ fn testCmp(comptime T: type) !void {
223}221}
224222
225test "vector cmp f16" {223test "vector cmp f16" {
224 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
226 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO225 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
227 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO226 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
228 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;227 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
...@@ -236,6 +235,7 @@ test "vector cmp f16" {...@@ -236,6 +235,7 @@ test "vector cmp f16" {
236}235}
237236
238test "vector cmp f32" {237test "vector cmp f32" {
238 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
239 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;239 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
240 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO240 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
241 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO241 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -249,6 +249,7 @@ test "vector cmp f32" {...@@ -249,6 +249,7 @@ test "vector cmp f32" {
249}249}
250250
251test "vector cmp f64" {251test "vector cmp f64" {
252 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
252 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO253 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
253 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO254 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
254 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;255 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -261,8 +262,8 @@ test "vector cmp f64" {...@@ -261,8 +262,8 @@ test "vector cmp f64" {
261}262}
262263
263test "vector cmp f128" {264test "vector cmp f128" {
265 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
264 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO266 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
265 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
266 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO267 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
267 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;268 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
268 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;269 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -276,6 +277,7 @@ test "vector cmp f128" {...@@ -276,6 +277,7 @@ test "vector cmp f128" {
276}277}
277278
278test "vector cmp f80/c_longdouble" {279test "vector cmp f80/c_longdouble" {
280 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
279 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;281 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
280 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest;282 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest;
281 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;283 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -324,7 +326,6 @@ fn testCmpVector(comptime T: type) !void {...@@ -324,7 +326,6 @@ fn testCmpVector(comptime T: type) !void {
324326
325test "different sized float comparisons" {327test "different sized float comparisons" {
326 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
327 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
328 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO329 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
329 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;330 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
330331
...@@ -371,7 +372,6 @@ test "negative f128 intFromFloat at compile-time" {...@@ -371,7 +372,6 @@ test "negative f128 intFromFloat at compile-time" {
371372
372test "@sqrt f16" {373test "@sqrt f16" {
373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO374 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
375 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO375 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
376 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;376 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
377 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;377 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -382,7 +382,6 @@ test "@sqrt f16" {...@@ -382,7 +382,6 @@ test "@sqrt f16" {
382382
383test "@sqrt f32/f64" {383test "@sqrt f32/f64" {
384 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO384 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
385 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
386 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO385 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
387 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;386 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
388387
...@@ -394,7 +393,6 @@ test "@sqrt f32/f64" {...@@ -394,7 +393,6 @@ test "@sqrt f32/f64" {
394393
395test "@sqrt f80/f128/c_longdouble" {394test "@sqrt f80/f128/c_longdouble" {
396 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO395 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
397 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
398 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
399 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;397 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
400 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;398 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -481,9 +479,9 @@ fn testSqrt(comptime T: type) !void {...@@ -481,9 +479,9 @@ fn testSqrt(comptime T: type) !void {
481}479}
482480
483test "@sqrt with vectors" {481test "@sqrt with vectors" {
482 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
484 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO483 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
485 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO484 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
486 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
487 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;485 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
488 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;486 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
489487
...@@ -503,7 +501,6 @@ fn testSqrtWithVectors() !void {...@@ -503,7 +501,6 @@ fn testSqrtWithVectors() !void {
503501
504test "@sin f16" {502test "@sin f16" {
505 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO503 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO504 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;505 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
509 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;506 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -514,7 +511,6 @@ test "@sin f16" {...@@ -514,7 +511,6 @@ test "@sin f16" {
514511
515test "@sin f32/f64" {512test "@sin f32/f64" {
516 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO513 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
517 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
518 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
519 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;515 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
520 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;516 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -527,7 +523,6 @@ test "@sin f32/f64" {...@@ -527,7 +523,6 @@ test "@sin f32/f64" {
527523
528test "@sin f80/f128/c_longdouble" {524test "@sin f80/f128/c_longdouble" {
529 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO525 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
530 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
531 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO526 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
532 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;527 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
533 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;528 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -554,9 +549,9 @@ fn testSin(comptime T: type) !void {...@@ -554,9 +549,9 @@ fn testSin(comptime T: type) !void {
554}549}
555550
556test "@sin with vectors" {551test "@sin with vectors" {
552 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
557 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO553 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
558 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO554 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
559 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
560 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;555 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
561 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;556 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
562557
...@@ -576,7 +571,6 @@ fn testSinWithVectors() !void {...@@ -576,7 +571,6 @@ fn testSinWithVectors() !void {
576571
577test "@cos f16" {572test "@cos f16" {
578 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO573 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
579 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
580 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO574 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
581 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;575 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
582 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;576 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -587,7 +581,6 @@ test "@cos f16" {...@@ -587,7 +581,6 @@ test "@cos f16" {
587581
588test "@cos f32/f64" {582test "@cos f32/f64" {
589 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO583 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
590 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
591 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO584 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
592 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;585 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
593 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;586 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -600,7 +593,6 @@ test "@cos f32/f64" {...@@ -600,7 +593,6 @@ test "@cos f32/f64" {
600593
601test "@cos f80/f128/c_longdouble" {594test "@cos f80/f128/c_longdouble" {
602 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO595 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
603 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
604 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO596 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
605 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;597 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
606 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;598 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -627,9 +619,9 @@ fn testCos(comptime T: type) !void {...@@ -627,9 +619,9 @@ fn testCos(comptime T: type) !void {
627}619}
628620
629test "@cos with vectors" {621test "@cos with vectors" {
622 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
630 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO623 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
631 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO624 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
632 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
633 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;625 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
634 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;626 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
635627
...@@ -649,7 +641,6 @@ fn testCosWithVectors() !void {...@@ -649,7 +641,6 @@ fn testCosWithVectors() !void {
649641
650test "@tan f16" {642test "@tan f16" {
651 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO643 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
652 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
653 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO644 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
654 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;645 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
655 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;646 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -660,7 +651,6 @@ test "@tan f16" {...@@ -660,7 +651,6 @@ test "@tan f16" {
660651
661test "@tan f32/f64" {652test "@tan f32/f64" {
662 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO653 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
663 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
664 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO654 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
665 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;655 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
666 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;656 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -673,7 +663,6 @@ test "@tan f32/f64" {...@@ -673,7 +663,6 @@ test "@tan f32/f64" {
673663
674test "@tan f80/f128/c_longdouble" {664test "@tan f80/f128/c_longdouble" {
675 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO665 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
676 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
677 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO666 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
678 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;667 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
679 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;668 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -700,9 +689,9 @@ fn testTan(comptime T: type) !void {...@@ -700,9 +689,9 @@ fn testTan(comptime T: type) !void {
700}689}
701690
702test "@tan with vectors" {691test "@tan with vectors" {
692 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
703 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO693 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
704 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO694 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
705 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
706 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;695 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
707 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;696 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
708697
...@@ -722,7 +711,6 @@ fn testTanWithVectors() !void {...@@ -722,7 +711,6 @@ fn testTanWithVectors() !void {
722711
723test "@exp f16" {712test "@exp f16" {
724 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO713 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
725 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
726 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO714 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
727 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;715 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
728 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;716 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -733,7 +721,6 @@ test "@exp f16" {...@@ -733,7 +721,6 @@ test "@exp f16" {
733721
734test "@exp f32/f64" {722test "@exp f32/f64" {
735 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO723 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
736 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
737 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO724 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
738 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;725 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
739 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;726 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -746,7 +733,6 @@ test "@exp f32/f64" {...@@ -746,7 +733,6 @@ test "@exp f32/f64" {
746733
747test "@exp f80/f128/c_longdouble" {734test "@exp f80/f128/c_longdouble" {
748 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO735 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
749 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
750 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO736 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
751 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;737 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
752 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;738 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -777,9 +763,9 @@ fn testExp(comptime T: type) !void {...@@ -777,9 +763,9 @@ fn testExp(comptime T: type) !void {
777}763}
778764
779test "@exp with vectors" {765test "@exp with vectors" {
766 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
780 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO767 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
781 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO768 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
782 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
783 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;769 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
784 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;770 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
785771
...@@ -799,7 +785,6 @@ fn testExpWithVectors() !void {...@@ -799,7 +785,6 @@ fn testExpWithVectors() !void {
799785
800test "@exp2 f16" {786test "@exp2 f16" {
801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO787 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO788 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
804 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;789 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
805 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;790 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -810,7 +795,6 @@ test "@exp2 f16" {...@@ -810,7 +795,6 @@ test "@exp2 f16" {
810795
811test "@exp2 f32/f64" {796test "@exp2 f32/f64" {
812 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO797 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
813 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
814 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO798 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
815 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;799 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
816 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;800 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -823,7 +807,6 @@ test "@exp2 f32/f64" {...@@ -823,7 +807,6 @@ test "@exp2 f32/f64" {
823807
824test "@exp2 f80/f128/c_longdouble" {808test "@exp2 f80/f128/c_longdouble" {
825 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO809 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
826 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
827 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO810 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
828 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;811 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
829 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;812 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -849,9 +832,9 @@ fn testExp2(comptime T: type) !void {...@@ -849,9 +832,9 @@ fn testExp2(comptime T: type) !void {
849}832}
850833
851test "@exp2 with @vectors" {834test "@exp2 with @vectors" {
835 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
852 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO836 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
853 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO837 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
854 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
855 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;838 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
856 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;839 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
857840
...@@ -870,7 +853,6 @@ fn testExp2WithVectors() !void {...@@ -870,7 +853,6 @@ fn testExp2WithVectors() !void {
870}853}
871854
872test "@log f16" {855test "@log f16" {
873 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
874 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO856 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
875 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO857 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
876 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;858 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -881,7 +863,6 @@ test "@log f16" {...@@ -881,7 +863,6 @@ test "@log f16" {
881}863}
882864
883test "@log f32/f64" {865test "@log f32/f64" {
884 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
885 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO866 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
886 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO867 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
887 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;868 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -894,7 +875,6 @@ test "@log f32/f64" {...@@ -894,7 +875,6 @@ test "@log f32/f64" {
894}875}
895876
896test "@log f80/f128/c_longdouble" {877test "@log f80/f128/c_longdouble" {
897 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
898 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO878 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
899 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO879 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
900 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;880 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -921,8 +901,8 @@ fn testLog(comptime T: type) !void {...@@ -921,8 +901,8 @@ fn testLog(comptime T: type) !void {
921}901}
922902
923test "@log with @vectors" {903test "@log with @vectors" {
904 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
924 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO905 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
925 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
926 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO906 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
927 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO907 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
928 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;908 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -940,7 +920,6 @@ test "@log with @vectors" {...@@ -940,7 +920,6 @@ test "@log with @vectors" {
940}920}
941921
942test "@log2 f16" {922test "@log2 f16" {
943 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
944 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO923 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
945 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO924 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
946 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;925 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -951,7 +930,6 @@ test "@log2 f16" {...@@ -951,7 +930,6 @@ test "@log2 f16" {
951}930}
952931
953test "@log2 f32/f64" {932test "@log2 f32/f64" {
954 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
955 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO933 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
956 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO934 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
957 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;935 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -964,7 +942,6 @@ test "@log2 f32/f64" {...@@ -964,7 +942,6 @@ test "@log2 f32/f64" {
964}942}
965943
966test "@log2 f80/f128/c_longdouble" {944test "@log2 f80/f128/c_longdouble" {
967 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
968 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO945 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
969 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO946 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
970 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;947 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -991,8 +968,8 @@ fn testLog2(comptime T: type) !void {...@@ -991,8 +968,8 @@ fn testLog2(comptime T: type) !void {
991}968}
992969
993test "@log2 with vectors" {970test "@log2 with vectors" {
971 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
994 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO972 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
995 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
996 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO973 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
997 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;974 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
998 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;975 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1016,7 +993,6 @@ fn testLog2WithVectors() !void {...@@ -1016,7 +993,6 @@ fn testLog2WithVectors() !void {
1016}993}
1017994
1018test "@log10 f16" {995test "@log10 f16" {
1019 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1020 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO996 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1021 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO997 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1022 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;998 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1027,7 +1003,6 @@ test "@log10 f16" {...@@ -1027,7 +1003,6 @@ test "@log10 f16" {
1027}1003}
10281004
1029test "@log10 f32/f64" {1005test "@log10 f32/f64" {
1030 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1031 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1006 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1032 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1007 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1033 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1008 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1040,7 +1015,6 @@ test "@log10 f32/f64" {...@@ -1040,7 +1015,6 @@ test "@log10 f32/f64" {
1040}1015}
10411016
1042test "@log10 f80/f128/c_longdouble" {1017test "@log10 f80/f128/c_longdouble" {
1043 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1044 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1018 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1045 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1019 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1046 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1020 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1067,8 +1041,8 @@ fn testLog10(comptime T: type) !void {...@@ -1067,8 +1041,8 @@ fn testLog10(comptime T: type) !void {
1067}1041}
10681042
1069test "@log10 with vectors" {1043test "@log10 with vectors" {
1044 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1070 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1045 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1071 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1072 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1046 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1073 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1047 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1074 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1048 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1089,7 +1063,6 @@ fn testLog10WithVectors() !void {...@@ -1089,7 +1063,6 @@ fn testLog10WithVectors() !void {
10891063
1090test "@abs f16" {1064test "@abs f16" {
1091 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1065 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1092 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1093 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1066 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1094 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1067 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10951068
...@@ -1099,7 +1072,6 @@ test "@abs f16" {...@@ -1099,7 +1072,6 @@ test "@abs f16" {
10991072
1100test "@abs f32/f64" {1073test "@abs f32/f64" {
1101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1074 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1075 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11041076
1105 try testFabs(f32);1077 try testFabs(f32);
...@@ -1110,7 +1082,6 @@ test "@abs f32/f64" {...@@ -1110,7 +1082,6 @@ test "@abs f32/f64" {
11101082
1111test "@abs f80/f128/c_longdouble" {1083test "@abs f80/f128/c_longdouble" {
1112 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1084 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1114 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;1085 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1086 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1116 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1087 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1190,7 +1161,7 @@ fn testFabs(comptime T: type) !void {...@@ -1190,7 +1161,7 @@ fn testFabs(comptime T: type) !void {
1190}1161}
11911162
1192test "@abs with vectors" {1163test "@abs with vectors" {
1193 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1164 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1194 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1165 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1195 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1166 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1196 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1167 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1210,7 +1181,6 @@ fn testFabsWithVectors() !void {...@@ -1210,7 +1181,6 @@ fn testFabsWithVectors() !void {
1210}1181}
12111182
1212test "@floor f16" {1183test "@floor f16" {
1213 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1214 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1184 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1185 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1216 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1186 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1220,7 +1190,6 @@ test "@floor f16" {...@@ -1220,7 +1190,6 @@ test "@floor f16" {
1220}1190}
12211191
1222test "@floor f32/f64" {1192test "@floor f32/f64" {
1223 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1224 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1193 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1225 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1194 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1226 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1195 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1232,7 +1201,6 @@ test "@floor f32/f64" {...@@ -1232,7 +1201,6 @@ test "@floor f32/f64" {
1232}1201}
12331202
1234test "@floor f80/f128/c_longdouble" {1203test "@floor f80/f128/c_longdouble" {
1235 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1236 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1237 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;1205 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1206 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1284,7 +1252,7 @@ fn testFloor(comptime T: type) !void {...@@ -1284,7 +1252,7 @@ fn testFloor(comptime T: type) !void {
1284}1252}
12851253
1286test "@floor with vectors" {1254test "@floor with vectors" {
1287 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1255 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1288 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1289 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1257 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1290 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1258 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1304,7 +1272,6 @@ fn testFloorWithVectors() !void {...@@ -1304,7 +1272,6 @@ fn testFloorWithVectors() !void {
1304}1272}
13051273
1306test "@ceil f16" {1274test "@ceil f16" {
1307 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1308 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1275 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1309 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1276 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1310 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1277 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1314,7 +1281,6 @@ test "@ceil f16" {...@@ -1314,7 +1281,6 @@ test "@ceil f16" {
1314}1281}
13151282
1316test "@ceil f32/f64" {1283test "@ceil f32/f64" {
1317 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1318 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1284 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1319 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1285 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1320 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1286 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1326,7 +1292,6 @@ test "@ceil f32/f64" {...@@ -1326,7 +1292,6 @@ test "@ceil f32/f64" {
1326}1292}
13271293
1328test "@ceil f80/f128/c_longdouble" {1294test "@ceil f80/f128/c_longdouble" {
1329 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1330 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1295 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1331 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;1296 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1332 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1297 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1378,7 +1343,7 @@ fn testCeil(comptime T: type) !void {...@@ -1378,7 +1343,7 @@ fn testCeil(comptime T: type) !void {
1378}1343}
13791344
1380test "@ceil with vectors" {1345test "@ceil with vectors" {
1381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1346 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1382 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1347 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1383 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1348 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1384 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1349 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1398,7 +1363,6 @@ fn testCeilWithVectors() !void {...@@ -1398,7 +1363,6 @@ fn testCeilWithVectors() !void {
1398}1363}
13991364
1400test "@trunc f16" {1365test "@trunc f16" {
1401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1402 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1366 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1403 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1367 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1404 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1368 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1408,7 +1372,6 @@ test "@trunc f16" {...@@ -1408,7 +1372,6 @@ test "@trunc f16" {
1408}1372}
14091373
1410test "@trunc f32/f64" {1374test "@trunc f32/f64" {
1411 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1412 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1375 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1413 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1376 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1414 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1377 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1420,7 +1383,6 @@ test "@trunc f32/f64" {...@@ -1420,7 +1383,6 @@ test "@trunc f32/f64" {
1420}1383}
14211384
1422test "@trunc f80/f128/c_longdouble" {1385test "@trunc f80/f128/c_longdouble" {
1423 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1424 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1386 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1425 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;1387 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
1426 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1388 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1472,7 +1434,7 @@ fn testTrunc(comptime T: type) !void {...@@ -1472,7 +1434,7 @@ fn testTrunc(comptime T: type) !void {
1472}1434}
14731435
1474test "@trunc with vectors" {1436test "@trunc with vectors" {
1475 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1437 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1438 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1477 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1439 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1478 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1440 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1492,7 +1454,6 @@ fn testTruncWithVectors() !void {...@@ -1492,7 +1454,6 @@ fn testTruncWithVectors() !void {
1492}1454}
14931455
1494test "neg f16" {1456test "neg f16" {
1495 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1496 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1457 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1497 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1458 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1498 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1459 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1508,7 +1469,6 @@ test "neg f16" {...@@ -1508,7 +1469,6 @@ test "neg f16" {
1508}1469}
15091470
1510test "neg f32/f64" {1471test "neg f32/f64" {
1511 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1512 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1513 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1473 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1514 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1474 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1520,7 +1480,6 @@ test "neg f32/f64" {...@@ -1520,7 +1480,6 @@ test "neg f32/f64" {
1520}1480}
15211481
1522test "neg f80/f128/c_longdouble" {1482test "neg f80/f128/c_longdouble" {
1523 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1524 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1483 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1525 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1484 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1526 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1485 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1606,7 +1565,6 @@ fn testNeg(comptime T: type) !void {...@@ -1606,7 +1565,6 @@ fn testNeg(comptime T: type) !void {
1606}1565}
16071566
1608test "eval @setFloatMode at compile-time" {1567test "eval @setFloatMode at compile-time" {
1609 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1610 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1568 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16111569
1612 const result = comptime fnWithFloatMode();1570 const result = comptime fnWithFloatMode();
...@@ -1629,7 +1587,6 @@ test "f128 at compile time is lossy" {...@@ -1629,7 +1587,6 @@ test "f128 at compile time is lossy" {
16291587
1630test "comptime fixed-width float zero divided by zero produces NaN" {1588test "comptime fixed-width float zero divided by zero produces NaN" {
1631 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1589 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1632 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1633 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1590 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1634 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1591 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1635 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1592 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1641,7 +1598,6 @@ test "comptime fixed-width float zero divided by zero produces NaN" {...@@ -1641,7 +1598,6 @@ test "comptime fixed-width float zero divided by zero produces NaN" {
16411598
1642test "comptime fixed-width float non-zero divided by zero produces signed Inf" {1599test "comptime fixed-width float non-zero divided by zero produces signed Inf" {
1643 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1600 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1644 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1645 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1601 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1646 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1602 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16471603
...@@ -1686,21 +1642,18 @@ test "comptime inf >= runtime 1" {...@@ -1686,21 +1642,18 @@ test "comptime inf >= runtime 1" {
1686 try std.testing.expect(f >= i);1642 try std.testing.expect(f >= i);
1687}1643}
1688test "comptime isNan(nan * 1)" {1644test "comptime isNan(nan * 1)" {
1689 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1690 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1645 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16911646
1692 const nan_times_one = comptime std.math.nan(f64) * 1;1647 const nan_times_one = comptime std.math.nan(f64) * 1;
1693 try std.testing.expect(std.math.isNan(nan_times_one));1648 try std.testing.expect(std.math.isNan(nan_times_one));
1694}1649}
1695test "runtime isNan(nan * 1)" {1650test "runtime isNan(nan * 1)" {
1696 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1697 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1651 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16981652
1699 const nan_times_one = std.math.nan(f64) * 1;1653 const nan_times_one = std.math.nan(f64) * 1;
1700 try std.testing.expect(std.math.isNan(nan_times_one));1654 try std.testing.expect(std.math.isNan(nan_times_one));
1701}1655}
1702test "comptime isNan(nan * 0)" {1656test "comptime isNan(nan * 0)" {
1703 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1704 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1657 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17051658
1706 const nan_times_zero = comptime std.math.nan(f64) * 0;1659 const nan_times_zero = comptime std.math.nan(f64) * 0;
...@@ -1709,7 +1662,6 @@ test "comptime isNan(nan * 0)" {...@@ -1709,7 +1662,6 @@ test "comptime isNan(nan * 0)" {
1709 try std.testing.expect(std.math.isNan(zero_times_nan));1662 try std.testing.expect(std.math.isNan(zero_times_nan));
1710}1663}
1711test "runtime isNan(nan * 0)" {1664test "runtime isNan(nan * 0)" {
1712 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1713 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1665 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17141666
1715 const nan_times_zero = std.math.nan(f64) * 0;1667 const nan_times_zero = std.math.nan(f64) * 0;
...@@ -1718,7 +1670,6 @@ test "runtime isNan(nan * 0)" {...@@ -1718,7 +1670,6 @@ test "runtime isNan(nan * 0)" {
1718 try std.testing.expect(std.math.isNan(zero_times_nan));1670 try std.testing.expect(std.math.isNan(zero_times_nan));
1719}1671}
1720test "comptime isNan(inf * 0)" {1672test "comptime isNan(inf * 0)" {
1721 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1722 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1673 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17231674
1724 const inf_times_zero = comptime std.math.inf(f64) * 0;1675 const inf_times_zero = comptime std.math.inf(f64) * 0;
...@@ -1727,7 +1678,6 @@ test "comptime isNan(inf * 0)" {...@@ -1727,7 +1678,6 @@ test "comptime isNan(inf * 0)" {
1727 try std.testing.expect(std.math.isNan(zero_times_inf));1678 try std.testing.expect(std.math.isNan(zero_times_inf));
1728}1679}
1729test "runtime isNan(inf * 0)" {1680test "runtime isNan(inf * 0)" {
1730 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1681 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17321682
1733 const inf_times_zero = std.math.inf(f64) * 0;1683 const inf_times_zero = std.math.inf(f64) * 0;
test/behavior/fn.zig-13
...@@ -78,7 +78,6 @@ test "return inner function which references comptime variable of outer function...@@ -78,7 +78,6 @@ test "return inner function which references comptime variable of outer function
7878
79test "discard the result of a function that returns a struct" {79test "discard the result of a function that returns a struct" {
80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
81 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
82 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO81 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8382
84 const S = struct {83 const S = struct {
...@@ -101,7 +100,6 @@ test "discard the result of a function that returns a struct" {...@@ -101,7 +100,6 @@ test "discard the result of a function that returns a struct" {
101100
102test "inline function call that calls optional function pointer, return pointer at callsite interacts correctly with callsite return type" {101test "inline function call that calls optional function pointer, return pointer at callsite interacts correctly with callsite return type" {
103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
104 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
105 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
106 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;104 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
107105
...@@ -179,7 +177,6 @@ fn fComplexCallconvRet(x: u32) callconv(blk: {...@@ -179,7 +177,6 @@ fn fComplexCallconvRet(x: u32) callconv(blk: {
179177
180test "function with complex callconv and return type expressions" {178test "function with complex callconv and return type expressions" {
181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;179 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO180 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
184181
185 try expect(fComplexCallconvRet(3).x == 9);182 try expect(fComplexCallconvRet(3).x == 9);
...@@ -255,7 +252,6 @@ test "pass by non-copying value as method, at comptime" {...@@ -255,7 +252,6 @@ test "pass by non-copying value as method, at comptime" {
255252
256test "implicit cast fn call result to optional in field result" {253test "implicit cast fn call result to optional in field result" {
257 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;254 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
258 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO255 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;256 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
261257
...@@ -283,7 +279,6 @@ test "implicit cast fn call result to optional in field result" {...@@ -283,7 +279,6 @@ test "implicit cast fn call result to optional in field result" {
283279
284test "void parameters" {280test "void parameters" {
285 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;281 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
286 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
287282
288 try voidFun(1, void{}, 2, {});283 try voidFun(1, void{}, 2, {});
289}284}
...@@ -306,7 +301,6 @@ fn acceptsString(foo: []u8) void {...@@ -306,7 +301,6 @@ fn acceptsString(foo: []u8) void {
306}301}
307302
308test "function pointers" {303test "function pointers" {
309 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
310 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
311 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
312 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;306 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -345,7 +339,6 @@ fn numberLiteralArg(a: anytype) !void {...@@ -345,7 +339,6 @@ fn numberLiteralArg(a: anytype) !void {
345339
346test "function call with anon list literal" {340test "function call with anon list literal" {
347 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
348 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
349 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
350343
351 const S = struct {344 const S = struct {
...@@ -365,7 +358,6 @@ test "function call with anon list literal" {...@@ -365,7 +358,6 @@ test "function call with anon list literal" {
365358
366test "function call with anon list literal - 2D" {359test "function call with anon list literal - 2D" {
367 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO360 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
368 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
369 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO361 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
370362
371 const S = struct {363 const S = struct {
...@@ -426,7 +418,6 @@ test "import passed byref to function in return type" {...@@ -426,7 +418,6 @@ test "import passed byref to function in return type" {
426418
427test "implicit cast function to function ptr" {419test "implicit cast function to function ptr" {
428 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
430 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO421 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
431 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;422 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
432423
...@@ -485,7 +476,6 @@ test "method call with optional pointer first param" {...@@ -485,7 +476,6 @@ test "method call with optional pointer first param" {
485476
486test "using @ptrCast on function pointers" {477test "using @ptrCast on function pointers" {
487 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO478 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
488 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
489 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO479 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;480 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
491481
...@@ -524,8 +514,6 @@ test "function returns function returning type" {...@@ -524,8 +514,6 @@ test "function returns function returning type" {
524}514}
525515
526test "peer type resolution of inferred error set with non-void payload" {516test "peer type resolution of inferred error set with non-void payload" {
527 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
528
529 const S = struct {517 const S = struct {
530 fn openDataFile(mode: enum { read, write }) !u32 {518 fn openDataFile(mode: enum { read, write }) !u32 {
531 return switch (mode) {519 return switch (mode) {
...@@ -582,7 +570,6 @@ test "pass and return comptime-only types" {...@@ -582,7 +570,6 @@ test "pass and return comptime-only types" {
582570
583test "pointer to alias behaves same as pointer to function" {571test "pointer to alias behaves same as pointer to function" {
584 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
585 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
586 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;573 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
587574
588 const S = struct {575 const S = struct {
test/behavior/for.zig-20
...@@ -5,7 +5,6 @@ const expectEqual = std.testing.expectEqual;...@@ -5,7 +5,6 @@ const expectEqual = std.testing.expectEqual;
5const mem = std.mem;5const mem = std.mem;
66
7test "continue in for loop" {7test "continue in for loop" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
109
11 const array = [_]i32{ 1, 2, 3, 4, 5 };10 const array = [_]i32{ 1, 2, 3, 4, 5 };
...@@ -67,7 +66,6 @@ test "ignore lval with underscore (for loop)" {...@@ -67,7 +66,6 @@ test "ignore lval with underscore (for loop)" {
6766
68test "basic for loop" {67test "basic for loop" {
69 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
70 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;70 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
7371
...@@ -111,7 +109,6 @@ test "basic for loop" {...@@ -111,7 +109,6 @@ test "basic for loop" {
111109
112test "for with null and T peer types and inferred result location type" {110test "for with null and T peer types and inferred result location type" {
113 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;111 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO112 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
116 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;113 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
117114
...@@ -132,7 +129,6 @@ test "for with null and T peer types and inferred result location type" {...@@ -132,7 +129,6 @@ test "for with null and T peer types and inferred result location type" {
132}129}
133130
134test "2 break statements and an else" {131test "2 break statements and an else" {
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO132 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
137133
138 const S = struct {134 const S = struct {
...@@ -152,7 +148,6 @@ test "2 break statements and an else" {...@@ -152,7 +148,6 @@ test "2 break statements and an else" {
152}148}
153149
154test "for loop with pointer elem var" {150test "for loop with pointer elem var" {
155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
157 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO152 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
158 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;153 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -180,7 +175,6 @@ fn mangleString(s: []u8) void {...@@ -180,7 +175,6 @@ fn mangleString(s: []u8) void {
180}175}
181176
182test "for copies its payload" {177test "for copies its payload" {
183 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
184 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO178 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
185179
186 const S = struct {180 const S = struct {
...@@ -198,7 +192,6 @@ test "for copies its payload" {...@@ -198,7 +192,6 @@ test "for copies its payload" {
198}192}
199193
200test "for on slice with allowzero ptr" {194test "for on slice with allowzero ptr" {
201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO195 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO196 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;197 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -215,7 +208,6 @@ test "for on slice with allowzero ptr" {...@@ -215,7 +208,6 @@ test "for on slice with allowzero ptr" {
215}208}
216209
217test "else continue outer for" {210test "else continue outer for" {
218 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
219 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO211 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
220 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;212 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
221213
...@@ -230,8 +222,6 @@ test "else continue outer for" {...@@ -230,8 +222,6 @@ test "else continue outer for" {
230}222}
231223
232test "for loop with else branch" {224test "for loop with else branch" {
233 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
234
235 {225 {
236 var x = [_]u32{ 1, 2 };226 var x = [_]u32{ 1, 2 };
237 _ = &x;227 _ = &x;
...@@ -312,7 +302,6 @@ test "1-based counter and ptr to array" {...@@ -312,7 +302,6 @@ test "1-based counter and ptr to array" {
312test "slice and two counters, one is offset and one is runtime" {302test "slice and two counters, one is offset and one is runtime" {
313 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
314 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
316 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;305 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
317306
318 const slice: []const u8 = "blah";307 const slice: []const u8 = "blah";
...@@ -342,7 +331,6 @@ test "slice and two counters, one is offset and one is runtime" {...@@ -342,7 +331,6 @@ test "slice and two counters, one is offset and one is runtime" {
342test "two slices, one captured by-ref" {331test "two slices, one captured by-ref" {
343 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO332 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
344 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO333 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
345 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
346 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;334 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
347335
348 var buf: [10]u8 = undefined;336 var buf: [10]u8 = undefined;
...@@ -362,7 +350,6 @@ test "two slices, one captured by-ref" {...@@ -362,7 +350,6 @@ test "two slices, one captured by-ref" {
362test "raw pointer and slice" {350test "raw pointer and slice" {
363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO351 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO352 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
365 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
366 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;353 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
367354
368 var buf: [10]u8 = undefined;355 var buf: [10]u8 = undefined;
...@@ -382,7 +369,6 @@ test "raw pointer and slice" {...@@ -382,7 +369,6 @@ test "raw pointer and slice" {
382test "raw pointer and counter" {369test "raw pointer and counter" {
383 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO370 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
384 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO371 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
385 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
386 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;372 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
387373
388 var buf: [10]u8 = undefined;374 var buf: [10]u8 = undefined;
...@@ -401,7 +387,6 @@ test "raw pointer and counter" {...@@ -401,7 +387,6 @@ test "raw pointer and counter" {
401test "inline for with slice as the comptime-known" {387test "inline for with slice as the comptime-known" {
402 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO388 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
403 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO389 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
405390
406 const comptime_slice = "hello";391 const comptime_slice = "hello";
407 var runtime_i: usize = 3;392 var runtime_i: usize = 3;
...@@ -432,7 +417,6 @@ test "inline for with slice as the comptime-known" {...@@ -432,7 +417,6 @@ test "inline for with slice as the comptime-known" {
432test "inline for with counter as the comptime-known" {417test "inline for with counter as the comptime-known" {
433 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO418 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
434 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO419 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
435 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
436 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;420 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
437421
438 var runtime_slice = "hello";422 var runtime_slice = "hello";
...@@ -464,7 +448,6 @@ test "inline for with counter as the comptime-known" {...@@ -464,7 +448,6 @@ test "inline for with counter as the comptime-known" {
464test "inline for on tuple pointer" {448test "inline for on tuple pointer" {
465 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO449 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
466 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO450 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
467 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
468 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;451 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
469452
470 const S = struct { u32, u32, u32 };453 const S = struct { u32, u32, u32 };
...@@ -480,7 +463,6 @@ test "inline for on tuple pointer" {...@@ -480,7 +463,6 @@ test "inline for on tuple pointer" {
480test "ref counter that starts at zero" {463test "ref counter that starts at zero" {
481 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO464 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
482 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO465 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
483 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
484466
485 for ([_]usize{ 0, 1, 2 }, 0..) |i, j| {467 for ([_]usize{ 0, 1, 2 }, 0..) |i, j| {
486 try expectEqual(i, j);468 try expectEqual(i, j);
...@@ -495,7 +477,6 @@ test "ref counter that starts at zero" {...@@ -495,7 +477,6 @@ test "ref counter that starts at zero" {
495test "inferred alloc ptr of for loop" {477test "inferred alloc ptr of for loop" {
496 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO478 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
497 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO479 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
499480
500 {481 {
501 var cond = false;482 var cond = false;
...@@ -516,7 +497,6 @@ test "inferred alloc ptr of for loop" {...@@ -516,7 +497,6 @@ test "inferred alloc ptr of for loop" {
516}497}
517498
518test "for loop results in a bool" {499test "for loop results in a bool" {
519 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
520 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO500 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
521501
522 try std.testing.expect(for ([1]u8{0}) |x| {502 try std.testing.expect(for ([1]u8{0}) |x| {
test/behavior/generics.zig+1-18
...@@ -17,7 +17,6 @@ fn checkSize(comptime T: type) usize {...@@ -17,7 +17,6 @@ fn checkSize(comptime T: type) usize {
17}17}
1818
19test "simple generic fn" {19test "simple generic fn" {
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO20 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2221
23 try expect(max(i32, 3, -1) == 3);22 try expect(max(i32, 3, -1) == 3);
...@@ -53,7 +52,6 @@ fn sameButWithFloats(a: f64, b: f64) f64 {...@@ -53,7 +52,6 @@ fn sameButWithFloats(a: f64, b: f64) f64 {
5352
54test "fn with comptime args" {53test "fn with comptime args" {
55 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;54 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
56 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
57 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5856
59 try expect(gimmeTheBigOne(1234, 5678) == 5678);57 try expect(gimmeTheBigOne(1234, 5678) == 5678);
...@@ -63,7 +61,6 @@ test "fn with comptime args" {...@@ -63,7 +61,6 @@ test "fn with comptime args" {
6361
64test "anytype params" {62test "anytype params" {
65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;63 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
67 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO64 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
6865
69 try expect(max_i32(12, 34) == 34);66 try expect(max_i32(12, 34) == 34);
...@@ -87,7 +84,6 @@ fn max_f64(a: f64, b: f64) f64 {...@@ -87,7 +84,6 @@ fn max_f64(a: f64, b: f64) f64 {
87}84}
8885
89test "type constructed by comptime function call" {86test "type constructed by comptime function call" {
90 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
91 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
92 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;88 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
93 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;89 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -113,7 +109,6 @@ fn SimpleList(comptime L: usize) type {...@@ -113,7 +109,6 @@ fn SimpleList(comptime L: usize) type {
113109
114test "function with return type type" {110test "function with return type type" {
115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;111 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
116 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
117 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO112 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
118113
119 var list: List(i32) = undefined;114 var list: List(i32) = undefined;
...@@ -154,7 +149,6 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) T {...@@ -154,7 +149,6 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
154149
155test "generic fn with implicit cast" {150test "generic fn with implicit cast" {
156 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
157 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO152 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;153 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
160154
...@@ -173,7 +167,6 @@ fn getFirstByte(comptime T: type, mem: []const T) u8 {...@@ -173,7 +167,6 @@ fn getFirstByte(comptime T: type, mem: []const T) u8 {
173167
174test "generic fn keeps non-generic parameter types" {168test "generic fn keeps non-generic parameter types" {
175 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;169 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
176 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
177 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
178 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;171 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
179172
...@@ -249,7 +242,6 @@ test "function parameter is generic" {...@@ -249,7 +242,6 @@ test "function parameter is generic" {
249}242}
250243
251test "generic function instantiation turns into comptime call" {244test "generic function instantiation turns into comptime call" {
252 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
253 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO245 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
254 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO246 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
255 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;247 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -300,7 +292,6 @@ test "generic function with void and comptime parameter" {...@@ -300,7 +292,6 @@ test "generic function with void and comptime parameter" {
300}292}
301293
302test "anonymous struct return type referencing comptime parameter" {294test "anonymous struct return type referencing comptime parameter" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO295 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
305296
306 const S = struct {297 const S = struct {
...@@ -318,7 +309,6 @@ test "anonymous struct return type referencing comptime parameter" {...@@ -318,7 +309,6 @@ test "anonymous struct return type referencing comptime parameter" {
318309
319test "generic function instantiation non-duplicates" {310test "generic function instantiation non-duplicates" {
320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO311 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
321 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
322 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
323 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;313 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
324314
...@@ -339,7 +329,6 @@ test "generic function instantiation non-duplicates" {...@@ -339,7 +329,6 @@ test "generic function instantiation non-duplicates" {
339329
340test "generic instantiation of tagged union with only one field" {330test "generic instantiation of tagged union with only one field" {
341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO331 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
343332
344 if (builtin.os.tag == .wasi) return error.SkipZigTest;333 if (builtin.os.tag == .wasi) return error.SkipZigTest;
345334
...@@ -439,8 +428,6 @@ test "null sentinel pointer passed as generic argument" {...@@ -439,8 +428,6 @@ test "null sentinel pointer passed as generic argument" {
439}428}
440429
441test "generic function passed as comptime argument" {430test "generic function passed as comptime argument" {
442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
443
444 const S = struct {431 const S = struct {
445 fn doMath(comptime f: fn (comptime type, i32, i32) error{Overflow}!i32, a: i32, b: i32) !void {432 fn doMath(comptime f: fn (comptime type, i32, i32) error{Overflow}!i32, a: i32, b: i32) !void {
446 const result = try f(i32, a, b);433 const result = try f(i32, a, b);
...@@ -451,7 +438,6 @@ test "generic function passed as comptime argument" {...@@ -451,7 +438,6 @@ test "generic function passed as comptime argument" {
451}438}
452439
453test "return type of generic function is function pointer" {440test "return type of generic function is function pointer" {
454 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
455 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;441 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
456442
457 const S = struct {443 const S = struct {
...@@ -464,8 +450,6 @@ test "return type of generic function is function pointer" {...@@ -464,8 +450,6 @@ test "return type of generic function is function pointer" {
464}450}
465451
466test "coerced function body has inequal value with its uncoerced body" {452test "coerced function body has inequal value with its uncoerced body" {
467 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
468
469 const S = struct {453 const S = struct {
470 const A = B(i32, c);454 const A = B(i32, c);
471 fn c() !i32 {455 fn c() !i32 {
...@@ -513,7 +497,6 @@ test "union in struct captures argument" {...@@ -513,7 +497,6 @@ test "union in struct captures argument" {
513497
514test "function argument tuple used as struct field" {498test "function argument tuple used as struct field" {
515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO499 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
517 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;500 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
518501
519 const S = struct {502 const S = struct {
...@@ -546,8 +529,8 @@ test "comptime callconv(.c) function ptr uses comptime type argument" {...@@ -546,8 +529,8 @@ test "comptime callconv(.c) function ptr uses comptime type argument" {
546}529}
547530
548test "call generic function with from function called by the generic function" {531test "call generic function with from function called by the generic function" {
549 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
550 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;532 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
551 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
552535
553 const GET = struct {536 const GET = struct {
test/behavior/globals.zig+2-4
...@@ -6,7 +6,6 @@ var pos = [2]f32{ 0.0, 0.0 };...@@ -6,7 +6,6 @@ var pos = [2]f32{ 0.0, 0.0 };
6test "store to global array" {6test "store to global array" {
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
109
11 try expect(pos[1] == 0.0);10 try expect(pos[1] == 0.0);
12 pos = [2]f32{ 0.0, 1.0 };11 pos = [2]f32{ 0.0, 1.0 };
...@@ -15,9 +14,9 @@ test "store to global array" {...@@ -15,9 +14,9 @@ test "store to global array" {
1514
16var vpos = @Vector(2, f32){ 0.0, 0.0 };15var vpos = @Vector(2, f32){ 0.0, 0.0 };
17test "store to global vector" {16test "store to global vector" {
17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2120
22 try expect(vpos[1] == 0.0);21 try expect(vpos[1] == 0.0);
23 vpos = @Vector(2, f32){ 0.0, 1.0 };22 vpos = @Vector(2, f32){ 0.0, 1.0 };
...@@ -26,7 +25,6 @@ test "store to global vector" {...@@ -26,7 +25,6 @@ test "store to global vector" {
2625
27test "slices pointing at the same address as global array." {26test "slices pointing at the same address as global array." {
28 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;27 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO28 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;29 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
3230
...@@ -47,7 +45,6 @@ test "slices pointing at the same address as global array." {...@@ -47,7 +45,6 @@ test "slices pointing at the same address as global array." {
47test "global loads can affect liveness" {45test "global loads can affect liveness" {
48 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;46 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
5148
52 const S = struct {49 const S = struct {
53 const ByRef = struct {50 const ByRef = struct {
...@@ -188,6 +185,7 @@ test "function pointer field call on global extern struct, conditional on global...@@ -188,6 +185,7 @@ test "function pointer field call on global extern struct, conditional on global
188}185}
189186
190test "function pointer field call on global extern struct" {187test "function pointer field call on global extern struct" {
188 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
191 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;189 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
192190
193 const S = struct {191 const S = struct {
test/behavior/if.zig+4-2
...@@ -116,7 +116,6 @@ test "if prongs cast to expected type instead of peer type resolution" {...@@ -116,7 +116,6 @@ test "if prongs cast to expected type instead of peer type resolution" {
116116
117test "if peer expressions inferred optional type" {117test "if peer expressions inferred optional type" {
118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
120 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
121 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;120 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
122121
...@@ -135,7 +134,6 @@ test "if peer expressions inferred optional type" {...@@ -135,7 +134,6 @@ test "if peer expressions inferred optional type" {
135134
136test "if-else expression with runtime condition result location is inferred optional" {135test "if-else expression with runtime condition result location is inferred optional" {
137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;136 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
140138
141 const A = struct { b: u64, c: u64 };139 const A = struct { b: u64, c: u64 };
...@@ -174,6 +172,8 @@ fn returnTrue() bool {...@@ -174,6 +172,8 @@ fn returnTrue() bool {
174}172}
175173
176test "if value shouldn't be load-elided if used later (structs)" {174test "if value shouldn't be load-elided if used later (structs)" {
175 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
176
177 const Foo = struct { x: i32 };177 const Foo = struct { x: i32 };
178178
179 var a = Foo{ .x = 1 };179 var a = Foo{ .x = 1 };
...@@ -191,6 +191,8 @@ test "if value shouldn't be load-elided if used later (structs)" {...@@ -191,6 +191,8 @@ test "if value shouldn't be load-elided if used later (structs)" {
191}191}
192192
193test "if value shouldn't be load-elided if used later (optionals)" {193test "if value shouldn't be load-elided if used later (optionals)" {
194 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
195
194 var a: ?i32 = 1;196 var a: ?i32 = 1;
195 var b: ?i32 = 1;197 var b: ?i32 = 1;
196198
test/behavior/import_c_keywords.zig-1
...@@ -27,7 +27,6 @@ extern fn @"break"() Id;...@@ -27,7 +27,6 @@ extern fn @"break"() Id;
27extern fn an_alias_of_some_non_c_keyword_function() Id;27extern fn an_alias_of_some_non_c_keyword_function() Id;
2828
29test "import c keywords" {29test "import c keywords" {
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;32 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/inline_switch.zig+2-9
...@@ -3,7 +3,6 @@ const expect = std.testing.expect;...@@ -3,7 +3,6 @@ const expect = std.testing.expect;
3const builtin = @import("builtin");3const builtin = @import("builtin");
44
5test "inline scalar prongs" {5test "inline scalar prongs" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
87
9 var x: usize = 0;8 var x: usize = 0;
...@@ -18,7 +17,6 @@ test "inline scalar prongs" {...@@ -18,7 +17,6 @@ test "inline scalar prongs" {
18}17}
1918
20test "inline prong ranges" {19test "inline prong ranges" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO20 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2321
24 var x: usize = 0;22 var x: usize = 0;
...@@ -33,7 +31,6 @@ test "inline prong ranges" {...@@ -33,7 +31,6 @@ test "inline prong ranges" {
3331
34const E = enum { a, b, c, d };32const E = enum { a, b, c, d };
35test "inline switch enums" {33test "inline switch enums" {
36 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
37 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3835
39 var x: E = .a;36 var x: E = .a;
...@@ -46,7 +43,7 @@ test "inline switch enums" {...@@ -46,7 +43,7 @@ test "inline switch enums" {
4643
47const U = union(E) { a: void, b: u2, c: u3, d: u4 };44const U = union(E) { a: void, b: u2, c: u3, d: u4 };
48test "inline switch unions" {45test "inline switch unions" {
49 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO46 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
50 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO48 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5249
...@@ -73,7 +70,6 @@ test "inline switch unions" {...@@ -73,7 +70,6 @@ test "inline switch unions" {
73}70}
7471
75test "inline else bool" {72test "inline else bool" {
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO73 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7874
79 var a = true;75 var a = true;
...@@ -85,7 +81,6 @@ test "inline else bool" {...@@ -85,7 +81,6 @@ test "inline else bool" {
85}81}
8682
87test "inline else error" {83test "inline else error" {
88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
89 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9085
91 const Err = error{ a, b, c };86 const Err = error{ a, b, c };
...@@ -98,7 +93,6 @@ test "inline else error" {...@@ -98,7 +93,6 @@ test "inline else error" {
98}93}
9994
100test "inline else enum" {95test "inline else enum" {
101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO96 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10397
104 const E2 = enum(u8) { a = 2, b = 3, c = 4, d = 5 };98 const E2 = enum(u8) { a = 2, b = 3, c = 4, d = 5 };
...@@ -111,7 +105,7 @@ test "inline else enum" {...@@ -111,7 +105,7 @@ test "inline else enum" {
111}105}
112106
113test "inline else int with gaps" {107test "inline else int with gaps" {
114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO109 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
116 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO110 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
117111
...@@ -130,7 +124,6 @@ test "inline else int with gaps" {...@@ -130,7 +124,6 @@ test "inline else int with gaps" {
130}124}
131125
132test "inline else int all values" {126test "inline else int all values" {
133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
135128
136 var a: u2 = 0;129 var a: u2 = 0;
test/behavior/int128.zig-5
...@@ -5,7 +5,6 @@ const minInt = std.math.minInt;...@@ -5,7 +5,6 @@ const minInt = std.math.minInt;
5const builtin = @import("builtin");5const builtin = @import("builtin");
66
7test "uint128" {7test "uint128" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -25,7 +24,6 @@ test "uint128" {...@@ -25,7 +24,6 @@ test "uint128" {
25}24}
2625
27test "undefined 128 bit int" {26test "undefined 128 bit int" {
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO27 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO28 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;29 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -45,7 +43,6 @@ test "undefined 128 bit int" {...@@ -45,7 +43,6 @@ test "undefined 128 bit int" {
45}43}
4644
47test "int128" {45test "int128" {
48 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO47 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;48 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -68,7 +65,6 @@ test "int128" {...@@ -68,7 +65,6 @@ test "int128" {
68}65}
6966
70test "truncate int128" {67test "truncate int128" {
71 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
73 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
74 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;70 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -92,7 +88,6 @@ test "truncate int128" {...@@ -92,7 +88,6 @@ test "truncate int128" {
92}88}
9389
94test "shift int128" {90test "shift int128" {
95 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
96 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO91 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
97 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO92 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;93 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/int_comparison_elision.zig-1
...@@ -15,7 +15,6 @@ test "int comparison elision" {...@@ -15,7 +15,6 @@ test "int comparison elision" {
1515
16 // TODO: support int types > 128 bits wide in other backends16 // TODO: support int types > 128 bits wide in other backends
17 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO17 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
20 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2120
test/behavior/ir_block_deps.zig-1
...@@ -18,7 +18,6 @@ fn getErrInt() anyerror!i32 {...@@ -18,7 +18,6 @@ fn getErrInt() anyerror!i32 {
18}18}
1919
20test "ir block deps" {20test "ir block deps" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2423
test/behavior/lower_strlit_to_vector.zig-1
...@@ -3,7 +3,6 @@ const builtin = @import("builtin");...@@ -3,7 +3,6 @@ const builtin = @import("builtin");
33
4test "strlit to vector" {4test "strlit to vector" {
5 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO5 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/math.zig+23-49
...@@ -62,11 +62,11 @@ fn assertFalse(b: bool) !void {...@@ -62,11 +62,11 @@ fn assertFalse(b: bool) !void {
62}62}
6363
64test "@clz" {64test "@clz" {
65 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO66 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
68 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;67 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
69 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO68 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
69
70 try testClz();70 try testClz();
71 try comptime testClz();71 try comptime testClz();
72}72}
...@@ -80,7 +80,6 @@ fn testClz() !void {...@@ -80,7 +80,6 @@ fn testClz() !void {
80}80}
8181
82test "@clz big ints" {82test "@clz big ints" {
83 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
86 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;85 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -100,8 +99,8 @@ fn testOneClz(comptime T: type, x: T) u32 {...@@ -100,8 +99,8 @@ fn testOneClz(comptime T: type, x: T) u32 {
100}99}
101100
102test "@clz vectors" {101test "@clz vectors" {
102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
103 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO103 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO104 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO105 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
107 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;106 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -146,7 +145,6 @@ fn expectVectorsEqual(a: anytype, b: anytype) !void {...@@ -146,7 +145,6 @@ fn expectVectorsEqual(a: anytype, b: anytype) !void {
146}145}
147146
148test "@ctz" {147test "@ctz" {
149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO148 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
151 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO149 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
152 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;150 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -170,7 +168,7 @@ fn testOneCtz(comptime T: type, x: T) u32 {...@@ -170,7 +168,7 @@ fn testOneCtz(comptime T: type, x: T) u32 {
170}168}
171169
172test "@ctz 128-bit integers" {170test "@ctz 128-bit integers" {
173 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO171 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
174 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO172 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO173 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
176 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;174 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -188,8 +186,8 @@ fn testCtz128() !void {...@@ -188,8 +186,8 @@ fn testCtz128() !void {
188}186}
189187
190test "@ctz vectors" {188test "@ctz vectors" {
189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
191 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO190 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
192 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
193 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO191 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
194 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO192 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
195 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;193 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -227,7 +225,6 @@ test "const number literal" {...@@ -227,7 +225,6 @@ test "const number literal" {
227const ten = 10;225const ten = 10;
228226
229test "float equality" {227test "float equality" {
230 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
231 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
232 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO229 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
233230
...@@ -433,7 +430,6 @@ test "binary not" {...@@ -433,7 +430,6 @@ test "binary not" {
433}430}
434431
435test "binary not big int <= 128 bits" {432test "binary not big int <= 128 bits" {
436 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
437 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO433 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
438 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO434 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
439 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;435 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -467,7 +463,7 @@ test "binary not big int <= 128 bits" {...@@ -467,7 +463,7 @@ test "binary not big int <= 128 bits" {
467}463}
468464
469test "division" {465test "division" {
470 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO466 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
471 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO467 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
472 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO468 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;469 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -607,7 +603,6 @@ test "large integer division" {...@@ -607,7 +603,6 @@ test "large integer division" {
607}603}
608604
609test "division half-precision floats" {605test "division half-precision floats" {
610 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
611 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO606 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
612 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO607 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
613 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;608 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -694,7 +689,6 @@ fn testUnsignedNegationWrappingEval(x: u16) !void {...@@ -694,7 +689,6 @@ fn testUnsignedNegationWrappingEval(x: u16) !void {
694}689}
695690
696test "negation wrapping" {691test "negation wrapping" {
697 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
698 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO692 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
699 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;693 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
700694
...@@ -747,7 +741,6 @@ fn testShrTrunc(x: u16) !void {...@@ -747,7 +741,6 @@ fn testShrTrunc(x: u16) !void {
747}741}
748742
749test "f128" {743test "f128" {
750 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
751 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO744 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
752 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO745 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
753 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;746 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -776,6 +769,7 @@ fn should_not_be_zero(x: f128) !void {...@@ -776,6 +769,7 @@ fn should_not_be_zero(x: f128) !void {
776}769}
777770
778test "umax wrapped squaring" {771test "umax wrapped squaring" {
772 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
779 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;773 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
780 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;774 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
781775
...@@ -832,7 +826,6 @@ test "umax wrapped squaring" {...@@ -832,7 +826,6 @@ test "umax wrapped squaring" {
832}826}
833827
834test "128-bit multiplication" {828test "128-bit multiplication" {
835 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
836 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO829 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
837 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO830 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
838 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;831 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -867,7 +860,6 @@ fn testAddWithOverflow(comptime T: type, a: T, b: T, add: T, bit: u1) !void {...@@ -867,7 +860,6 @@ fn testAddWithOverflow(comptime T: type, a: T, b: T, add: T, bit: u1) !void {
867}860}
868861
869test "@addWithOverflow" {862test "@addWithOverflow" {
870 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
871 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO863 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
872 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO864 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
873 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO865 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
...@@ -886,7 +878,6 @@ test "@addWithOverflow" {...@@ -886,7 +878,6 @@ test "@addWithOverflow" {
886}878}
887879
888test "@addWithOverflow > 64 bits" {880test "@addWithOverflow > 64 bits" {
889 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
890 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO881 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
891 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO882 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
892 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;883 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -958,7 +949,7 @@ fn testMulWithOverflow(comptime T: type, a: T, b: T, mul: T, bit: u1) !void {...@@ -958,7 +949,7 @@ fn testMulWithOverflow(comptime T: type, a: T, b: T, mul: T, bit: u1) !void {
958}949}
959950
960test "basic @mulWithOverflow" {951test "basic @mulWithOverflow" {
961 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO952 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
962 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO953 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
963 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO954 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
964955
...@@ -970,7 +961,7 @@ test "basic @mulWithOverflow" {...@@ -970,7 +961,7 @@ test "basic @mulWithOverflow" {
970}961}
971962
972test "extensive @mulWithOverflow" {963test "extensive @mulWithOverflow" {
973 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO964 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
974 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO965 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
975 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;966 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
976 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;967 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1010,11 +1001,9 @@ test "extensive @mulWithOverflow" {...@@ -1010,11 +1001,9 @@ test "extensive @mulWithOverflow" {
1010}1001}
10111002
1012test "@mulWithOverflow bitsize > 32" {1003test "@mulWithOverflow bitsize > 32" {
1013 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1004 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1014
1015 // aarch64 fails on a release build of the compiler.
1016 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1017 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1005 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1006 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1018 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1007 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10191008
1020 try testMulWithOverflow(u40, 3, 0x55_5555_5555, 0xff_ffff_ffff, 0);1009 try testMulWithOverflow(u40, 3, 0x55_5555_5555, 0xff_ffff_ffff, 0);
...@@ -1041,9 +1030,9 @@ test "@mulWithOverflow bitsize > 32" {...@@ -1041,9 +1030,9 @@ test "@mulWithOverflow bitsize > 32" {
1041}1030}
10421031
1043test "@mulWithOverflow bitsize 128 bits" {1032test "@mulWithOverflow bitsize 128 bits" {
1033 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1044 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;1034 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1045 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1035 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1046 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1047 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1036 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1048 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1037 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1049 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO1038 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -1068,6 +1057,7 @@ test "@mulWithOverflow bitsize 128 bits" {...@@ -1068,6 +1057,7 @@ test "@mulWithOverflow bitsize 128 bits" {
1068}1057}
10691058
1070test "@mulWithOverflow bitsize 256 bits" {1059test "@mulWithOverflow bitsize 256 bits" {
1060 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1071 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;1061 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1072 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;1062 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1073 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1063 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1114,7 +1104,6 @@ fn testSubWithOverflow(comptime T: type, a: T, b: T, sub: T, bit: u1) !void {...@@ -1114,7 +1104,6 @@ fn testSubWithOverflow(comptime T: type, a: T, b: T, sub: T, bit: u1) !void {
1114}1104}
11151105
1116test "@subWithOverflow" {1106test "@subWithOverflow" {
1117 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11201109
...@@ -1131,7 +1120,6 @@ test "@subWithOverflow" {...@@ -1131,7 +1120,6 @@ test "@subWithOverflow" {
1131}1120}
11321121
1133test "@subWithOverflow > 64 bits" {1122test "@subWithOverflow > 64 bits" {
1134 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1135 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1137 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1125 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1179,7 +1167,7 @@ fn testShlWithOverflow(comptime T: type, a: T, b: math.Log2Int(T), shl: T, bit:...@@ -1179,7 +1167,7 @@ fn testShlWithOverflow(comptime T: type, a: T, b: math.Log2Int(T), shl: T, bit:
1179}1167}
11801168
1181test "@shlWithOverflow" {1169test "@shlWithOverflow" {
1182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1183 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1184 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1172 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1185 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1173 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1198,7 +1186,7 @@ test "@shlWithOverflow" {...@@ -1198,7 +1186,7 @@ test "@shlWithOverflow" {
1198}1186}
11991187
1200test "@shlWithOverflow > 64 bits" {1188test "@shlWithOverflow > 64 bits" {
1201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1189 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1190 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1203 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1191 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1204 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1192 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1267,7 +1255,6 @@ test "allow signed integer division/remainder when values are comptime-known and...@@ -1267,7 +1255,6 @@ test "allow signed integer division/remainder when values are comptime-known and
1267}1255}
12681256
1269test "quad hex float literal parsing accurate" {1257test "quad hex float literal parsing accurate" {
1270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1271 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1272 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1273 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1260 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1425,8 +1412,8 @@ test "comptime float rem int" {...@@ -1425,8 +1412,8 @@ test "comptime float rem int" {
1425}1412}
14261413
1427test "remainder division" {1414test "remainder division" {
1415 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1428 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1416 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1429 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1430 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1417 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1431 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1418 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1432 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;1419 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
...@@ -1465,7 +1452,6 @@ fn remdivOne(comptime T: type, a: T, b: T, c: T) !void {...@@ -1465,7 +1452,6 @@ fn remdivOne(comptime T: type, a: T, b: T, c: T) !void {
14651452
1466test "float remainder division using @rem" {1453test "float remainder division using @rem" {
1467 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1454 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1468 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1469 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1455 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1470 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1456 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1471 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1457 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1506,8 +1492,8 @@ fn fremOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {...@@ -1506,8 +1492,8 @@ fn fremOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {
1506}1492}
15071493
1508test "float modulo division using @mod" {1494test "float modulo division using @mod" {
1495 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1509 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1496 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1510 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1511 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1497 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1512 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1498 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1513 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;1499 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
...@@ -1550,7 +1536,6 @@ fn fmodOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {...@@ -1550,7 +1536,6 @@ fn fmodOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {
15501536
1551test "@round f16" {1537test "@round f16" {
1552 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1553 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1554 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1539 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1555 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1540 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15561541
...@@ -1560,7 +1545,6 @@ test "@round f16" {...@@ -1560,7 +1545,6 @@ test "@round f16" {
15601545
1561test "@round f32/f64" {1546test "@round f32/f64" {
1562 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1547 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1563 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1564 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1548 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1565 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1549 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
15661550
...@@ -1577,7 +1561,6 @@ test "@round f32/f64" {...@@ -1577,7 +1561,6 @@ test "@round f32/f64" {
15771561
1578test "@round f80" {1562test "@round f80" {
1579 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1563 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1580 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1581 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1564 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1582 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1565 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1583 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;1566 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
...@@ -1589,7 +1572,6 @@ test "@round f80" {...@@ -1589,7 +1572,6 @@ test "@round f80" {
15891572
1590test "@round f128" {1573test "@round f128" {
1591 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1592 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1593 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1575 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1594 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1576 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1595 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;1577 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
...@@ -1606,9 +1588,9 @@ fn testRound(comptime T: type, x: T) !void {...@@ -1606,9 +1588,9 @@ fn testRound(comptime T: type, x: T) !void {
1606}1588}
16071589
1608test "vector integer addition" {1590test "vector integer addition" {
1591 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1609 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1592 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1610 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1593 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1612 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1594 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1613 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1595 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1614 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1596 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1630,7 +1612,6 @@ test "vector integer addition" {...@@ -1630,7 +1612,6 @@ test "vector integer addition" {
16301612
1631test "NaN comparison" {1613test "NaN comparison" {
1632 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1614 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1633 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1634 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1615 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1635 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1616 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1636 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1617 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1648,7 +1629,6 @@ test "NaN comparison" {...@@ -1648,7 +1629,6 @@ test "NaN comparison" {
16481629
1649test "NaN comparison f80" {1630test "NaN comparison f80" {
1650 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1631 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1651 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1652 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1632 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1653 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1633 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1654 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1634 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1670,9 +1650,9 @@ fn testNanEqNan(comptime F: type) !void {...@@ -1670,9 +1650,9 @@ fn testNanEqNan(comptime F: type) !void {
1670}1650}
16711651
1672test "vector comparison" {1652test "vector comparison" {
1653 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1673 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1654 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1674 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1655 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1675 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1676 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1656 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1677 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1657 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1678 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1658 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1703,7 +1683,6 @@ test "compare undefined literal with comptime_int" {...@@ -1703,7 +1683,6 @@ test "compare undefined literal with comptime_int" {
17031683
1704test "signed zeros are represented properly" {1684test "signed zeros are represented properly" {
1705 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1685 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1706 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1707 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1686 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1708 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1687 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1709 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1688 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1735,7 +1714,6 @@ test "signed zeros are represented properly" {...@@ -1735,7 +1714,6 @@ test "signed zeros are represented properly" {
17351714
1736test "absFloat" {1715test "absFloat" {
1737 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1716 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1738 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1739 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1717 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17401718
1741 try testAbsFloat();1719 try testAbsFloat();
...@@ -1765,8 +1743,8 @@ test "mod lazy values" {...@@ -1765,8 +1743,8 @@ test "mod lazy values" {
1765}1743}
17661744
1767test "@clz works on both vector and scalar inputs" {1745test "@clz works on both vector and scalar inputs" {
1746 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1768 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1747 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1769 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1770 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1748 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1771 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1749 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1772 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1750 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1784,7 +1762,6 @@ test "@clz works on both vector and scalar inputs" {...@@ -1784,7 +1762,6 @@ test "@clz works on both vector and scalar inputs" {
17841762
1785test "runtime comparison to NaN is comptime-known" {1763test "runtime comparison to NaN is comptime-known" {
1786 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1764 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1787 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1788 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1765 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1789 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1766 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1790 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1767 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1814,7 +1791,6 @@ test "runtime comparison to NaN is comptime-known" {...@@ -1814,7 +1791,6 @@ test "runtime comparison to NaN is comptime-known" {
18141791
1815test "runtime int comparison to inf is comptime-known" {1792test "runtime int comparison to inf is comptime-known" {
1816 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1793 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1817 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1818 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1794 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1819 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1795 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1820 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1796 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1843,8 +1819,8 @@ test "runtime int comparison to inf is comptime-known" {...@@ -1843,8 +1819,8 @@ test "runtime int comparison to inf is comptime-known" {
1843}1819}
18441820
1845test "float divide by zero" {1821test "float divide by zero" {
1822 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1846 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1823 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1847 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1848 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1849 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1850 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1826 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1878,8 +1854,8 @@ test "float divide by zero" {...@@ -1878,8 +1854,8 @@ test "float divide by zero" {
1878}1854}
18791855
1880test "partially-runtime integer vector division would be illegal if vector elements were reordered" {1856test "partially-runtime integer vector division would be illegal if vector elements were reordered" {
1857 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1881 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1858 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1882 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1883 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1859 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1884 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1860 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1885 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1861 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1907,8 +1883,8 @@ test "partially-runtime integer vector division would be illegal if vector eleme...@@ -1907,8 +1883,8 @@ test "partially-runtime integer vector division would be illegal if vector eleme
1907}1883}
19081884
1909test "float vector division of comptime zero by runtime nan is nan" {1885test "float vector division of comptime zero by runtime nan is nan" {
1886 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1910 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1887 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1911 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1912 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1888 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1913 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1889 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1914 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1890 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1925,8 +1901,8 @@ test "float vector division of comptime zero by runtime nan is nan" {...@@ -1925,8 +1901,8 @@ test "float vector division of comptime zero by runtime nan is nan" {
1925}1901}
19261902
1927test "float vector multiplication of comptime zero by runtime nan is nan" {1903test "float vector multiplication of comptime zero by runtime nan is nan" {
1904 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1928 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1905 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1929 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1930 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1906 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1931 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1907 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1932 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1908 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1943,7 +1919,6 @@ test "float vector multiplication of comptime zero by runtime nan is nan" {...@@ -1943,7 +1919,6 @@ test "float vector multiplication of comptime zero by runtime nan is nan" {
19431919
1944test "comptime float vector division of zero by nan is nan" {1920test "comptime float vector division of zero by nan is nan" {
1945 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1921 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1946 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1947 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1922 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1948 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1923 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1949 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1924 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1959,7 +1934,6 @@ test "comptime float vector division of zero by nan is nan" {...@@ -1959,7 +1934,6 @@ test "comptime float vector division of zero by nan is nan" {
19591934
1960test "comptime float vector multiplication of zero by nan is nan" {1935test "comptime float vector multiplication of zero by nan is nan" {
1961 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1936 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1962 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1963 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1937 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1964 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1938 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1965 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1939 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/maximum_minimum.zig+7-15
...@@ -7,7 +7,6 @@ const expectEqual = std.testing.expectEqual;...@@ -7,7 +7,6 @@ const expectEqual = std.testing.expectEqual;
77
8test "@max" {8test "@max" {
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1312
...@@ -28,9 +27,9 @@ test "@max" {...@@ -28,9 +27,9 @@ test "@max" {
28}27}
2928
30test "@max on vectors" {29test "@max on vectors" {
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO32 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO33 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
35 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;34 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
36 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;35 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -61,7 +60,6 @@ test "@max on vectors" {...@@ -61,7 +60,6 @@ test "@max on vectors" {
61}60}
6261
63test "@min" {62test "@min" {
64 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO63 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO64 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;65 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -83,8 +81,8 @@ test "@min" {...@@ -83,8 +81,8 @@ test "@min" {
83}81}
8482
85test "@min for vectors" {83test "@min for vectors" {
84 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
86 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO85 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
87 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO86 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
89 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
90 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;88 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -116,7 +114,6 @@ test "@min for vectors" {...@@ -116,7 +114,6 @@ test "@min for vectors" {
116}114}
117115
118test "@min/max for floats" {116test "@min/max for floats" {
119 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
121 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO118 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
122 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;119 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -167,8 +164,8 @@ test "@min/@max more than two arguments" {...@@ -167,8 +164,8 @@ test "@min/@max more than two arguments" {
167}164}
168165
169test "@min/@max more than two vector arguments" {166test "@min/@max more than two vector arguments" {
167 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
170 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO168 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
171 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
172 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO169 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
173 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
174 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;171 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -181,7 +178,6 @@ test "@min/@max more than two vector arguments" {...@@ -181,7 +178,6 @@ test "@min/@max more than two vector arguments" {
181}178}
182179
183test "@min/@max notices bounds" {180test "@min/@max notices bounds" {
184 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
185 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
186 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO182 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
187183
...@@ -198,8 +194,8 @@ test "@min/@max notices bounds" {...@@ -198,8 +194,8 @@ test "@min/@max notices bounds" {
198}194}
199195
200test "@min/@max notices vector bounds" {196test "@min/@max notices vector bounds" {
197 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
201 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO198 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
203 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO199 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO200 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
205 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;201 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -217,7 +213,6 @@ test "@min/@max notices vector bounds" {...@@ -217,7 +213,6 @@ test "@min/@max notices vector bounds" {
217}213}
218214
219test "@min/@max on comptime_int" {215test "@min/@max on comptime_int" {
220 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
221 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO216 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
222 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
223218
...@@ -231,7 +226,6 @@ test "@min/@max on comptime_int" {...@@ -231,7 +226,6 @@ test "@min/@max on comptime_int" {
231}226}
232227
233test "@min/@max notices bounds from types" {228test "@min/@max notices bounds from types" {
234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
235 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO229 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
236 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO230 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
237231
...@@ -251,8 +245,8 @@ test "@min/@max notices bounds from types" {...@@ -251,8 +245,8 @@ test "@min/@max notices bounds from types" {
251}245}
252246
253test "@min/@max notices bounds from vector types" {247test "@min/@max notices bounds from vector types" {
248 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
254 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO249 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
255 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO250 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
257 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO251 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
258 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;252 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -273,7 +267,6 @@ test "@min/@max notices bounds from vector types" {...@@ -273,7 +267,6 @@ test "@min/@max notices bounds from vector types" {
273}267}
274268
275test "@min/@max notices bounds from types when comptime-known value is undef" {269test "@min/@max notices bounds from types when comptime-known value is undef" {
276 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO270 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO271 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
279 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;272 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -293,8 +286,8 @@ test "@min/@max notices bounds from types when comptime-known value is undef" {...@@ -293,8 +286,8 @@ test "@min/@max notices bounds from types when comptime-known value is undef" {
293}286}
294287
295test "@min/@max notices bounds from vector types when element of comptime-known vector is undef" {288test "@min/@max notices bounds from vector types when element of comptime-known vector is undef" {
289 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
296 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO290 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
297 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
298 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO291 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
299 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO292 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
300 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;293 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -333,7 +326,6 @@ test "@min/@max of signed and unsigned runtime integers" {...@@ -333,7 +326,6 @@ test "@min/@max of signed and unsigned runtime integers" {
333}326}
334327
335test "@min resulting in u0" {328test "@min resulting in u0" {
336 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
337 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO329 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
338 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO330 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
339331
...@@ -364,8 +356,8 @@ test "@min/@max with runtime signed and unsigned integers of same size" {...@@ -364,8 +356,8 @@ test "@min/@max with runtime signed and unsigned integers of same size" {
364}356}
365357
366test "@min/@max with runtime vectors of signed and unsigned integers of same size" {358test "@min/@max with runtime vectors of signed and unsigned integers of same size" {
359 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
367 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO360 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
368 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
369 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO361 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
370 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO362 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
371 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;363 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/member_func.zig-2
...@@ -28,7 +28,6 @@ const HasFuncs = struct {...@@ -28,7 +28,6 @@ const HasFuncs = struct {
2828
29test "standard field calls" {29test "standard field calls" {
30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;32 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
3433
...@@ -72,7 +71,6 @@ test "standard field calls" {...@@ -72,7 +71,6 @@ test "standard field calls" {
7271
73test "@field field calls" {72test "@field field calls" {
74 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
75 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO74 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;75 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
7876
test/behavior/memcpy.zig+1-4
...@@ -4,7 +4,6 @@ const expect = std.testing.expect;...@@ -4,7 +4,6 @@ const expect = std.testing.expect;
4const assert = std.debug.assert;4const assert = std.debug.assert;
55
6test "memcpy and memset intrinsics" {6test "memcpy and memset intrinsics" {
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -26,7 +25,6 @@ fn testMemcpyMemset() !void {...@@ -26,7 +25,6 @@ fn testMemcpyMemset() !void {
26}25}
2726
28test "@memcpy with both operands single-ptr-to-array, one is null-terminated" {27test "@memcpy with both operands single-ptr-to-array, one is null-terminated" {
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;28 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -47,7 +45,6 @@ fn testMemcpyBothSinglePtrArrayOneIsNullTerminated() !void {...@@ -47,7 +45,6 @@ fn testMemcpyBothSinglePtrArrayOneIsNullTerminated() !void {
47}45}
4846
49test "@memcpy dest many pointer" {47test "@memcpy dest many pointer" {
50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;48 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;49 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;50 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -70,7 +67,6 @@ fn testMemcpyDestManyPtr() !void {...@@ -70,7 +67,6 @@ fn testMemcpyDestManyPtr() !void {
70}67}
7168
72test "@memcpy C pointer" {69test "@memcpy C pointer" {
73 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
74 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;70 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;72 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -156,6 +152,7 @@ test "@memcpy zero-bit type with aliasing" {...@@ -156,6 +152,7 @@ test "@memcpy zero-bit type with aliasing" {
156}152}
157153
158test "@memcpy with sentinel" {154test "@memcpy with sentinel" {
155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
159 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;156 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
160157
161 const S = struct {158 const S = struct {
test/behavior/memmove.zig-3
...@@ -3,7 +3,6 @@ const builtin = @import("builtin");...@@ -3,7 +3,6 @@ const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "memmove and memset intrinsics" {5test "memmove and memset intrinsics" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -32,7 +31,6 @@ fn testMemmoveMemset() !void {...@@ -32,7 +31,6 @@ fn testMemmoveMemset() !void {
32}31}
3332
34test "@memmove with both operands single-ptr-to-array, one is null-terminated" {33test "@memmove with both operands single-ptr-to-array, one is null-terminated" {
35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;34 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;35 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -77,7 +75,6 @@ fn testMemmoveBothSinglePtrArrayOneIsNullTerminated() !void {...@@ -77,7 +75,6 @@ fn testMemmoveBothSinglePtrArrayOneIsNullTerminated() !void {
77}75}
7876
79test "@memmove dest many pointer" {77test "@memmove dest many pointer" {
80 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
81 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;78 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
82 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;80 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/memset.zig-7
...@@ -3,7 +3,6 @@ const builtin = @import("builtin");...@@ -3,7 +3,6 @@ const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "@memset on array pointers" {5test "@memset on array pointers" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -32,7 +31,6 @@ fn testMemsetArray() !void {...@@ -32,7 +31,6 @@ fn testMemsetArray() !void {
32}31}
3332
34test "@memset on slices" {33test "@memset on slices" {
35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;34 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;35 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -68,7 +66,6 @@ fn testMemsetSlice() !void {...@@ -68,7 +66,6 @@ fn testMemsetSlice() !void {
68}66}
6967
70test "memset with bool element" {68test "memset with bool element" {
71 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
72 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;69 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
73 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;70 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
74 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;71 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -80,7 +77,6 @@ test "memset with bool element" {...@@ -80,7 +77,6 @@ test "memset with bool element" {
80}77}
8178
82test "memset with 1-byte struct element" {79test "memset with 1-byte struct element" {
83 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
85 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;81 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
86 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;82 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -94,7 +90,6 @@ test "memset with 1-byte struct element" {...@@ -94,7 +90,6 @@ test "memset with 1-byte struct element" {
94}90}
9591
96test "memset with 1-byte array element" {92test "memset with 1-byte array element" {
97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
98 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;93 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;94 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
100 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;95 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -145,7 +140,6 @@ test "memset with large array element, comptime known" {...@@ -145,7 +140,6 @@ test "memset with large array element, comptime known" {
145}140}
146141
147test "@memset provides result type" {142test "@memset provides result type" {
148 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;143 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
150 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;144 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;145 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -164,7 +158,6 @@ test "@memset provides result type" {...@@ -164,7 +158,6 @@ test "@memset provides result type" {
164}158}
165159
166test "zero keys with @memset" {160test "zero keys with @memset" {
167 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
168 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
169 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
170 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/muladd.zig+5-9
...@@ -4,7 +4,6 @@ const expect = std.testing.expect;...@@ -4,7 +4,6 @@ const expect = std.testing.expect;
44
5test "@mulAdd" {5test "@mulAdd" {
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -32,7 +31,6 @@ fn testMulAdd() !void {...@@ -32,7 +31,6 @@ fn testMulAdd() !void {
3231
33test "@mulAdd f16" {32test "@mulAdd f16" {
34 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO33 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
35 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
37 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;35 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -51,7 +49,6 @@ fn testMulAdd16() !void {...@@ -51,7 +49,6 @@ fn testMulAdd16() !void {
5149
52test "@mulAdd f80" {50test "@mulAdd f80" {
53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;53 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
57 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;54 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
...@@ -71,7 +68,6 @@ fn testMulAdd80() !void {...@@ -71,7 +68,6 @@ fn testMulAdd80() !void {
7168
72test "@mulAdd f128" {69test "@mulAdd f128" {
73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO70 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
74 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
75 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;72 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;73 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
...@@ -103,9 +99,9 @@ fn vector16() !void {...@@ -103,9 +99,9 @@ fn vector16() !void {
103}99}
104100
105test "vector f16" {101test "vector f16" {
102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
106 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO103 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO104 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO105 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
110 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;106 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
111 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;107 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -128,9 +124,9 @@ fn vector32() !void {...@@ -128,9 +124,9 @@ fn vector32() !void {
128}124}
129125
130test "vector f32" {126test "vector f32" {
127 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
131 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO128 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
132 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO129 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
135 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;131 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
136 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;132 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -153,9 +149,9 @@ fn vector64() !void {...@@ -153,9 +149,9 @@ fn vector64() !void {
153}149}
154150
155test "vector f64" {151test "vector f64" {
152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
156 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO153 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
158 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO155 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
160 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;156 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
161 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;157 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -177,9 +173,9 @@ fn vector80() !void {...@@ -177,9 +173,9 @@ fn vector80() !void {
177}173}
178174
179test "vector f80" {175test "vector f80" {
176 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
180 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO177 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO178 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO179 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
184 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;180 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;181 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
...@@ -203,9 +199,9 @@ fn vector128() !void {...@@ -203,9 +199,9 @@ fn vector128() !void {
203}199}
204200
205test "vector f128" {201test "vector f128" {
202 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
206 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO203 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
207 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
208 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
210 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;206 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
211 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;207 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest;
test/behavior/multiple_externs_with_conflicting_types.zig-1
...@@ -11,7 +11,6 @@ comptime {...@@ -11,7 +11,6 @@ comptime {
11const builtin = @import("builtin");11const builtin = @import("builtin");
1212
13test "call extern function defined with conflicting type" {13test "call extern function defined with conflicting type" {
14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO15 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;16 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/nan.zig-1
...@@ -23,7 +23,6 @@ const snan_f128: f128 = math.snan(f128);...@@ -23,7 +23,6 @@ const snan_f128: f128 = math.snan(f128);
2323
24test "nan memory equality" {24test "nan memory equality" {
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
26 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
27 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;26 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;27 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2928
test/behavior/null.zig+2-4
...@@ -29,8 +29,8 @@ test "optional type" {...@@ -29,8 +29,8 @@ test "optional type" {
29}29}
3030
31test "test maybe object and get a pointer to the inner value" {31test "test maybe object and get a pointer to the inner value" {
32 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
35 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;35 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3636
...@@ -51,7 +51,6 @@ test "rhs maybe unwrap return" {...@@ -51,7 +51,6 @@ test "rhs maybe unwrap return" {
5151
52test "maybe return" {52test "maybe return" {
53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO54 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5655
57 try maybeReturnImpl();56 try maybeReturnImpl();
...@@ -140,8 +139,8 @@ test "optional pointer to 0 bit type null value at runtime" {...@@ -140,8 +139,8 @@ test "optional pointer to 0 bit type null value at runtime" {
140}139}
141140
142test "if var maybe pointer" {141test "if var maybe pointer" {
143 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;142 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
143 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO144 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;145 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
147146
...@@ -185,7 +184,6 @@ const here_is_a_null_literal = SillyStruct{ .context = null };...@@ -185,7 +184,6 @@ const here_is_a_null_literal = SillyStruct{ .context = null };
185184
186test "unwrap optional which is field of global var" {185test "unwrap optional which is field of global var" {
187 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;186 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
188 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
189 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO187 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
190188
191 struct_with_optional.field = null;189 struct_with_optional.field = null;
test/behavior/optional.zig+10-12
...@@ -59,6 +59,7 @@ fn testNullPtrsEql() !void {...@@ -59,6 +59,7 @@ fn testNullPtrsEql() !void {
59}59}
6060
61test "optional with zero-bit type" {61test "optional with zero-bit type" {
62 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
62 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;63 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
6364
64 const S = struct {65 const S = struct {
...@@ -109,7 +110,6 @@ test "optional with zero-bit type" {...@@ -109,7 +110,6 @@ test "optional with zero-bit type" {
109}110}
110111
111test "address of unwrap optional" {112test "address of unwrap optional" {
112 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
113 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO113 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
115 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;115 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -132,7 +132,6 @@ test "address of unwrap optional" {...@@ -132,7 +132,6 @@ test "address of unwrap optional" {
132}132}
133133
134test "nested optional field in struct" {134test "nested optional field in struct" {
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
136 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
138137
...@@ -210,6 +209,7 @@ test "equality compare optionals and non-optionals" {...@@ -210,6 +209,7 @@ test "equality compare optionals and non-optionals" {
210}209}
211210
212test "compare optionals with modified payloads" {211test "compare optionals with modified payloads" {
212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
213 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;213 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
214214
215 var lhs: ?bool = false;215 var lhs: ?bool = false;
...@@ -319,7 +319,7 @@ test "assigning to an unwrapped optional field in an inline loop" {...@@ -319,7 +319,7 @@ test "assigning to an unwrapped optional field in an inline loop" {
319}319}
320320
321test "coerce an anon struct literal to optional struct" {321test "coerce an anon struct literal to optional struct" {
322 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO322 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
323 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO323 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
324 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO324 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
325 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;325 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -339,7 +339,6 @@ test "coerce an anon struct literal to optional struct" {...@@ -339,7 +339,6 @@ test "coerce an anon struct literal to optional struct" {
339}339}
340340
341test "0-bit child type coerced to optional return ptr result location" {341test "0-bit child type coerced to optional return ptr result location" {
342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
343 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO342 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
344 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO343 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
345344
...@@ -365,6 +364,7 @@ test "0-bit child type coerced to optional return ptr result location" {...@@ -365,6 +364,7 @@ test "0-bit child type coerced to optional return ptr result location" {
365}364}
366365
367test "0-bit child type coerced to optional" {366test "0-bit child type coerced to optional" {
367 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
368 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO368 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
369 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;369 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
370370
...@@ -391,7 +391,7 @@ test "0-bit child type coerced to optional" {...@@ -391,7 +391,7 @@ test "0-bit child type coerced to optional" {
391}391}
392392
393test "array of optional unaligned types" {393test "array of optional unaligned types" {
394 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO394 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
395 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO395 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
397 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;397 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -428,8 +428,8 @@ test "array of optional unaligned types" {...@@ -428,8 +428,8 @@ test "array of optional unaligned types" {
428}428}
429429
430test "optional pointer to zero bit optional payload" {430test "optional pointer to zero bit optional payload" {
431 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
431 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO432 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
432 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
433 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO433 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
434 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;434 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
435435
...@@ -447,8 +447,8 @@ test "optional pointer to zero bit optional payload" {...@@ -447,8 +447,8 @@ test "optional pointer to zero bit optional payload" {
447}447}
448448
449test "optional pointer to zero bit error union payload" {449test "optional pointer to zero bit error union payload" {
450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
450 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
451 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
453 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;453 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
454 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;454 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -543,7 +543,6 @@ test "alignment of wrapping an optional payload" {...@@ -543,7 +543,6 @@ test "alignment of wrapping an optional payload" {
543}543}
544544
545test "Optional slice size is optimized" {545test "Optional slice size is optimized" {
546 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
547 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;546 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
548 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO547 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
549 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;548 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -556,7 +555,7 @@ test "Optional slice size is optimized" {...@@ -556,7 +555,7 @@ test "Optional slice size is optimized" {
556}555}
557556
558test "Optional slice passed to function" {557test "Optional slice passed to function" {
559 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO558 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
560 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO559 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
561 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO560 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
562 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;561 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -574,7 +573,6 @@ test "Optional slice passed to function" {...@@ -574,7 +573,6 @@ test "Optional slice passed to function" {
574}573}
575574
576test "peer type resolution in nested if expressions" {575test "peer type resolution in nested if expressions" {
577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
578 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;576 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
579577
580 const Thing = struct { n: i32 };578 const Thing = struct { n: i32 };
...@@ -623,8 +621,8 @@ test "variable of optional of noreturn" {...@@ -623,8 +621,8 @@ test "variable of optional of noreturn" {
623}621}
624622
625test "copied optional doesn't alias source" {623test "copied optional doesn't alias source" {
624 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
626 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO625 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
627 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
628 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO626 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
629 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;627 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
630628
...@@ -637,8 +635,8 @@ test "copied optional doesn't alias source" {...@@ -637,8 +635,8 @@ test "copied optional doesn't alias source" {
637}635}
638636
639test "result location initialization of optional with OPV payload" {637test "result location initialization of optional with OPV payload" {
638 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
640 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO639 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
641 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
642 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO640 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
643 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;641 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
644 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO642 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
test/behavior/packed-struct.zig+24-22
...@@ -120,7 +120,6 @@ test "consistent size of packed structs" {...@@ -120,7 +120,6 @@ test "consistent size of packed structs" {
120}120}
121121
122test "correct sizeOf and offsets in packed structs" {122test "correct sizeOf and offsets in packed structs" {
123 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
124 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
126125
...@@ -187,7 +186,6 @@ test "correct sizeOf and offsets in packed structs" {...@@ -187,7 +186,6 @@ test "correct sizeOf and offsets in packed structs" {
187}186}
188187
189test "nested packed structs" {188test "nested packed structs" {
190 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
191 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO189 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
192 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO190 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
193191
...@@ -484,7 +482,6 @@ test "load pointer from packed struct" {...@@ -484,7 +482,6 @@ test "load pointer from packed struct" {
484}482}
485483
486test "@intFromPtr on a packed struct field" {484test "@intFromPtr on a packed struct field" {
487 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
488 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;485 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
489 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO486 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;487 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -507,7 +504,6 @@ test "@intFromPtr on a packed struct field" {...@@ -507,7 +504,6 @@ test "@intFromPtr on a packed struct field" {
507}504}
508505
509test "@intFromPtr on a packed struct field unaligned and nested" {506test "@intFromPtr on a packed struct field unaligned and nested" {
510 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
511 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;507 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
512 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO508 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
513 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;509 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -617,6 +613,7 @@ test "@intFromPtr on a packed struct field unaligned and nested" {...@@ -617,6 +613,7 @@ test "@intFromPtr on a packed struct field unaligned and nested" {
617}613}
618614
619test "packed struct fields modification" {615test "packed struct fields modification" {
616 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
620 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;617 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
621618
622 // Originally reported at https://github.com/ziglang/zig/issues/16615619 // Originally reported at https://github.com/ziglang/zig/issues/16615
...@@ -656,9 +653,9 @@ test "optional pointer in packed struct" {...@@ -656,9 +653,9 @@ test "optional pointer in packed struct" {
656}653}
657654
658test "nested packed struct field access test" {655test "nested packed struct field access test" {
656 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
659 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO657 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
660 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits658 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits
661 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
662 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO659 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
663 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO660 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
664 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;661 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -777,6 +774,7 @@ test "nested packed struct field access test" {...@@ -777,6 +774,7 @@ test "nested packed struct field access test" {
777}774}
778775
779test "nested packed struct at non-zero offset" {776test "nested packed struct at non-zero offset" {
777 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
780 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO778 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
781 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;779 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
782780
...@@ -915,7 +913,6 @@ test "packed struct passed to callconv(.c) function" {...@@ -915,7 +913,6 @@ test "packed struct passed to callconv(.c) function" {
915}913}
916914
917test "overaligned pointer to packed struct" {915test "overaligned pointer to packed struct" {
918 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
919 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;916 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
920 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO917 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
921 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;918 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -937,7 +934,7 @@ test "overaligned pointer to packed struct" {...@@ -937,7 +934,7 @@ test "overaligned pointer to packed struct" {
937}934}
938935
939test "packed struct initialized in bitcast" {936test "packed struct initialized in bitcast" {
940 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO937 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
941 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO938 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
942 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO939 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
943 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;940 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -986,8 +983,8 @@ test "store undefined to packed result location" {...@@ -986,8 +983,8 @@ test "store undefined to packed result location" {
986 try expectEqual(x, s.x);983 try expectEqual(x, s.x);
987}984}
988985
986// Originally reported at https://github.com/ziglang/zig/issues/9914
989test "bitcast back and forth" {987test "bitcast back and forth" {
990 // Originally reported at https://github.com/ziglang/zig/issues/9914
991 const S = packed struct { one: u6, two: u1 };988 const S = packed struct { one: u6, two: u1 };
992 const s = S{ .one = 0b110101, .two = 0b1 };989 const s = S{ .one = 0b110101, .two = 0b1 };
993 const u: u7 = @bitCast(s);990 const u: u7 = @bitCast(s);
...@@ -996,8 +993,9 @@ test "bitcast back and forth" {...@@ -996,8 +993,9 @@ test "bitcast back and forth" {
996 try expect(s.two == s2.two);993 try expect(s.two == s2.two);
997}994}
998995
996// Originally reported at https://github.com/ziglang/zig/issues/14200
999test "field access of packed struct smaller than its abi size inside struct initialized with rls" {997test "field access of packed struct smaller than its abi size inside struct initialized with rls" {
1000 // Originally reported at https://github.com/ziglang/zig/issues/14200998 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1001 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;999 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1002 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO1000 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
10031001
...@@ -1015,8 +1013,8 @@ test "field access of packed struct smaller than its abi size inside struct init...@@ -1015,8 +1013,8 @@ test "field access of packed struct smaller than its abi size inside struct init
1015 try expect(@as(i2, 1) == s.ps.y);1013 try expect(@as(i2, 1) == s.ps.y);
1016}1014}
10171015
1016// Originally reported at https://github.com/ziglang/zig/issues/14632
1018test "modify nested packed struct aligned field" {1017test "modify nested packed struct aligned field" {
1019 // Originally reported at https://github.com/ziglang/zig/issues/14632
1020 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1018 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1021 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1019 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1022 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;1020 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
...@@ -1045,10 +1043,10 @@ test "modify nested packed struct aligned field" {...@@ -1045,10 +1043,10 @@ test "modify nested packed struct aligned field" {
1045 try std.testing.expect(!opts.baz);1043 try std.testing.expect(!opts.baz);
1046}1044}
10471045
1046// Originally reported at https://github.com/ziglang/zig/issues/9674
1048test "assigning packed struct inside another packed struct" {1047test "assigning packed struct inside another packed struct" {
1048 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1049 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1049 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1050
1051 // Originally reported at https://github.com/ziglang/zig/issues/9674
1052 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1050 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10531051
1054 const S = struct {1052 const S = struct {
...@@ -1078,7 +1076,6 @@ test "assigning packed struct inside another packed struct" {...@@ -1078,7 +1076,6 @@ test "assigning packed struct inside another packed struct" {
1078}1076}
10791077
1080test "packed struct used as part of anon decl name" {1078test "packed struct used as part of anon decl name" {
1081 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1082 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1079 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1083 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1080 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1084 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1081 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1107,7 +1104,13 @@ test "packed struct acts as a namespace" {...@@ -1107,7 +1104,13 @@ test "packed struct acts as a namespace" {
1107}1104}
11081105
1109test "pointer loaded correctly from packed struct" {1106test "pointer loaded correctly from packed struct" {
1107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1108 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1110 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1109 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1110 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
1111 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1112
1113 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // crashes MSVC
11111114
1112 const RAM = struct {1115 const RAM = struct {
1113 data: [0xFFFF + 1]u8,1116 data: [0xFFFF + 1]u8,
...@@ -1135,12 +1138,6 @@ test "pointer loaded correctly from packed struct" {...@@ -1135,12 +1138,6 @@ test "pointer loaded correctly from packed struct" {
1135 }1138 }
1136 }1139 }
1137 };1140 };
1138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1139 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1140 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
1141 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1142
1143 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // crashes MSVC
11441141
1145 var ram = try RAM.new();1142 var ram = try RAM.new();
1146 var cpu = try CPU.new(&ram);1143 var cpu = try CPU.new(&ram);
...@@ -1149,7 +1146,7 @@ test "pointer loaded correctly from packed struct" {...@@ -1149,7 +1146,7 @@ test "pointer loaded correctly from packed struct" {
1149}1146}
11501147
1151test "assignment to non-byte-aligned field in packed struct" {1148test "assignment to non-byte-aligned field in packed struct" {
1152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1154 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1151 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1155 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO1152 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
...@@ -1170,7 +1167,6 @@ test "assignment to non-byte-aligned field in packed struct" {...@@ -1170,7 +1167,6 @@ test "assignment to non-byte-aligned field in packed struct" {
1170}1167}
11711168
1172test "packed struct field pointer aligned properly" {1169test "packed struct field pointer aligned properly" {
1173 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1174 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1170 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1171 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1176 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO1172 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -1189,7 +1185,7 @@ test "packed struct field pointer aligned properly" {...@@ -1189,7 +1185,7 @@ test "packed struct field pointer aligned properly" {
1189}1185}
11901186
1191test "load flag from packed struct in union" {1187test "load flag from packed struct in union" {
1192 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1188 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1189 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1194 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1190 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1195 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1191 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1314,6 +1310,7 @@ test "packed struct equality" {...@@ -1314,6 +1310,7 @@ test "packed struct equality" {
1314}1310}
13151311
1316test "packed struct equality ignores padding bits" {1312test "packed struct equality ignores padding bits" {
1313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1317 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;1314 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1318 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1315 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13191316
...@@ -1325,6 +1322,8 @@ test "packed struct equality ignores padding bits" {...@@ -1325,6 +1322,8 @@ test "packed struct equality ignores padding bits" {
1325}1322}
13261323
1327test "packed struct with signed field" {1324test "packed struct with signed field" {
1325 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1326
1328 var s: packed struct {1327 var s: packed struct {
1329 a: i2,1328 a: i2,
1330 b: u6,1329 b: u6,
...@@ -1335,6 +1334,7 @@ test "packed struct with signed field" {...@@ -1335,6 +1334,7 @@ test "packed struct with signed field" {
1335}1334}
13361335
1337test "assign packed struct initialized with RLS to packed struct literal field" {1336test "assign packed struct initialized with RLS to packed struct literal field" {
1337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1338 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isWasm()) return error.SkipZigTest;1338 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isWasm()) return error.SkipZigTest;
1339 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1339 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1340 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1340 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1352,6 +1352,7 @@ test "assign packed struct initialized with RLS to packed struct literal field"...@@ -1352,6 +1352,7 @@ test "assign packed struct initialized with RLS to packed struct literal field"
1352}1352}
13531353
1354test "byte-aligned packed relocation" {1354test "byte-aligned packed relocation" {
1355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1355 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;1356 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1356 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;1357 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
1357 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1358 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1366,6 +1367,7 @@ test "byte-aligned packed relocation" {...@@ -1366,6 +1367,7 @@ test "byte-aligned packed relocation" {
1366}1367}
13671368
1368test "packed struct store of comparison result" {1369test "packed struct store of comparison result" {
1370 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1369 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1371 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1370 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO1372 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
13711373
test/behavior/packed-union.zig+3-3
...@@ -99,10 +99,10 @@ fn testFlagsInPackedUnionAtOffset() !void {...@@ -99,10 +99,10 @@ fn testFlagsInPackedUnionAtOffset() !void {
99 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_2);99 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_2);
100}100}
101101
102// Originally reported at https://github.com/ziglang/zig/issues/16581
102test "packed union in packed struct" {103test "packed union in packed struct" {
104 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
103 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;105 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
104
105 // Originally reported at https://github.com/ziglang/zig/issues/16581
106 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;106 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
107107
108 try testPackedUnionInPackedStruct();108 try testPackedUnionInPackedStruct();
...@@ -136,7 +136,7 @@ fn testPackedUnionInPackedStruct() !void {...@@ -136,7 +136,7 @@ fn testPackedUnionInPackedStruct() !void {
136}136}
137137
138test "packed union initialized with a runtime value" {138test "packed union initialized with a runtime value" {
139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
142 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;142 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/packed_struct_explicit_backing_int.zig-1
...@@ -5,7 +5,6 @@ const expectEqual = std.testing.expectEqual;...@@ -5,7 +5,6 @@ const expectEqual = std.testing.expectEqual;
5const native_endian = builtin.cpu.arch.endian();5const native_endian = builtin.cpu.arch.endian();
66
7test "packed struct explicit backing integer" {7test "packed struct explicit backing integer" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1110
test/behavior/pointers.zig+1-12
...@@ -18,7 +18,6 @@ fn testDerefPtr() !void {...@@ -18,7 +18,6 @@ fn testDerefPtr() !void {
18}18}
1919
20test "pointer-integer arithmetic" {20test "pointer-integer arithmetic" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;23 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -232,7 +231,6 @@ test "peer type resolution with C pointer and const pointer" {...@@ -232,7 +231,6 @@ test "peer type resolution with C pointer and const pointer" {
232231
233test "implicit casting between C pointer and optional non-C pointer" {232test "implicit casting between C pointer and optional non-C pointer" {
234 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;233 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
235 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
236 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO234 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
237 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;235 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
238 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;236 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -248,8 +246,8 @@ test "implicit casting between C pointer and optional non-C pointer" {...@@ -248,8 +246,8 @@ test "implicit casting between C pointer and optional non-C pointer" {
248}246}
249247
250test "implicit cast error unions with non-optional to optional pointer" {248test "implicit cast error unions with non-optional to optional pointer" {
249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO250 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
252 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
253 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO251 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
254 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;252 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
255 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;253 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -298,7 +296,6 @@ test "allowzero pointer and slice" {...@@ -298,7 +296,6 @@ test "allowzero pointer and slice" {
298296
299test "assign null directly to C pointer and test null equality" {297test "assign null directly to C pointer and test null equality" {
300 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO298 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
301 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
302 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO299 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
303 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;300 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
304301
...@@ -366,7 +363,6 @@ test "array initialization types" {...@@ -366,7 +363,6 @@ test "array initialization types" {
366}363}
367364
368test "null terminated pointer" {365test "null terminated pointer" {
369 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
370 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
371 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;367 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
372368
...@@ -384,7 +380,6 @@ test "null terminated pointer" {...@@ -384,7 +380,6 @@ test "null terminated pointer" {
384}380}
385381
386test "allow any sentinel" {382test "allow any sentinel" {
387 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
388 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO383 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
389 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;384 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
390 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;385 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -401,7 +396,6 @@ test "allow any sentinel" {...@@ -401,7 +396,6 @@ test "allow any sentinel" {
401}396}
402397
403test "pointer sentinel with enums" {398test "pointer sentinel with enums" {
404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO399 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
406 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;400 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
407 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;401 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -515,7 +509,6 @@ test "@intFromPtr on null optional at comptime" {...@@ -515,7 +509,6 @@ test "@intFromPtr on null optional at comptime" {
515}509}
516510
517test "indexing array with sentinel returns correct type" {511test "indexing array with sentinel returns correct type" {
518 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
519 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO512 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
520 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO513 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
521 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;514 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -525,7 +518,6 @@ test "indexing array with sentinel returns correct type" {...@@ -525,7 +518,6 @@ test "indexing array with sentinel returns correct type" {
525}518}
526519
527test "element pointer to slice" {520test "element pointer to slice" {
528 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
529 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO521 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
530 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;522 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
531523
...@@ -548,7 +540,6 @@ test "element pointer to slice" {...@@ -548,7 +540,6 @@ test "element pointer to slice" {
548}540}
549541
550test "element pointer arithmetic to slice" {542test "element pointer arithmetic to slice" {
551 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
552 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO543 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
553 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;544 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
554545
...@@ -604,7 +595,6 @@ test "pointer to constant decl preserves alignment" {...@@ -604,7 +595,6 @@ test "pointer to constant decl preserves alignment" {
604595
605test "ptrCast comptime known slice to C pointer" {596test "ptrCast comptime known slice to C pointer" {
606 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO597 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
607 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
608 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO598 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
609 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;599 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
610600
...@@ -625,7 +615,6 @@ test "pointer alignment and element type include call expression" {...@@ -625,7 +615,6 @@ test "pointer alignment and element type include call expression" {
625}615}
626616
627test "pointer to array has explicit alignment" {617test "pointer to array has explicit alignment" {
628 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
629 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;618 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
630619
631 const S = struct {620 const S = struct {
test/behavior/popcount.zig+2-3
...@@ -4,7 +4,6 @@ const expect = std.testing.expect;...@@ -4,7 +4,6 @@ const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;4const expectEqual = std.testing.expectEqual;
55
6test "@popCount integers" {6test "@popCount integers" {
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -15,7 +14,7 @@ test "@popCount integers" {...@@ -15,7 +14,7 @@ test "@popCount integers" {
15}14}
1615
17test "@popCount 128bit integer" {16test "@popCount 128bit integer" {
18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
20 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO19 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -77,8 +76,8 @@ fn testPopCountIntegers() !void {...@@ -77,8 +76,8 @@ fn testPopCountIntegers() !void {
77}76}
7877
79test "@popCount vectors" {78test "@popCount vectors" {
79 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
80 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO80 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
81 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
82 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO81 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
83 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO82 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;83 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/ptrcast.zig-19
...@@ -22,7 +22,6 @@ fn testReinterpretBytesAsInteger() !void {...@@ -22,7 +22,6 @@ fn testReinterpretBytesAsInteger() !void {
2222
23test "reinterpret an array over multiple elements, with no well-defined layout" {23test "reinterpret an array over multiple elements, with no well-defined layout" {
24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO25 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
27 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;26 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2827
...@@ -56,7 +55,6 @@ fn testReinterpretStructWrappedBytesAsInteger() !void {...@@ -56,7 +55,6 @@ fn testReinterpretStructWrappedBytesAsInteger() !void {
56}55}
5756
58test "reinterpret bytes of an array into an extern struct" {57test "reinterpret bytes of an array into an extern struct" {
59 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
60 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO58 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;59 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
6260
...@@ -130,7 +128,6 @@ fn testReinterpretOverAlignedExternStructAsExternStruct() !void {...@@ -130,7 +128,6 @@ fn testReinterpretOverAlignedExternStructAsExternStruct() !void {
130128
131test "lower reinterpreted comptime field ptr (with under-aligned fields)" {129test "lower reinterpreted comptime field ptr (with under-aligned fields)" {
132 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO131 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
135132
136 // Test lowering a field ptr133 // Test lowering a field ptr
...@@ -152,7 +149,6 @@ test "lower reinterpreted comptime field ptr (with under-aligned fields)" {...@@ -152,7 +149,6 @@ test "lower reinterpreted comptime field ptr (with under-aligned fields)" {
152149
153test "lower reinterpreted comptime field ptr" {150test "lower reinterpreted comptime field ptr" {
154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO152 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
157153
158 // Test lowering a field ptr154 // Test lowering a field ptr
...@@ -174,7 +170,6 @@ test "lower reinterpreted comptime field ptr" {...@@ -174,7 +170,6 @@ test "lower reinterpreted comptime field ptr" {
174170
175test "reinterpret struct field at comptime" {171test "reinterpret struct field at comptime" {
176 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO172 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
178 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;173 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
179174
180 const numNative = comptime Bytes.init(0x12345678);175 const numNative = comptime Bytes.init(0x12345678);
...@@ -232,7 +227,6 @@ test "ptrcast of const integer has the correct object size" {...@@ -232,7 +227,6 @@ test "ptrcast of const integer has the correct object size" {
232test "implicit optional pointer to optional anyopaque pointer" {227test "implicit optional pointer to optional anyopaque pointer" {
233 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO229 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
235 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
236 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;230 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
237231
238 var buf: [4]u8 = "aoeu".*;232 var buf: [4]u8 = "aoeu".*;
...@@ -244,7 +238,6 @@ test "implicit optional pointer to optional anyopaque pointer" {...@@ -244,7 +238,6 @@ test "implicit optional pointer to optional anyopaque pointer" {
244238
245test "@ptrCast slice to slice" {239test "@ptrCast slice to slice" {
246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO240 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
247 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
248 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO241 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
249 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;242 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
250243
...@@ -262,7 +255,6 @@ test "@ptrCast slice to slice" {...@@ -262,7 +255,6 @@ test "@ptrCast slice to slice" {
262255
263test "comptime @ptrCast a subset of an array, then write through it" {256test "comptime @ptrCast a subset of an array, then write through it" {
264 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO257 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
265 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
266 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO258 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
267259
268 comptime {260 comptime {
...@@ -354,7 +346,6 @@ test "@ptrCast restructures sliced comptime-only array" {...@@ -354,7 +346,6 @@ test "@ptrCast restructures sliced comptime-only array" {
354346
355test "@ptrCast slice multiplying length" {347test "@ptrCast slice multiplying length" {
356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO348 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
357 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
358 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO349 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
359 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;350 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
360351
...@@ -372,7 +363,6 @@ test "@ptrCast slice multiplying length" {...@@ -372,7 +363,6 @@ test "@ptrCast slice multiplying length" {
372363
373test "@ptrCast array pointer to slice multiplying length" {364test "@ptrCast array pointer to slice multiplying length" {
374 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO365 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
375 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
376 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
377 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;367 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
378368
...@@ -390,7 +380,6 @@ test "@ptrCast array pointer to slice multiplying length" {...@@ -390,7 +380,6 @@ test "@ptrCast array pointer to slice multiplying length" {
390380
391test "@ptrCast slice dividing length" {381test "@ptrCast slice dividing length" {
392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO382 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
394 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO383 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
395 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;384 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
396385
...@@ -408,7 +397,6 @@ test "@ptrCast slice dividing length" {...@@ -408,7 +397,6 @@ test "@ptrCast slice dividing length" {
408397
409test "@ptrCast array pointer to slice dividing length" {398test "@ptrCast array pointer to slice dividing length" {
410 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO399 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
411 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
412 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO400 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
413 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;401 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
414402
...@@ -426,7 +414,6 @@ test "@ptrCast array pointer to slice dividing length" {...@@ -426,7 +414,6 @@ test "@ptrCast array pointer to slice dividing length" {
426414
427test "@ptrCast slice with complex length increase" {415test "@ptrCast slice with complex length increase" {
428 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO416 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
430 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO417 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
431 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;418 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
432419
...@@ -447,7 +434,6 @@ test "@ptrCast slice with complex length increase" {...@@ -447,7 +434,6 @@ test "@ptrCast slice with complex length increase" {
447434
448test "@ptrCast array pointer to slice with complex length increase" {435test "@ptrCast array pointer to slice with complex length increase" {
449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO436 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
451 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO437 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
452 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;438 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
453439
...@@ -468,7 +454,6 @@ test "@ptrCast array pointer to slice with complex length increase" {...@@ -468,7 +454,6 @@ test "@ptrCast array pointer to slice with complex length increase" {
468454
469test "@ptrCast slice with complex length decrease" {455test "@ptrCast slice with complex length decrease" {
470 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO456 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
471 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
472 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO457 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;458 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
474459
...@@ -489,7 +474,6 @@ test "@ptrCast slice with complex length decrease" {...@@ -489,7 +474,6 @@ test "@ptrCast slice with complex length decrease" {
489474
490test "@ptrCast array pointer to slice with complex length decrease" {475test "@ptrCast array pointer to slice with complex length decrease" {
491 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
492 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
493 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO477 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
494 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;478 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
495479
...@@ -510,7 +494,6 @@ test "@ptrCast array pointer to slice with complex length decrease" {...@@ -510,7 +494,6 @@ test "@ptrCast array pointer to slice with complex length decrease" {
510494
511test "@ptrCast slice of zero-bit type to different slice" {495test "@ptrCast slice of zero-bit type to different slice" {
512 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO496 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
513 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO497 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
515 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;498 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
516499
...@@ -530,7 +513,6 @@ test "@ptrCast slice of zero-bit type to different slice" {...@@ -530,7 +513,6 @@ test "@ptrCast slice of zero-bit type to different slice" {
530513
531test "@ptrCast single-item pointer to slice with length 1" {514test "@ptrCast single-item pointer to slice with length 1" {
532 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
533 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO516 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
535 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;517 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
536 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO518 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
...@@ -552,7 +534,6 @@ test "@ptrCast single-item pointer to slice with length 1" {...@@ -552,7 +534,6 @@ test "@ptrCast single-item pointer to slice with length 1" {
552534
553test "@ptrCast single-item pointer to slice of bytes" {535test "@ptrCast single-item pointer to slice of bytes" {
554 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO536 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
555 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
556 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO537 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
557 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;538 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
558 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO539 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/ptrfromint.zig-3
...@@ -17,7 +17,6 @@ fn addressToFunction() void {...@@ -17,7 +17,6 @@ fn addressToFunction() void {
1717
18test "mutate through ptr initialized with constant ptrFromInt value" {18test "mutate through ptr initialized with constant ptrFromInt value" {
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO20 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;21 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2322
...@@ -35,7 +34,6 @@ fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {...@@ -35,7 +34,6 @@ fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
3534
36test "@ptrFromInt creates null pointer" {35test "@ptrFromInt creates null pointer" {
37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO37 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
40 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;38 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
4139
...@@ -45,7 +43,6 @@ test "@ptrFromInt creates null pointer" {...@@ -45,7 +43,6 @@ test "@ptrFromInt creates null pointer" {
4543
46test "@ptrFromInt creates allowzero zero pointer" {44test "@ptrFromInt creates allowzero zero pointer" {
47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
48 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
49 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO46 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5047
51 const ptr = @as(*allowzero u32, @ptrFromInt(0));48 const ptr = @as(*allowzero u32, @ptrFromInt(0));
test/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig-1
...@@ -6,7 +6,6 @@ const mem = std.mem;...@@ -6,7 +6,6 @@ const mem = std.mem;
6var ok: bool = false;6var ok: bool = false;
7test "reference a variable in an if after an if in the 2nd switch prong" {7test "reference a variable in an if after an if in the 2nd switch prong" {
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1211
test/behavior/reflection.zig-1
...@@ -26,7 +26,6 @@ fn dummy(a: bool, b: i32, c: f32) i32 {...@@ -26,7 +26,6 @@ fn dummy(a: bool, b: i32, c: f32) i32 {
26}26}
2727
28test "reflection: @field" {28test "reflection: @field" {
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3130
32 var f = Foo{31 var f = Foo{
test/behavior/return_address.zig+1-1
...@@ -6,7 +6,7 @@ fn retAddr() usize {...@@ -6,7 +6,7 @@ fn retAddr() usize {
6}6}
77
8test "return address" {8test "return address" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/saturating_arithmetic.zig+9-8
...@@ -5,7 +5,7 @@ const maxInt = std.math.maxInt;...@@ -5,7 +5,7 @@ const maxInt = std.math.maxInt;
5const expect = std.testing.expect;5const expect = std.testing.expect;
66
7test "saturating add" {7test "saturating add" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -52,8 +52,8 @@ test "saturating add" {...@@ -52,8 +52,8 @@ test "saturating add" {
52}52}
5353
54test "saturating add 128bit" {54test "saturating add 128bit" {
55 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
55 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO57 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO58 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
59 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;59 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -79,7 +79,7 @@ test "saturating add 128bit" {...@@ -79,7 +79,7 @@ test "saturating add 128bit" {
79}79}
8080
81test "saturating subtraction" {81test "saturating subtraction" {
82 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO82 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO83 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;85 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -125,8 +125,8 @@ test "saturating subtraction" {...@@ -125,8 +125,8 @@ test "saturating subtraction" {
125}125}
126126
127test "saturating subtraction 128bit" {127test "saturating subtraction 128bit" {
128 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
128 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO129 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
129 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
131 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO131 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
132 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;132 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -158,7 +158,6 @@ fn testSatMul(comptime T: type, a: T, b: T, expected: T) !void {...@@ -158,7 +158,6 @@ fn testSatMul(comptime T: type, a: T, b: T, expected: T) !void {
158}158}
159159
160test "saturating multiplication <= 32 bits" {160test "saturating multiplication <= 32 bits" {
161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
164 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -229,6 +228,7 @@ test "saturating multiplication <= 32 bits" {...@@ -229,6 +228,7 @@ test "saturating multiplication <= 32 bits" {
229}228}
230229
231test "saturating mul i64, i128" {230test "saturating mul i64, i128" {
231 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
232 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;232 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
233 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;233 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
234234
...@@ -256,8 +256,8 @@ test "saturating mul i64, i128" {...@@ -256,8 +256,8 @@ test "saturating mul i64, i128" {
256}256}
257257
258test "saturating multiplication" {258test "saturating multiplication" {
259 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO260 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
261 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO261 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
262 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO262 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
263 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;263 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -295,7 +295,7 @@ test "saturating multiplication" {...@@ -295,7 +295,7 @@ test "saturating multiplication" {
295}295}
296296
297test "saturating shift-left" {297test "saturating shift-left" {
298 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO298 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
299 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO299 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
300 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO300 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
301 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;301 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -340,6 +340,7 @@ test "saturating shift-left" {...@@ -340,6 +340,7 @@ test "saturating shift-left" {
340}340}
341341
342test "saturating shift-left large rhs" {342test "saturating shift-left large rhs" {
343 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
343 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;344 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
344 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;345 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
345 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;346 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -357,7 +358,7 @@ test "saturating shift-left large rhs" {...@@ -357,7 +358,7 @@ test "saturating shift-left large rhs" {
357}358}
358359
359test "saturating shl uses the LHS type" {360test "saturating shl uses the LHS type" {
360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO361 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
361 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO362 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
362 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
363 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;364 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/select.zig+3-2
...@@ -4,9 +4,9 @@ const mem = std.mem;...@@ -4,9 +4,9 @@ const mem = std.mem;
4const expect = std.testing.expect;4const expect = std.testing.expect;
55
6test "@select vectors" {6test "@select vectors" {
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -35,9 +35,9 @@ fn selectVectors() !void {...@@ -35,9 +35,9 @@ fn selectVectors() !void {
35}35}
3636
37test "@select arrays" {37test "@select arrays" {
38 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO39 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
39 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO40 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
40 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
41 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO41 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
42 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;42 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
43 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;43 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -66,6 +66,7 @@ fn selectArrays() !void {...@@ -66,6 +66,7 @@ fn selectArrays() !void {
66}66}
6767
68test "@select compare result" {68test "@select compare result" {
69 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
69 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;70 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
70 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;71 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;72 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
test/behavior/shuffle.zig+4-4
...@@ -5,7 +5,7 @@ const expect = std.testing.expect;...@@ -5,7 +5,7 @@ const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;5const expectEqual = std.testing.expectEqual;
66
7test "@shuffle int" {7test "@shuffle int" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -50,8 +50,8 @@ test "@shuffle int" {...@@ -50,8 +50,8 @@ test "@shuffle int" {
50}50}
5151
52test "@shuffle int strange sizes" {52test "@shuffle int strange sizes" {
53 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO54 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;57 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -132,8 +132,8 @@ fn testShuffle(...@@ -132,8 +132,8 @@ fn testShuffle(
132}132}
133133
134test "@shuffle bool 1" {134test "@shuffle bool 1" {
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
135 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;139 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -155,8 +155,8 @@ test "@shuffle bool 1" {...@@ -155,8 +155,8 @@ test "@shuffle bool 1" {
155}155}
156156
157test "@shuffle bool 2" {157test "@shuffle bool 2" {
158 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
158 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO159 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO161 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;162 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/sizeof_and_typeof.zig-3
...@@ -270,7 +270,6 @@ test "bitSizeOf comptime_int" {...@@ -270,7 +270,6 @@ test "bitSizeOf comptime_int" {
270}270}
271271
272test "runtime instructions inside typeof in comptime only scope" {272test "runtime instructions inside typeof in comptime only scope" {
273 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
274 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;273 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
275 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO274 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
276275
...@@ -326,7 +325,6 @@ test "lazy abi size used in comparison" {...@@ -326,7 +325,6 @@ test "lazy abi size used in comparison" {
326}325}
327326
328test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {327test "peer type resolution with @TypeOf doesn't trigger dependency loop check" {
329 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
330 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
331 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;329 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
332330
...@@ -437,7 +435,6 @@ test "Peer resolution of extern function calls in @TypeOf" {...@@ -437,7 +435,6 @@ test "Peer resolution of extern function calls in @TypeOf" {
437}435}
438436
439test "Extern function calls, dereferences and field access in @TypeOf" {437test "Extern function calls, dereferences and field access in @TypeOf" {
440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
441 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO438 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
442439
443 const Test = struct {440 const Test = struct {
test/behavior/slice.zig+2-22
...@@ -211,7 +211,6 @@ test "comptime pointer cast array and then slice" {...@@ -211,7 +211,6 @@ test "comptime pointer cast array and then slice" {
211}211}
212212
213test "slicing zero length array" {213test "slicing zero length array" {
214 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO214 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
216 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;215 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
217216
...@@ -273,7 +272,6 @@ test "result location zero sized array inside struct field implicit cast to slic...@@ -273,7 +272,6 @@ test "result location zero sized array inside struct field implicit cast to slic
273}272}
274273
275test "runtime safety lets us slice from len..len" {274test "runtime safety lets us slice from len..len" {
276 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;275 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO276 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
279 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;277 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -287,7 +285,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {...@@ -287,7 +285,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
287}285}
288286
289test "C pointer" {287test "C pointer" {
290 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
291 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO288 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
292 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;289 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
293290
...@@ -299,7 +296,6 @@ test "C pointer" {...@@ -299,7 +296,6 @@ test "C pointer" {
299}296}
300297
301test "C pointer slice access" {298test "C pointer slice access" {
302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;299 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO300 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
305 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;301 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -331,7 +327,6 @@ fn sliceSum(comptime q: []const u8) i32 {...@@ -331,7 +327,6 @@ fn sliceSum(comptime q: []const u8) i32 {
331}327}
332328
333test "slice type with custom alignment" {329test "slice type with custom alignment" {
334 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
335 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO330 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
336 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;331 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
337332
...@@ -390,7 +385,6 @@ test "empty array to slice" {...@@ -390,7 +385,6 @@ test "empty array to slice" {
390}385}
391386
392test "@ptrCast slice to pointer" {387test "@ptrCast slice to pointer" {
393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
394 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO388 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
395 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;389 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
396390
...@@ -445,7 +439,6 @@ test "slice multi-pointer without end" {...@@ -445,7 +439,6 @@ test "slice multi-pointer without end" {
445}439}
446440
447test "slice syntax resulting in pointer-to-array" {441test "slice syntax resulting in pointer-to-array" {
448 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO443 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
451 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;444 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -665,7 +658,6 @@ test "slice syntax resulting in pointer-to-array" {...@@ -665,7 +658,6 @@ test "slice syntax resulting in pointer-to-array" {
665}658}
666659
667test "slice pointer-to-array null terminated" {660test "slice pointer-to-array null terminated" {
668 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
669 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO661 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
670 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;662 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
671663
...@@ -718,7 +710,7 @@ test "slice pointer-to-array zero length" {...@@ -718,7 +710,7 @@ test "slice pointer-to-array zero length" {
718}710}
719711
720test "type coercion of pointer to anon struct literal to pointer to slice" {712test "type coercion of pointer to anon struct literal to pointer to slice" {
721 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO713 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
722 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO714 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
723 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO715 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
724 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;716 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -812,7 +804,6 @@ test "slice sentinel access at comptime" {...@@ -812,7 +804,6 @@ test "slice sentinel access at comptime" {
812}804}
813805
814test "slicing array with sentinel as end index" {806test "slicing array with sentinel as end index" {
815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
816 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO807 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
817 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;808 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
818809
...@@ -831,7 +822,6 @@ test "slicing array with sentinel as end index" {...@@ -831,7 +822,6 @@ test "slicing array with sentinel as end index" {
831}822}
832823
833test "slicing slice with sentinel as end index" {824test "slicing slice with sentinel as end index" {
834 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
835 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
836 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;826 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
837827
...@@ -888,7 +878,7 @@ test "slice field ptr var" {...@@ -888,7 +878,7 @@ test "slice field ptr var" {
888}878}
889879
890test "global slice field access" {880test "global slice field access" {
891 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO881 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
892 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO882 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
893 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO883 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
894 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;884 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -929,7 +919,6 @@ test "slice with dereferenced value" {...@@ -929,7 +919,6 @@ test "slice with dereferenced value" {
929}919}
930920
931test "empty slice ptr is non null" {921test "empty slice ptr is non null" {
932 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; // TODO
933 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Test assumes `undefined` is non-zero922 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Test assumes `undefined` is non-zero
934923
935 {924 {
...@@ -947,7 +936,6 @@ test "empty slice ptr is non null" {...@@ -947,7 +936,6 @@ test "empty slice ptr is non null" {
947}936}
948937
949test "slice decays to many pointer" {938test "slice decays to many pointer" {
950 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
951 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;939 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
952 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;940 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
953941
...@@ -957,7 +945,6 @@ test "slice decays to many pointer" {...@@ -957,7 +945,6 @@ test "slice decays to many pointer" {
957}945}
958946
959test "write through pointer to optional slice arg" {947test "write through pointer to optional slice arg" {
960 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
961 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;948 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
962 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;949 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
963 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;950 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -977,7 +964,6 @@ test "write through pointer to optional slice arg" {...@@ -977,7 +964,6 @@ test "write through pointer to optional slice arg" {
977}964}
978965
979test "modify slice length at comptime" {966test "modify slice length at comptime" {
980 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
981 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;967 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
982 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;968 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
983 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;969 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -994,7 +980,6 @@ test "modify slice length at comptime" {...@@ -994,7 +980,6 @@ test "modify slice length at comptime" {
994}980}
995981
996test "slicing zero length array field of struct" {982test "slicing zero length array field of struct" {
997 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
998 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO983 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
999 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;984 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1000 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;985 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1010,7 +995,6 @@ test "slicing zero length array field of struct" {...@@ -1010,7 +995,6 @@ test "slicing zero length array field of struct" {
1010}995}
1011996
1012test "slicing slices gives correct result" {997test "slicing slices gives correct result" {
1013 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1014 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO998 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1015 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;999 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10161000
...@@ -1024,7 +1008,6 @@ test "slicing slices gives correct result" {...@@ -1024,7 +1008,6 @@ test "slicing slices gives correct result" {
1024}1008}
10251009
1026test "get address of element of zero-sized slice" {1010test "get address of element of zero-sized slice" {
1027 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1028 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1011 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1029 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1012 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10301013
...@@ -1037,7 +1020,6 @@ test "get address of element of zero-sized slice" {...@@ -1037,7 +1020,6 @@ test "get address of element of zero-sized slice" {
1037}1020}
10381021
1039test "sentinel-terminated 0-length slices" {1022test "sentinel-terminated 0-length slices" {
1040 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1041 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1023 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1042 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1024 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10431025
...@@ -1058,8 +1040,6 @@ test "sentinel-terminated 0-length slices" {...@@ -1058,8 +1040,6 @@ test "sentinel-terminated 0-length slices" {
1058}1040}
10591041
1060test "peer slices keep abi alignment with empty struct" {1042test "peer slices keep abi alignment with empty struct" {
1061 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1062
1063 var cond: bool = undefined;1043 var cond: bool = undefined;
1064 cond = false;1044 cond = false;
1065 const slice = if (cond) &[1]u32{42} else &.{};1045 const slice = if (cond) &[1]u32{42} else &.{};
test/behavior/src.zig-1
...@@ -16,7 +16,6 @@ const expect = std.testing.expect;...@@ -16,7 +16,6 @@ const expect = std.testing.expect;
16const expectEqualStrings = std.testing.expectEqualStrings;16const expectEqualStrings = std.testing.expectEqualStrings;
1717
18test "@src" {18test "@src" {
19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
20 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO19 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO20 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;21 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/string_literals.zig+1-5
...@@ -6,7 +6,6 @@ const tag_name = @tagName(TestEnum.TestEnumValue);...@@ -6,7 +6,6 @@ const tag_name = @tagName(TestEnum.TestEnumValue);
6const ptr_tag_name: [*:0]const u8 = tag_name;6const ptr_tag_name: [*:0]const u8 = tag_name;
77
8test "@tagName() returns a string literal" {8test "@tagName() returns a string literal" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1211
...@@ -20,7 +19,6 @@ const error_name = @errorName(TestError.TestErrorCode);...@@ -20,7 +19,6 @@ const error_name = @errorName(TestError.TestErrorCode);
20const ptr_error_name: [*:0]const u8 = error_name;19const ptr_error_name: [*:0]const u8 = error_name;
2120
22test "@errorName() returns a string literal" {21test "@errorName() returns a string literal" {
23 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;23 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2624
...@@ -34,7 +32,6 @@ const type_name = @typeName(TestType);...@@ -34,7 +32,6 @@ const type_name = @typeName(TestType);
34const ptr_type_name: [*:0]const u8 = type_name;32const ptr_type_name: [*:0]const u8 = type_name;
3533
36test "@typeName() returns a string literal" {34test "@typeName() returns a string literal" {
37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
38 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO35 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
39 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
4037
...@@ -48,7 +45,6 @@ const ptr_actual_contents: [*:0]const u8 = actual_contents;...@@ -48,7 +45,6 @@ const ptr_actual_contents: [*:0]const u8 = actual_contents;
48const expected_contents = "hello zig\n";45const expected_contents = "hello zig\n";
4946
50test "@embedFile() returns a string literal" {47test "@embedFile() returns a string literal" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO48 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;49 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;50 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -64,7 +60,7 @@ fn testFnForSrc() std.builtin.SourceLocation {...@@ -64,7 +60,7 @@ fn testFnForSrc() std.builtin.SourceLocation {
64}60}
6561
66test "@src() returns a struct containing 0-terminated string slices" {62test "@src() returns a struct containing 0-terminated string slices" {
67 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO63 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
68 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO64 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
69 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;65 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
7066
test/behavior/struct.zig+17-45
...@@ -10,7 +10,6 @@ const maxInt = std.math.maxInt;...@@ -10,7 +10,6 @@ const maxInt = std.math.maxInt;
10top_level_field: i32,10top_level_field: i32,
1111
12test "top level fields" {12test "top level fields" {
13 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO13 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1514
16 var instance = @This(){15 var instance = @This(){
...@@ -87,7 +86,6 @@ const StructFoo = struct {...@@ -87,7 +86,6 @@ const StructFoo = struct {
87};86};
8887
89test "structs" {88test "structs" {
90 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
91 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;89 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
92 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO90 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
93 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;91 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -200,7 +198,6 @@ const MemberFnRand = struct {...@@ -200,7 +198,6 @@ const MemberFnRand = struct {
200};198};
201199
202test "return struct byval from function" {200test "return struct byval from function" {
203 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
204 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO201 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
205202
206 const Bar = struct {203 const Bar = struct {
...@@ -237,7 +234,6 @@ test "call method with mutable reference to struct with no fields" {...@@ -237,7 +234,6 @@ test "call method with mutable reference to struct with no fields" {
237}234}
238235
239test "struct field init with catch" {236test "struct field init with catch" {
240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
241 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO237 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
242238
243 const S = struct {239 const S = struct {
...@@ -280,7 +276,6 @@ const Val = struct {...@@ -280,7 +276,6 @@ const Val = struct {
280};276};
281277
282test "struct point to self" {278test "struct point to self" {
283 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO279 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
285 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;280 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
286281
...@@ -297,7 +292,6 @@ test "struct point to self" {...@@ -297,7 +292,6 @@ test "struct point to self" {
297}292}
298293
299test "void struct fields" {294test "void struct fields" {
300 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
301 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO295 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
302296
303 const foo = VoidStructFieldsFoo{297 const foo = VoidStructFieldsFoo{
...@@ -335,7 +329,6 @@ fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {...@@ -335,7 +329,6 @@ fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
335}329}
336330
337test "self-referencing struct via array member" {331test "self-referencing struct via array member" {
338 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO332 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
340 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO333 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
341 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;334 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -492,7 +485,7 @@ const Bitfields = packed struct {...@@ -492,7 +485,7 @@ const Bitfields = packed struct {
492};485};
493486
494test "packed struct fields are ordered from LSB to MSB" {487test "packed struct fields are ordered from LSB to MSB" {
495 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO488 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
496 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO489 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
497 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO490 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
498 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;491 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -610,7 +603,6 @@ fn getC(data: *const BitField1) u2 {...@@ -610,7 +603,6 @@ fn getC(data: *const BitField1) u2 {
610}603}
611604
612test "default struct initialization fields" {605test "default struct initialization fields" {
613 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
614 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO606 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
615607
616 const S = struct {608 const S = struct {
...@@ -634,8 +626,8 @@ test "default struct initialization fields" {...@@ -634,8 +626,8 @@ test "default struct initialization fields" {
634}626}
635627
636test "packed array 24bits" {628test "packed array 24bits" {
637 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
638 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;629 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
630 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
639 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO631 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
640 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;632 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
641633
...@@ -701,8 +693,8 @@ const FooArrayOfAligned = packed struct {...@@ -701,8 +693,8 @@ const FooArrayOfAligned = packed struct {
701};693};
702694
703test "pointer to packed struct member in a stack variable" {695test "pointer to packed struct member in a stack variable" {
696 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
704 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO697 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
705 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
706 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO698 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
707 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;699 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
708 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO700 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
...@@ -731,7 +723,6 @@ test "packed struct with u0 field access" {...@@ -731,7 +723,6 @@ test "packed struct with u0 field access" {
731}723}
732724
733test "access to global struct fields" {725test "access to global struct fields" {
734 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
735 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO726 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
736727
737 g_foo.bar.value = 42;728 g_foo.bar.value = 42;
...@@ -753,8 +744,8 @@ const S0 = struct {...@@ -753,8 +744,8 @@ const S0 = struct {
753var g_foo: S0 = S0.init();744var g_foo: S0 = S0.init();
754745
755test "packed struct with fp fields" {746test "packed struct with fp fields" {
747 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
756 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO748 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
757 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
758 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO749 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
759 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;750 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
760 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;751 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -783,7 +774,6 @@ test "packed struct with fp fields" {...@@ -783,7 +774,6 @@ test "packed struct with fp fields" {
783774
784test "fn with C calling convention returns struct by value" {775test "fn with C calling convention returns struct by value" {
785 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO776 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
786 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
787 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO777 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
788778
789 const S = struct {779 const S = struct {
...@@ -807,7 +797,7 @@ test "fn with C calling convention returns struct by value" {...@@ -807,7 +797,7 @@ test "fn with C calling convention returns struct by value" {
807}797}
808798
809test "non-packed struct with u128 entry in union" {799test "non-packed struct with u128 entry in union" {
810 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO800 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
811 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
812 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO802 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
813 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;803 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -834,8 +824,8 @@ test "non-packed struct with u128 entry in union" {...@@ -834,8 +824,8 @@ test "non-packed struct with u128 entry in union" {
834}824}
835825
836test "packed struct field passed to generic function" {826test "packed struct field passed to generic function" {
827 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
837 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO828 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
838 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
839 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO829 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
840 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;830 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
841831
...@@ -859,7 +849,6 @@ test "packed struct field passed to generic function" {...@@ -859,7 +849,6 @@ test "packed struct field passed to generic function" {
859}849}
860850
861test "anonymous struct literal syntax" {851test "anonymous struct literal syntax" {
862 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
863 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO852 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
864853
865 const S = struct {854 const S = struct {
...@@ -951,7 +940,6 @@ test "comptime struct field" {...@@ -951,7 +940,6 @@ test "comptime struct field" {
951test "tuple element initialized with fn call" {940test "tuple element initialized with fn call" {
952 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;941 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
953 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO942 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
954 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
955 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO943 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
956944
957 const S = struct {945 const S = struct {
...@@ -968,8 +956,8 @@ test "tuple element initialized with fn call" {...@@ -968,8 +956,8 @@ test "tuple element initialized with fn call" {
968}956}
969957
970test "struct with union field" {958test "struct with union field" {
959 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
971 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;960 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
972 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
973 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO961 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
974 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO962 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
975963
...@@ -990,7 +978,6 @@ test "struct with union field" {...@@ -990,7 +978,6 @@ test "struct with union field" {
990}978}
991979
992test "struct with 0-length union array field" {980test "struct with 0-length union array field" {
993 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
994 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO981 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
995 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO982 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
996983
...@@ -1039,6 +1026,7 @@ test "packed struct with undefined initializers" {...@@ -1039,6 +1026,7 @@ test "packed struct with undefined initializers" {
1039}1026}
10401027
1041test "for loop over pointers to struct, getting field from struct pointer" {1028test "for loop over pointers to struct, getting field from struct pointer" {
1029 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1042 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1030 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1043 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1031 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1044 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1032 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1078,7 +1066,7 @@ test "for loop over pointers to struct, getting field from struct pointer" {...@@ -1078,7 +1066,7 @@ test "for loop over pointers to struct, getting field from struct pointer" {
1078}1066}
10791067
1080test "anon init through error unions and optionals" {1068test "anon init through error unions and optionals" {
1081 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1069 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1082 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1070 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1083 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1071 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1084 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1072 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1105,7 +1093,7 @@ test "anon init through error unions and optionals" {...@@ -1105,7 +1093,7 @@ test "anon init through error unions and optionals" {
1105}1093}
11061094
1107test "anon init through optional" {1095test "anon init through optional" {
1108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1096 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1097 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1110 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1098 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1111 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1099 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1125,7 +1113,7 @@ test "anon init through optional" {...@@ -1125,7 +1113,7 @@ test "anon init through optional" {
1125}1113}
11261114
1127test "anon init through error union" {1115test "anon init through error union" {
1128 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1116 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1129 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1118 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1131 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1119 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1145,7 +1133,7 @@ test "anon init through error union" {...@@ -1145,7 +1133,7 @@ test "anon init through error union" {
1145}1133}
11461134
1147test "typed init through error unions and optionals" {1135test "typed init through error unions and optionals" {
1148 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1136 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1150 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11511139
...@@ -1171,7 +1159,6 @@ test "typed init through error unions and optionals" {...@@ -1171,7 +1159,6 @@ test "typed init through error unions and optionals" {
1171}1159}
11721160
1173test "initialize struct with empty literal" {1161test "initialize struct with empty literal" {
1174 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1175 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11761163
1177 const S = struct { x: i32 = 1234 };1164 const S = struct { x: i32 = 1234 };
...@@ -1206,7 +1193,7 @@ test "loading a struct pointer perfoms a copy" {...@@ -1206,7 +1193,7 @@ test "loading a struct pointer perfoms a copy" {
1206}1193}
12071194
1208test "packed struct aggregate init" {1195test "packed struct aggregate init" {
1209 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1197 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1211 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1198 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1212 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1199 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1226,7 +1213,7 @@ test "packed struct aggregate init" {...@@ -1226,7 +1213,7 @@ test "packed struct aggregate init" {
1226}1213}
12271214
1228test "packed struct field access via pointer" {1215test "packed struct field access via pointer" {
1229 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1230 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1217 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1231 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1218 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1232 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1219 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1267,7 +1254,6 @@ test "store to comptime field" {...@@ -1267,7 +1254,6 @@ test "store to comptime field" {
1267}1254}
12681255
1269test "struct field init value is size of the struct" {1256test "struct field init value is size of the struct" {
1270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1271 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1257 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12721258
1273 const namespace = struct {1259 const namespace = struct {
...@@ -1282,7 +1268,6 @@ test "struct field init value is size of the struct" {...@@ -1282,7 +1268,6 @@ test "struct field init value is size of the struct" {
1282}1268}
12831269
1284test "under-aligned struct field" {1270test "under-aligned struct field" {
1285 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1286 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1271 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1287 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1272 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1288 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1273 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1306,7 +1291,6 @@ test "under-aligned struct field" {...@@ -1306,7 +1291,6 @@ test "under-aligned struct field" {
1306}1291}
13071292
1308test "fieldParentPtr of a zero-bit field" {1293test "fieldParentPtr of a zero-bit field" {
1309 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1310 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1294 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1311 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1295 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1312 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1296 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1357,7 +1341,6 @@ test "fieldParentPtr of a zero-bit field" {...@@ -1357,7 +1341,6 @@ test "fieldParentPtr of a zero-bit field" {
13571341
1358test "struct field has a pointer to an aligned version of itself" {1342test "struct field has a pointer to an aligned version of itself" {
1359 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1343 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13611344
1362 const E = struct {1345 const E = struct {
1363 next: *align(1) @This(),1346 next: *align(1) @This(),
...@@ -1437,7 +1420,6 @@ test "discarded struct initialization works as expected" {...@@ -1437,7 +1420,6 @@ test "discarded struct initialization works as expected" {
1437}1420}
14381421
1439test "function pointer in struct returns the struct" {1422test "function pointer in struct returns the struct" {
1440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1441 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1423 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
14421424
1443 const A = struct {1425 const A = struct {
...@@ -1455,7 +1437,6 @@ test "function pointer in struct returns the struct" {...@@ -1455,7 +1437,6 @@ test "function pointer in struct returns the struct" {
14551437
1456test "no dependency loop on optional field wrapped in generic function" {1438test "no dependency loop on optional field wrapped in generic function" {
1457 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1439 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1458 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14591440
1460 const S = struct {1441 const S = struct {
1461 fn Atomic(comptime T: type) type {1442 fn Atomic(comptime T: type) type {
...@@ -1473,7 +1454,6 @@ test "no dependency loop on optional field wrapped in generic function" {...@@ -1473,7 +1454,6 @@ test "no dependency loop on optional field wrapped in generic function" {
1473}1454}
14741455
1475test "optional field init with tuple" {1456test "optional field init with tuple" {
1476 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1477 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1457 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14781458
1479 const S = struct {1459 const S = struct {
...@@ -1488,8 +1468,6 @@ test "optional field init with tuple" {...@@ -1488,8 +1468,6 @@ test "optional field init with tuple" {
1488}1468}
14891469
1490test "if inside struct init inside if" {1470test "if inside struct init inside if" {
1491 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1492
1493 const MyStruct = struct { x: u32 };1471 const MyStruct = struct { x: u32 };
1494 const b: u32 = 5;1472 const b: u32 = 5;
1495 var i: u32 = 1;1473 var i: u32 = 1;
...@@ -1580,7 +1558,6 @@ test "instantiate struct with comptime field" {...@@ -1580,7 +1558,6 @@ test "instantiate struct with comptime field" {
1580test "struct field pointer has correct alignment" {1558test "struct field pointer has correct alignment" {
1581 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1559 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1582 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1560 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1583 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1584 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1561 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15851562
1586 const S = struct {1563 const S = struct {
...@@ -1610,7 +1587,6 @@ test "struct field pointer has correct alignment" {...@@ -1610,7 +1587,6 @@ test "struct field pointer has correct alignment" {
1610test "extern struct field pointer has correct alignment" {1587test "extern struct field pointer has correct alignment" {
1611 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1588 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1612 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1589 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1613 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1614 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1590 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16151591
1616 const S = struct {1592 const S = struct {
...@@ -1828,7 +1804,6 @@ test "tuple with comptime-only field" {...@@ -1828,7 +1804,6 @@ test "tuple with comptime-only field" {
1828}1804}
18291805
1830test "extern struct fields are aligned to 1" {1806test "extern struct fields are aligned to 1" {
1831 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1832 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1807 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
18331808
1834 const Foo = extern struct {1809 const Foo = extern struct {
...@@ -1845,7 +1820,7 @@ test "extern struct fields are aligned to 1" {...@@ -1845,7 +1820,7 @@ test "extern struct fields are aligned to 1" {
1845}1820}
18461821
1847test "assign to slice.len of global variable" {1822test "assign to slice.len of global variable" {
1848 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1823 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1849 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1850 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1851 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1826 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1897,7 +1872,6 @@ test "array of structs inside struct initialized with undefined" {...@@ -1897,7 +1872,6 @@ test "array of structs inside struct initialized with undefined" {
1897}1872}
18981873
1899test "runtime call in nested initializer" {1874test "runtime call in nested initializer" {
1900 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1901 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1875 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1902 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1876 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19031877
...@@ -1929,7 +1903,6 @@ test "runtime call in nested initializer" {...@@ -1929,7 +1903,6 @@ test "runtime call in nested initializer" {
1929}1903}
19301904
1931test "runtime value in nested initializer passed as pointer to function" {1905test "runtime value in nested initializer passed as pointer to function" {
1932 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1933 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1906 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
19341907
1935 const Bar = struct {1908 const Bar = struct {
...@@ -1953,7 +1926,7 @@ test "runtime value in nested initializer passed as pointer to function" {...@@ -1953,7 +1926,7 @@ test "runtime value in nested initializer passed as pointer to function" {
1953}1926}
19541927
1955test "struct field default value is a call" {1928test "struct field default value is a call" {
1956 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1929 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1957 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1930 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1958 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1931 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
19591932
...@@ -2001,7 +1974,6 @@ test "aggregate initializers should allow initializing comptime fields, verifyin...@@ -2001,7 +1974,6 @@ test "aggregate initializers should allow initializing comptime fields, verifyin
20011974
2002test "assignment of field with padding" {1975test "assignment of field with padding" {
2003 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1976 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2004 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2005 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1977 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
20061978
2007 const Mesh = extern struct {1979 const Mesh = extern struct {
...@@ -2031,7 +2003,6 @@ test "assignment of field with padding" {...@@ -2031,7 +2003,6 @@ test "assignment of field with padding" {
20312003
2032test "initiate global variable with runtime value" {2004test "initiate global variable with runtime value" {
2033 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;2005 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2034 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2035 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2006 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
20362007
2037 const S = struct {2008 const S = struct {
...@@ -2126,6 +2097,7 @@ test "anonymous struct equivalence" {...@@ -2126,6 +2097,7 @@ test "anonymous struct equivalence" {
2126}2097}
21272098
2128test "field access through mem ptr arg" {2099test "field access through mem ptr arg" {
2100 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2129 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2101 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
21302102
2131 const S = struct {2103 const S = struct {
test/behavior/struct_contains_null_ptr_itself.zig-1
...@@ -3,7 +3,6 @@ const expect = std.testing.expect;...@@ -3,7 +3,6 @@ const expect = std.testing.expect;
3const builtin = @import("builtin");3const builtin = @import("builtin");
44
5test "struct contains null pointer which contains original struct" {5test "struct contains null pointer which contains original struct" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;7 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
98
test/behavior/struct_contains_slice_of_itself.zig+2-1
...@@ -12,6 +12,7 @@ const NodeAligned = struct {...@@ -12,6 +12,7 @@ const NodeAligned = struct {
12};12};
1313
14test "struct contains slice of itself" {14test "struct contains slice of itself" {
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1718
...@@ -52,7 +53,7 @@ test "struct contains slice of itself" {...@@ -52,7 +53,7 @@ test "struct contains slice of itself" {
52}53}
5354
54test "struct contains aligned slice of itself" {55test "struct contains aligned slice of itself" {
55 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
56 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO57 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;58 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
5859
test/behavior/switch.zig+20-13
...@@ -8,6 +8,7 @@ const minInt = std.math.minInt;...@@ -8,6 +8,7 @@ const minInt = std.math.minInt;
8const maxInt = std.math.maxInt;8const maxInt = std.math.maxInt;
99
10test "switch with numbers" {10test "switch with numbers" {
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;13 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1314
...@@ -43,7 +44,7 @@ fn testSwitchWithAllRanges(x: u32, y: u32) u32 {...@@ -43,7 +44,7 @@ fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
43}44}
4445
45test "switch arbitrary int size" {46test "switch arbitrary int size" {
46 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO47 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO48 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
48 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO49 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
49 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO50 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -274,8 +275,8 @@ const SwitchProngWithVarEnum = union(enum) {...@@ -274,8 +275,8 @@ const SwitchProngWithVarEnum = union(enum) {
274};275};
275276
276test "switch prong with variable" {277test "switch prong with variable" {
278 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO279 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
278 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
279 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO280 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
280 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;281 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
281282
...@@ -299,8 +300,8 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {...@@ -299,8 +300,8 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
299}300}
300301
301test "switch on enum using pointer capture" {302test "switch on enum using pointer capture" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
305306
306 try testSwitchEnumPtrCapture();307 try testSwitchEnumPtrCapture();
...@@ -360,8 +361,8 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {...@@ -360,8 +361,8 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
360}361}
361362
362test "switch on union with some prongs capturing" {363test "switch on union with some prongs capturing" {
364 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
363 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO365 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
364 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
365 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
366367
367 const X = union(enum) {368 const X = union(enum) {
...@@ -398,7 +399,6 @@ test "switch on const enum with var" {...@@ -398,7 +399,6 @@ test "switch on const enum with var" {
398}399}
399400
400test "anon enum literal used in switch on union enum" {401test "anon enum literal used in switch on union enum" {
401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
402 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO402 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
403403
404 const Foo = union(enum) {404 const Foo = union(enum) {
...@@ -469,8 +469,8 @@ test "switch on integer with else capturing expr" {...@@ -469,8 +469,8 @@ test "switch on integer with else capturing expr" {
469}469}
470470
471test "else prong of switch on error set excludes other cases" {471test "else prong of switch on error set excludes other cases" {
472 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO473 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
474 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO474 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
475 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;475 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
476 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;476 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -505,8 +505,8 @@ test "else prong of switch on error set excludes other cases" {...@@ -505,8 +505,8 @@ test "else prong of switch on error set excludes other cases" {
505}505}
506506
507test "switch prongs with error set cases make a new error set type for capture value" {507test "switch prongs with error set cases make a new error set type for capture value" {
508 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
508 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO509 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
509 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
510 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO510 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
511 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;511 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
512 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;512 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -563,7 +563,6 @@ test "return result loc and then switch with range implicit casted to error unio...@@ -563,7 +563,6 @@ test "return result loc and then switch with range implicit casted to error unio
563563
564test "switch with null and T peer types and inferred result location type" {564test "switch with null and T peer types and inferred result location type" {
565 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO565 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
566 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
567 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO566 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
568567
569 const S = struct {568 const S = struct {
...@@ -582,7 +581,7 @@ test "switch with null and T peer types and inferred result location type" {...@@ -582,7 +581,7 @@ test "switch with null and T peer types and inferred result location type" {
582}581}
583582
584test "switch prongs with cases with identical payload types" {583test "switch prongs with cases with identical payload types" {
585 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO584 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
586 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO585 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
587 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO586 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
588587
...@@ -689,7 +688,7 @@ test "switch prong pointer capture alignment" {...@@ -689,7 +688,7 @@ test "switch prong pointer capture alignment" {
689}688}
690689
691test "switch on pointer type" {690test "switch on pointer type" {
692 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO691 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
693 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO692 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
694 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;693 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
695694
...@@ -737,8 +736,8 @@ test "switch on error set with single else" {...@@ -737,8 +736,8 @@ test "switch on error set with single else" {
737}736}
738737
739test "switch capture copies its payload" {738test "switch capture copies its payload" {
739 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
740 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO740 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
741 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
742 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO741 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
743 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;742 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
744743
...@@ -831,6 +830,7 @@ test "comptime inline switch" {...@@ -831,6 +830,7 @@ test "comptime inline switch" {
831}830}
832831
833test "switch capture peer type resolution" {832test "switch capture peer type resolution" {
833 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
834 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;834 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
835835
836 const U = union(enum) {836 const U = union(enum) {
...@@ -848,6 +848,8 @@ test "switch capture peer type resolution" {...@@ -848,6 +848,8 @@ test "switch capture peer type resolution" {
848}848}
849849
850test "switch capture peer type resolution for in-memory coercible payloads" {850test "switch capture peer type resolution for in-memory coercible payloads" {
851 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
852
851 const T1 = c_int;853 const T1 = c_int;
852 const T2 = @Type(@typeInfo(T1));854 const T2 = @Type(@typeInfo(T1));
853855
...@@ -868,6 +870,8 @@ test "switch capture peer type resolution for in-memory coercible payloads" {...@@ -868,6 +870,8 @@ test "switch capture peer type resolution for in-memory coercible payloads" {
868}870}
869871
870test "switch pointer capture peer type resolution" {872test "switch pointer capture peer type resolution" {
873 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
874
871 const T1 = c_int;875 const T1 = c_int;
872 const T2 = @Type(@typeInfo(T1));876 const T2 = @Type(@typeInfo(T1));
873877
...@@ -904,6 +908,7 @@ test "inline switch range that includes the maximum value of the switched type"...@@ -904,6 +908,7 @@ test "inline switch range that includes the maximum value of the switched type"
904}908}
905909
906test "nested break ignores switch conditions and breaks instead" {910test "nested break ignores switch conditions and breaks instead" {
911 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
907 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;912 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
908 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;913 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
909914
...@@ -926,6 +931,7 @@ test "nested break ignores switch conditions and breaks instead" {...@@ -926,6 +931,7 @@ test "nested break ignores switch conditions and breaks instead" {
926}931}
927932
928test "peer type resolution on switch captures ignores unused payload bits" {933test "peer type resolution on switch captures ignores unused payload bits" {
934 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
929 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;935 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
930 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;936 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
931937
...@@ -951,7 +957,6 @@ test "peer type resolution on switch captures ignores unused payload bits" {...@@ -951,7 +957,6 @@ test "peer type resolution on switch captures ignores unused payload bits" {
951}957}
952958
953test "switch prong captures range" {959test "switch prong captures range" {
954 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
955 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO960 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
956 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO961 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
957962
...@@ -971,6 +976,8 @@ test "switch prong captures range" {...@@ -971,6 +976,8 @@ test "switch prong captures range" {
971}976}
972977
973test "prong with inline call to unreachable" {978test "prong with inline call to unreachable" {
979 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
980
974 const U = union(enum) {981 const U = union(enum) {
975 void: void,982 void: void,
976 bool: bool,983 bool: bool,
...@@ -1042,7 +1049,7 @@ test "labeled switch with break" {...@@ -1042,7 +1049,7 @@ test "labeled switch with break" {
1042}1049}
10431050
1044test "unlabeled break ignores switch" {1051test "unlabeled break ignores switch" {
1045 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1052 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1046 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1053 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1047 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1054 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1048 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO1055 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
test/behavior/switch_loop.zig+32-9
...@@ -3,7 +3,7 @@ const std = @import("std");...@@ -3,7 +3,7 @@ const std = @import("std");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "simple switch loop" {5test "simple switch loop" {
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -27,7 +27,7 @@ test "simple switch loop" {...@@ -27,7 +27,7 @@ test "simple switch loop" {
27}27}
2828
29test "switch loop with ranges" {29test "switch loop with ranges" {
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO33 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -48,7 +48,7 @@ test "switch loop with ranges" {...@@ -48,7 +48,7 @@ test "switch loop with ranges" {
48}48}
4949
50test "switch loop on enum" {50test "switch loop on enum" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO53 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
54 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO54 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -72,7 +72,7 @@ test "switch loop on enum" {...@@ -72,7 +72,7 @@ test "switch loop on enum" {
72}72}
7373
74test "switch loop with error set" {74test "switch loop with error set" {
75 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO75 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -96,7 +96,7 @@ test "switch loop with error set" {...@@ -96,7 +96,7 @@ test "switch loop with error set" {
96}96}
9797
98test "switch loop on tagged union" {98test "switch loop on tagged union" {
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -129,7 +129,7 @@ test "switch loop on tagged union" {...@@ -129,7 +129,7 @@ test "switch loop on tagged union" {
129}129}
130130
131test "switch loop dispatching instructions" {131test "switch loop dispatching instructions" {
132 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO132 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
133 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO133 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO134 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
135 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -179,7 +179,7 @@ test "switch loop dispatching instructions" {...@@ -179,7 +179,7 @@ test "switch loop dispatching instructions" {
179}179}
180180
181test "switch loop with pointer capture" {181test "switch loop with pointer capture" {
182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
183 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO183 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
184 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO184 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
185 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO185 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
...@@ -218,11 +218,34 @@ test "switch loop with pointer capture" {...@@ -218,11 +218,34 @@ test "switch loop with pointer capture" {
218}218}
219219
220test "unanalyzed continue with operand" {220test "unanalyzed continue with operand" {
221 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
222
223 @setRuntimeSafety(false);221 @setRuntimeSafety(false);
224 label: switch (false) {222 label: switch (false) {
225 false => if (false) continue :label true,223 false => if (false) continue :label true,
226 true => {},224 true => {},
227 }225 }
228}226}
227
228test "switch loop on larger than pointer integer" {
229 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
230 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
231 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
232
233 var entry: @Type(.{ .int = .{
234 .signedness = .unsigned,
235 .bits = @bitSizeOf(usize) + 1,
236 } }) = undefined;
237 entry = 0;
238 loop: switch (entry) {
239 0 => {
240 entry += 1;
241 continue :loop 1;
242 },
243 1 => |x| {
244 entry += 1;
245 continue :loop x + 1;
246 },
247 2 => entry += 1,
248 else => unreachable,
249 }
250 try expect(entry == 3);
251}
test/behavior/switch_on_captured_error.zig+2
...@@ -6,6 +6,7 @@ const expectEqual = std.testing.expectEqual;...@@ -6,6 +6,7 @@ const expectEqual = std.testing.expectEqual;
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8test "switch on error union catch capture" {8test "switch on error union catch capture" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1112
...@@ -300,6 +301,7 @@ test "switch on error union catch capture" {...@@ -300,6 +301,7 @@ test "switch on error union catch capture" {
300}301}
301302
302test "switch on error union if else capture" {303test "switch on error union if else capture" {
304 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
303 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;305 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;306 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
305307
test/behavior/switch_prong_err_enum.zig+1-1
...@@ -21,8 +21,8 @@ fn doThing(form_id: u64) anyerror!FormValue {...@@ -21,8 +21,8 @@ fn doThing(form_id: u64) anyerror!FormValue {
21}21}
2222
23test "switch prong returns error enum" {23test "switch prong returns error enum" {
24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
27 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;27 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2828
test/behavior/switch_prong_implicit_cast.zig+1-1
...@@ -15,8 +15,8 @@ fn foo(id: u64) !FormValue {...@@ -15,8 +15,8 @@ fn foo(id: u64) !FormValue {
15}15}
1616
17test "switch prong implicit cast" {17test "switch prong implicit cast" {
18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO20 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2121
22 const result = switch (foo(2) catch unreachable) {22 const result = switch (foo(2) catch unreachable) {
test/behavior/this.zig-2
...@@ -26,7 +26,6 @@ test "this refer to module call private fn" {...@@ -26,7 +26,6 @@ test "this refer to module call private fn" {
26}26}
2727
28test "this refer to container" {28test "this refer to container" {
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3130
32 var pt: Point(i32) = undefined;31 var pt: Point(i32) = undefined;
...@@ -47,7 +46,6 @@ fn prev(p: ?State) void {...@@ -47,7 +46,6 @@ fn prev(p: ?State) void {
47}46}
4847
49test "this used as optional function parameter" {48test "this used as optional function parameter" {
50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/threadlocal.zig-3
...@@ -4,7 +4,6 @@ const expect = std.testing.expect;...@@ -4,7 +4,6 @@ const expect = std.testing.expect;
44
5test "thread local variable" {5test "thread local variable" {
6 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -25,7 +24,6 @@ test "thread local variable" {...@@ -25,7 +24,6 @@ test "thread local variable" {
2524
26test "pointer to thread local array" {25test "pointer to thread local array" {
27 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO26 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO27 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO28 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;29 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -40,7 +38,6 @@ threadlocal var buffer: [11]u8 = undefined;...@@ -40,7 +38,6 @@ threadlocal var buffer: [11]u8 = undefined;
4038
41test "reference a global threadlocal variable" {39test "reference a global threadlocal variable" {
42 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO40 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
43 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO41 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO42 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
46 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;43 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/truncate.zig+1-1
...@@ -65,8 +65,8 @@ test "truncate on comptime integer" {...@@ -65,8 +65,8 @@ test "truncate on comptime integer" {
65}65}
6666
67test "truncate on vectors" {67test "truncate on vectors" {
68 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
69 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;68 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
69 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
70 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;70 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO71 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;72 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/try.zig+1-2
...@@ -47,7 +47,7 @@ test "try then not executed with assignment" {...@@ -47,7 +47,7 @@ test "try then not executed with assignment" {
47}47}
4848
49test "`try`ing an if/else expression" {49test "`try`ing an if/else expression" {
50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
52 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;52 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;53 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -68,7 +68,6 @@ test "`try`ing an if/else expression" {...@@ -68,7 +68,6 @@ test "`try`ing an if/else expression" {
68}68}
6969
70test "'return try' of empty error set in function returning non-error" {70test "'return try' of empty error set in function returning non-error" {
71 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
72 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO71 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
73 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;72 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
7473
test/behavior/tuple.zig+2-20
...@@ -8,7 +8,6 @@ const expectEqual = std.testing.expectEqual;...@@ -8,7 +8,6 @@ const expectEqual = std.testing.expectEqual;
88
9test "tuple concatenation" {9test "tuple concatenation" {
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1312
14 const S = struct {13 const S = struct {
...@@ -51,7 +50,6 @@ test "tuple multiplication" {...@@ -51,7 +50,6 @@ test "tuple multiplication" {
51}50}
5251
53test "more tuple concatenation" {52test "more tuple concatenation" {
54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO54 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;55 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -129,7 +127,6 @@ test "tuple initializer for var" {...@@ -129,7 +127,6 @@ test "tuple initializer for var" {
129}127}
130128
131test "array-like initializer for tuple types" {129test "array-like initializer for tuple types" {
132 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
133 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;131 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
135132
...@@ -216,7 +213,6 @@ test "initializing anon struct with explicit type" {...@@ -216,7 +213,6 @@ test "initializing anon struct with explicit type" {
216}213}
217214
218test "fieldParentPtr of tuple" {215test "fieldParentPtr of tuple" {
219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;216 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;218 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -229,7 +225,6 @@ test "fieldParentPtr of tuple" {...@@ -229,7 +225,6 @@ test "fieldParentPtr of tuple" {
229}225}
230226
231test "fieldParentPtr of anon struct" {227test "fieldParentPtr of anon struct" {
232 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
233 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;228 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
234 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO229 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
235 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;230 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -256,7 +251,6 @@ test "offsetOf anon struct" {...@@ -256,7 +251,6 @@ test "offsetOf anon struct" {
256}251}
257252
258test "initializing tuple with mixed comptime-runtime fields" {253test "initializing tuple with mixed comptime-runtime fields" {
259 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;254 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
261255
262 var x: u32 = 15;256 var x: u32 = 15;
...@@ -268,7 +262,6 @@ test "initializing tuple with mixed comptime-runtime fields" {...@@ -268,7 +262,6 @@ test "initializing tuple with mixed comptime-runtime fields" {
268}262}
269263
270test "initializing anon struct with mixed comptime-runtime fields" {264test "initializing anon struct with mixed comptime-runtime fields" {
271 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
272 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;265 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
273266
274 var x: u32 = 15;267 var x: u32 = 15;
...@@ -280,7 +273,6 @@ test "initializing anon struct with mixed comptime-runtime fields" {...@@ -280,7 +273,6 @@ test "initializing anon struct with mixed comptime-runtime fields" {
280}273}
281274
282test "tuple in tuple passed to generic function" {275test "tuple in tuple passed to generic function" {
283 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
284 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO276 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
285 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO277 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
286 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;278 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -300,7 +292,6 @@ test "tuple in tuple passed to generic function" {...@@ -300,7 +292,6 @@ test "tuple in tuple passed to generic function" {
300}292}
301293
302test "coerce tuple to tuple" {294test "coerce tuple to tuple" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO295 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO296 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
306 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;297 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -315,7 +306,6 @@ test "coerce tuple to tuple" {...@@ -315,7 +306,6 @@ test "coerce tuple to tuple" {
315}306}
316307
317test "tuple type with void field" {308test "tuple type with void field" {
318 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
319 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO309 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
320 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO310 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
321 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;311 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -353,7 +343,6 @@ test "zero sized struct in tuple handled correctly" {...@@ -353,7 +343,6 @@ test "zero sized struct in tuple handled correctly" {
353}343}
354344
355test "tuple type with void field and a runtime field" {345test "tuple type with void field and a runtime field" {
356 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
357 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO346 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
358 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;347 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
359348
...@@ -364,7 +353,6 @@ test "tuple type with void field and a runtime field" {...@@ -364,7 +353,6 @@ test "tuple type with void field and a runtime field" {
364}353}
365354
366test "branching inside tuple literal" {355test "branching inside tuple literal" {
367 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
368 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
369 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO357 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
370358
...@@ -410,7 +398,6 @@ test "tuple of struct concatenation and coercion to array" {...@@ -410,7 +398,6 @@ test "tuple of struct concatenation and coercion to array" {
410}398}
411399
412test "nested runtime conditionals in tuple initializer" {400test "nested runtime conditionals in tuple initializer" {
413 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
414 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO401 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
415 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO402 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
416 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;403 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -446,7 +433,6 @@ test "sentinel slice in tuple" {...@@ -446,7 +433,6 @@ test "sentinel slice in tuple" {
446}433}
447434
448test "tuple pointer is indexable" {435test "tuple pointer is indexable" {
449 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
450 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO436 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
451 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO437 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
452 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;438 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -470,7 +456,6 @@ test "tuple pointer is indexable" {...@@ -470,7 +456,6 @@ test "tuple pointer is indexable" {
470}456}
471457
472test "coerce anon tuple to tuple" {458test "coerce anon tuple to tuple" {
473 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
474 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO459 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
475 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO460 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
476461
...@@ -496,14 +481,12 @@ test "empty tuple type" {...@@ -496,14 +481,12 @@ test "empty tuple type" {
496}481}
497482
498test "tuple with comptime fields with non empty initializer" {483test "tuple with comptime fields with non empty initializer" {
499 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
500
501 const a: struct { comptime comptime_int = 0 } = .{0};484 const a: struct { comptime comptime_int = 0 } = .{0};
502 _ = a;485 _ = a;
503}486}
504487
505test "tuple with runtime value coerced into a slice with a sentinel" {488test "tuple with runtime value coerced into a slice with a sentinel" {
506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO489 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
507 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO490 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO491 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
509 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;492 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -578,7 +561,6 @@ test "comptime fields in tuple can be initialized" {...@@ -578,7 +561,6 @@ test "comptime fields in tuple can be initialized" {
578561
579test "empty struct in tuple" {562test "empty struct in tuple" {
580 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO563 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
581 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
582 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;564 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
583 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;565 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
584566
...@@ -591,7 +573,6 @@ test "empty struct in tuple" {...@@ -591,7 +573,6 @@ test "empty struct in tuple" {
591573
592test "empty union in tuple" {574test "empty union in tuple" {
593 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO575 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
594 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
595 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;576 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
596 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;577 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
597578
...@@ -604,6 +585,7 @@ test "empty union in tuple" {...@@ -604,6 +585,7 @@ test "empty union in tuple" {
604585
605test "field pointer of underaligned tuple" {586test "field pointer of underaligned tuple" {
606 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;587 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
588
607 const S = struct {589 const S = struct {
608 fn doTheTest() !void {590 fn doTheTest() !void {
609 const T = struct { u8, u32 };591 const T = struct { u8, u32 };
test/behavior/tuple_declarations.zig-2
...@@ -5,7 +5,6 @@ const expect = testing.expect;...@@ -5,7 +5,6 @@ const expect = testing.expect;
5const expectEqualStrings = testing.expectEqualStrings;5const expectEqualStrings = testing.expectEqualStrings;
66
7test "tuple declaration type info" {7test "tuple declaration type info" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1110
...@@ -34,7 +33,6 @@ test "tuple declaration type info" {...@@ -34,7 +33,6 @@ test "tuple declaration type info" {
34}33}
3534
36test "tuple declaration usage" {35test "tuple declaration usage" {
37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
4038
test/behavior/type.zig+3-6
...@@ -200,8 +200,8 @@ test "Type.ErrorUnion" {...@@ -200,8 +200,8 @@ test "Type.ErrorUnion" {
200}200}
201201
202test "Type.Opaque" {202test "Type.Opaque" {
203 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
203 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;206 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
207207
...@@ -258,8 +258,8 @@ test "Type.ErrorSet" {...@@ -258,8 +258,8 @@ test "Type.ErrorSet" {
258}258}
259259
260test "Type.Struct" {260test "Type.Struct" {
261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
261 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
262 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
264 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;264 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
265265
...@@ -348,7 +348,6 @@ test "Type.Struct" {...@@ -348,7 +348,6 @@ test "Type.Struct" {
348348
349test "Type.Enum" {349test "Type.Enum" {
350 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO350 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
351 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
352 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;351 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
353352
354 const Foo = @Type(.{353 const Foo = @Type(.{
...@@ -409,8 +408,8 @@ test "Type.Enum" {...@@ -409,8 +408,8 @@ test "Type.Enum" {
409}408}
410409
411test "Type.Union" {410test "Type.Union" {
411 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
412 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO412 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
413 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
414 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;413 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
415414
416 const Untagged = @Type(.{415 const Untagged = @Type(.{
...@@ -547,7 +546,6 @@ test "Type.Union from empty Type.Enum" {...@@ -547,7 +546,6 @@ test "Type.Union from empty Type.Enum" {
547546
548test "Type.Fn" {547test "Type.Fn" {
549 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO548 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
550 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
551549
552 const some_opaque = opaque {};550 const some_opaque = opaque {};
553 const some_ptr = *some_opaque;551 const some_ptr = *some_opaque;
...@@ -724,7 +722,6 @@ test "@Type should resolve its children types" {...@@ -724,7 +722,6 @@ test "@Type should resolve its children types" {
724}722}
725723
726test "struct field names sliced at comptime from larger string" {724test "struct field names sliced at comptime from larger string" {
727 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
728 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO725 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
729726
730 const text =727 const text =
test/behavior/type_info.zig+2-4
...@@ -158,7 +158,6 @@ fn testArray() !void {...@@ -158,7 +158,6 @@ fn testArray() !void {
158}158}
159159
160test "type info: error set, error union info, anyerror" {160test "type info: error set, error union info, anyerror" {
161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
162 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
164 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -190,7 +189,6 @@ fn testErrorSet() !void {...@@ -190,7 +189,6 @@ fn testErrorSet() !void {
190}189}
191190
192test "type info: error set single value" {191test "type info: error set single value" {
193 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
194 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO192 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
195 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
196 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;194 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -204,7 +202,6 @@ test "type info: error set single value" {...@@ -204,7 +202,6 @@ test "type info: error set single value" {
204}202}
205203
206test "type info: error set merged" {204test "type info: error set merged" {
207 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
208 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO205 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO206 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
210 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;207 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -221,7 +218,6 @@ test "type info: error set merged" {...@@ -221,7 +218,6 @@ test "type info: error set merged" {
221218
222test "type info: enum info" {219test "type info: enum info" {
223 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
224 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
225 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
226 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;222 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
227223
...@@ -362,6 +358,8 @@ test "type info: function type info" {...@@ -362,6 +358,8 @@ test "type info: function type info" {
362}358}
363359
364fn testFunction() !void {360fn testFunction() !void {
361 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
362
365 const S = struct {363 const S = struct {
366 export fn typeInfoFoo() callconv(.c) usize {364 export fn typeInfoFoo() callconv(.c) usize {
367 unreachable;365 unreachable;
test/behavior/typename.zig-8
...@@ -12,7 +12,6 @@ const expectStringStartsWith = std.testing.expectStringStartsWith;...@@ -12,7 +12,6 @@ const expectStringStartsWith = std.testing.expectStringStartsWith;
12// failures.12// failures.
1313
14test "anon fn param" {14test "anon fn param" {
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -38,7 +37,6 @@ test "anon fn param" {...@@ -38,7 +37,6 @@ test "anon fn param" {
38}37}
3938
40test "anon field init" {39test "anon field init" {
41 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO40 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
43 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO41 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;42 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -64,7 +62,6 @@ test "anon field init" {...@@ -64,7 +62,6 @@ test "anon field init" {
64}62}
6563
66test "basic" {64test "basic" {
67 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
69 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO66 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
70 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;67 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -86,7 +83,6 @@ test "basic" {...@@ -86,7 +83,6 @@ test "basic" {
86}83}
8784
88test "top level decl" {85test "top level decl" {
89 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
90 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO86 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
91 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
92 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;88 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -136,7 +132,6 @@ const B = struct {...@@ -136,7 +132,6 @@ const B = struct {
136};132};
137133
138test "fn param" {134test "fn param" {
139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
142 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;137 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -216,7 +211,6 @@ pub fn expectEqualStringsIgnoreDigits(expected: []const u8, actual: []const u8)...@@ -216,7 +211,6 @@ pub fn expectEqualStringsIgnoreDigits(expected: []const u8, actual: []const u8)
216}211}
217212
218test "local variable" {213test "local variable" {
219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO214 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
222 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;216 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -235,7 +229,6 @@ test "local variable" {...@@ -235,7 +229,6 @@ test "local variable" {
235}229}
236230
237test "comptime parameters not converted to anytype in function type" {231test "comptime parameters not converted to anytype in function type" {
238 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
240 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
241 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;234 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -245,7 +238,6 @@ test "comptime parameters not converted to anytype in function type" {...@@ -245,7 +238,6 @@ test "comptime parameters not converted to anytype in function type" {
245}238}
246239
247test "anon name strategy used in sub expression" {240test "anon name strategy used in sub expression" {
248 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
249 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
250 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO242 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
251 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;243 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/undefined.zig-4
...@@ -46,7 +46,6 @@ fn setFooX(foo: *Foo) void {...@@ -46,7 +46,6 @@ fn setFooX(foo: *Foo) void {
4646
47test "assign undefined to struct" {47test "assign undefined to struct" {
48 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;48 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
49 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
50 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO49 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5150
52 comptime {51 comptime {
...@@ -63,7 +62,6 @@ test "assign undefined to struct" {...@@ -63,7 +62,6 @@ test "assign undefined to struct" {
6362
64test "assign undefined to struct with method" {63test "assign undefined to struct with method" {
65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;64 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
67 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO65 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
6866
69 comptime {67 comptime {
...@@ -89,7 +87,6 @@ test "type name of undefined" {...@@ -89,7 +87,6 @@ test "type name of undefined" {
89var buf: []u8 = undefined;87var buf: []u8 = undefined;
9088
91test "reslice of undefined global var slice" {89test "reslice of undefined global var slice" {
92 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
93 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO90 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;91 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
9592
...@@ -100,7 +97,6 @@ test "reslice of undefined global var slice" {...@@ -100,7 +97,6 @@ test "reslice of undefined global var slice" {
100}97}
10198
102test "returned undef is 0xaa bytes when runtime safety is enabled" {99test "returned undef is 0xaa bytes when runtime safety is enabled" {
103 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
105 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;101 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
106 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;102 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
test/behavior/union.zig+60-60
...@@ -12,8 +12,8 @@ const FooWithFloats = union {...@@ -12,8 +12,8 @@ const FooWithFloats = union {
12};12};
1313
14test "basic unions with floats" {14test "basic unions with floats" {
15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
16 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO17 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;19 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -29,8 +29,8 @@ fn setFloat(foo: *FooWithFloats, x: f64) void {...@@ -29,8 +29,8 @@ fn setFloat(foo: *FooWithFloats, x: f64) void {
29}29}
3030
31test "init union with runtime value - floats" {31test "init union with runtime value - floats" {
32 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
35 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;35 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3636
...@@ -60,8 +60,8 @@ const Foo = union {...@@ -60,8 +60,8 @@ const Foo = union {
60};60};
6161
62test "init union with runtime value" {62test "init union with runtime value" {
63 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
64 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;63 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
64 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO65 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;66 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
67 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;67 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -160,8 +160,8 @@ test "unions embedded in aggregate types" {...@@ -160,8 +160,8 @@ test "unions embedded in aggregate types" {
160}160}
161161
162test "constant tagged union with payload" {162test "constant tagged union with payload" {
163 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;163 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166166
167 var empty = TaggedUnionWithPayload{ .Empty = {} };167 var empty = TaggedUnionWithPayload{ .Empty = {} };
...@@ -210,8 +210,8 @@ const Payload = union(Letter) {...@@ -210,8 +210,8 @@ const Payload = union(Letter) {
210};210};
211211
212test "union with specified enum tag" {212test "union with specified enum tag" {
213 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
214 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;213 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
214 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
216 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;216 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
217 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;217 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -221,8 +221,8 @@ test "union with specified enum tag" {...@@ -221,8 +221,8 @@ test "union with specified enum tag" {
221}221}
222222
223test "packed union generates correctly aligned type" {223test "packed union generates correctly aligned type" {
224 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;224 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
225 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
226 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO226 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
227 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;227 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
228 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;228 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -263,8 +263,8 @@ fn testComparison() !void {...@@ -263,8 +263,8 @@ fn testComparison() !void {
263}263}
264264
265test "comparison between union and enum literal" {265test "comparison between union and enum literal" {
266 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
267 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
267 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
268 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO268 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
269 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;269 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
270270
...@@ -279,8 +279,8 @@ const TheUnion = union(TheTag) {...@@ -279,8 +279,8 @@ const TheUnion = union(TheTag) {
279 C: i32,279 C: i32,
280};280};
281test "cast union to tag type of union" {281test "cast union to tag type of union" {
282 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
283 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
285285
286 try testCastUnionToTag();286 try testCastUnionToTag();
...@@ -300,8 +300,8 @@ test "union field access gives the enum values" {...@@ -300,8 +300,8 @@ test "union field access gives the enum values" {
300}300}
301301
302test "cast tag type of union to union" {302test "cast tag type of union to union" {
303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
306306
307 var x: Value2 = Letter2.B;307 var x: Value2 = Letter2.B;
...@@ -316,8 +316,8 @@ const Value2 = union(Letter2) {...@@ -316,8 +316,8 @@ const Value2 = union(Letter2) {
316};316};
317317
318test "implicit cast union to its tag type" {318test "implicit cast union to its tag type" {
319 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
320 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
322322
323 var x: Value2 = Letter2.B;323 var x: Value2 = Letter2.B;
...@@ -337,8 +337,8 @@ pub const PackThis = union(enum) {...@@ -337,8 +337,8 @@ pub const PackThis = union(enum) {
337};337};
338338
339test "constant packed union" {339test "constant packed union" {
340 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
341 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;340 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO342 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
343 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;343 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
344344
...@@ -357,7 +357,6 @@ const MultipleChoice = union(enum(u32)) {...@@ -357,7 +357,6 @@ const MultipleChoice = union(enum(u32)) {
357};357};
358test "simple union(enum(u32))" {358test "simple union(enum(u32))" {
359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
361 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO360 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
362361
363 var x = MultipleChoice.C;362 var x = MultipleChoice.C;
...@@ -403,7 +402,6 @@ test "assigning to union with zero size field" {...@@ -403,7 +402,6 @@ test "assigning to union with zero size field" {
403402
404test "tagged union initialization with runtime void" {403test "tagged union initialization with runtime void" {
405 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
406 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
407 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
408406
409 try expect(testTaggedUnionInit({}));407 try expect(testTaggedUnionInit({}));
...@@ -423,7 +421,6 @@ pub const UnionEnumNoPayloads = union(enum) { A, B };...@@ -423,7 +421,6 @@ pub const UnionEnumNoPayloads = union(enum) { A, B };
423421
424test "tagged union with no payloads" {422test "tagged union with no payloads" {
425 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;423 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
426 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
427 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO424 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
428425
429 const a = UnionEnumNoPayloads{ .B = {} };426 const a = UnionEnumNoPayloads{ .B = {} };
...@@ -470,7 +467,6 @@ var glbl: Foo1 = undefined;...@@ -470,7 +467,6 @@ var glbl: Foo1 = undefined;
470467
471test "global union with single field is correctly initialized" {468test "global union with single field is correctly initialized" {
472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;469 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
473 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
474 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO470 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
475471
476 glbl = Foo1{472 glbl = Foo1{
...@@ -487,8 +483,8 @@ pub const FooUnion = union(enum) {...@@ -487,8 +483,8 @@ pub const FooUnion = union(enum) {
487var glbl_array: [2]FooUnion = undefined;483var glbl_array: [2]FooUnion = undefined;
488484
489test "initialize global array of union" {485test "initialize global array of union" {
490 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
491 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;486 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
487 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
492 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO488 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
493 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;489 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
494490
...@@ -499,8 +495,8 @@ test "initialize global array of union" {...@@ -499,8 +495,8 @@ test "initialize global array of union" {
499}495}
500496
501test "update the tag value for zero-sized unions" {497test "update the tag value for zero-sized unions" {
502 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
503 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
499 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
504 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO500 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
505501
506 const S = union(enum) {502 const S = union(enum) {
...@@ -515,7 +511,6 @@ test "update the tag value for zero-sized unions" {...@@ -515,7 +511,6 @@ test "update the tag value for zero-sized unions" {
515511
516test "union initializer generates padding only if needed" {512test "union initializer generates padding only if needed" {
517 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;513 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
518 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
519 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
520515
521 const U = union(enum) {516 const U = union(enum) {
...@@ -528,7 +523,6 @@ test "union initializer generates padding only if needed" {...@@ -528,7 +523,6 @@ test "union initializer generates padding only if needed" {
528}523}
529524
530test "runtime tag name with single field" {525test "runtime tag name with single field" {
531 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
532 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO526 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
533 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;527 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
534528
...@@ -543,7 +537,6 @@ test "runtime tag name with single field" {...@@ -543,7 +537,6 @@ test "runtime tag name with single field" {
543537
544test "method call on an empty union" {538test "method call on an empty union" {
545 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;539 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
546 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
547 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO540 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
548541
549 const S = struct {542 const S = struct {
...@@ -604,8 +597,8 @@ test "tagged union type" {...@@ -604,8 +597,8 @@ test "tagged union type" {
604}597}
605598
606test "tagged union as return value" {599test "tagged union as return value" {
607 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
608 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;600 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
601 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
609 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO602 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
610 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;603 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
611 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;604 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -621,8 +614,8 @@ fn returnAnInt(x: i32) TaggedFoo {...@@ -621,8 +614,8 @@ fn returnAnInt(x: i32) TaggedFoo {
621}614}
622615
623test "tagged union with all void fields but a meaningful tag" {616test "tagged union with all void fields but a meaningful tag" {
624 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
625 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;617 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
618 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
626 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO619 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
627620
628 const S = struct {621 const S = struct {
...@@ -649,8 +642,8 @@ test "tagged union with all void fields but a meaningful tag" {...@@ -649,8 +642,8 @@ test "tagged union with all void fields but a meaningful tag" {
649}642}
650643
651test "union(enum(u32)) with specified and unspecified tag values" {644test "union(enum(u32)) with specified and unspecified tag values" {
652 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
653 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;645 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
646 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
654 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO647 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
655 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;648 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
656649
...@@ -687,7 +680,6 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {...@@ -687,7 +680,6 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) !void {
687}680}
688681
689test "switch on union with only 1 field" {682test "switch on union with only 1 field" {
690 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
691 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO683 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
692 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO684 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
693685
...@@ -742,8 +734,8 @@ test "union with only 1 field casted to its enum type which has enum value speci...@@ -742,8 +734,8 @@ test "union with only 1 field casted to its enum type which has enum value speci
742}734}
743735
744test "@intFromEnum works on unions" {736test "@intFromEnum works on unions" {
737 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
745 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO738 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
746 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
747 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO739 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
748740
749 const Bar = union(enum) {741 const Bar = union(enum) {
...@@ -801,8 +793,8 @@ fn Setter(comptime attr: Attribute) type {...@@ -801,8 +793,8 @@ fn Setter(comptime attr: Attribute) type {
801}793}
802794
803test "return union init with void payload" {795test "return union init with void payload" {
804 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
805 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;796 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
797 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
806 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO798 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
807799
808 const S = struct {800 const S = struct {
...@@ -825,7 +817,7 @@ test "return union init with void payload" {...@@ -825,7 +817,7 @@ test "return union init with void payload" {
825}817}
826818
827test "@unionInit stored to a const" {819test "@unionInit stored to a const" {
828 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO820 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
829 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO821 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
830 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO822 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
831 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;823 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -856,7 +848,7 @@ test "@unionInit stored to a const" {...@@ -856,7 +848,7 @@ test "@unionInit stored to a const" {
856}848}
857849
858test "@unionInit can modify a union type" {850test "@unionInit can modify a union type" {
859 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO851 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
860 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO852 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
861 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO853 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
862854
...@@ -879,7 +871,7 @@ test "@unionInit can modify a union type" {...@@ -879,7 +871,7 @@ test "@unionInit can modify a union type" {
879}871}
880872
881test "@unionInit can modify a pointer value" {873test "@unionInit can modify a pointer value" {
882 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO874 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
883 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO875 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
884 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO876 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
885877
...@@ -899,7 +891,6 @@ test "@unionInit can modify a pointer value" {...@@ -899,7 +891,6 @@ test "@unionInit can modify a pointer value" {
899}891}
900892
901test "union no tag with struct member" {893test "union no tag with struct member" {
902 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
903 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO894 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
904 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO895 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
905 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;896 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -935,8 +926,8 @@ test "extern union doesn't trigger field check at comptime" {...@@ -935,8 +926,8 @@ test "extern union doesn't trigger field check at comptime" {
935}926}
936927
937test "anonymous union literal syntax" {928test "anonymous union literal syntax" {
929 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
938 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO930 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
939 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
940 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO931 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
941 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;932 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
942 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;933 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -964,8 +955,8 @@ test "anonymous union literal syntax" {...@@ -964,8 +955,8 @@ test "anonymous union literal syntax" {
964}955}
965956
966test "function call result coerces from tagged union to the tag" {957test "function call result coerces from tagged union to the tag" {
958 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
967 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO959 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
968 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
969 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO960 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
970961
971 const S = struct {962 const S = struct {
...@@ -999,8 +990,8 @@ test "function call result coerces from tagged union to the tag" {...@@ -999,8 +990,8 @@ test "function call result coerces from tagged union to the tag" {
999}990}
1000991
1001test "switching on non exhaustive union" {992test "switching on non exhaustive union" {
993 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1002 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO994 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1003 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1004 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO995 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1005996
1006 const S = struct {997 const S = struct {
...@@ -1028,7 +1019,6 @@ test "switching on non exhaustive union" {...@@ -1028,7 +1019,6 @@ test "switching on non exhaustive union" {
10281019
1029test "containers with single-field enums" {1020test "containers with single-field enums" {
1030 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1021 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1031 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1032 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1022 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10331023
1034 const S = struct {1024 const S = struct {
...@@ -1057,8 +1047,8 @@ test "containers with single-field enums" {...@@ -1057,8 +1047,8 @@ test "containers with single-field enums" {
1057}1047}
10581048
1059test "@unionInit on union with tag but no fields" {1049test "@unionInit on union with tag but no fields" {
1050 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1060 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1051 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1061 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1062 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1052 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10631053
1064 const S = struct {1054 const S = struct {
...@@ -1106,7 +1096,7 @@ test "union enum type gets a separate scope" {...@@ -1106,7 +1096,7 @@ test "union enum type gets a separate scope" {
1106}1096}
11071097
1108test "global variable struct contains union initialized to non-most-aligned field" {1098test "global variable struct contains union initialized to non-most-aligned field" {
1109 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1099 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1110 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1112 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1102 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1133,8 +1123,8 @@ test "global variable struct contains union initialized to non-most-aligned fiel...@@ -1133,8 +1123,8 @@ test "global variable struct contains union initialized to non-most-aligned fiel
1133}1123}
11341124
1135test "union with no result loc initiated with a runtime value" {1125test "union with no result loc initiated with a runtime value" {
1126 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1136 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1127 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1138 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1128 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1139 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1129 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11401130
...@@ -1151,8 +1141,8 @@ test "union with no result loc initiated with a runtime value" {...@@ -1151,8 +1141,8 @@ test "union with no result loc initiated with a runtime value" {
1151}1141}
11521142
1153test "union with a large struct field" {1143test "union with a large struct field" {
1144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1156 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1146 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1157 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1147 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11581148
...@@ -1186,8 +1176,8 @@ test "comptime equality of extern unions with same tag" {...@@ -1186,8 +1176,8 @@ test "comptime equality of extern unions with same tag" {
1186}1176}
11871177
1188test "union tag is set when initiated as a temporary value at runtime" {1178test "union tag is set when initiated as a temporary value at runtime" {
1179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1189 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1180 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1190 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1191 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1181 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1192 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1182 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11931183
...@@ -1206,8 +1196,8 @@ test "union tag is set when initiated as a temporary value at runtime" {...@@ -1206,8 +1196,8 @@ test "union tag is set when initiated as a temporary value at runtime" {
1206}1196}
12071197
1208test "extern union most-aligned field is smaller" {1198test "extern union most-aligned field is smaller" {
1199 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1200 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1210 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1211 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1201 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1212 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1202 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12131203
...@@ -1226,8 +1216,8 @@ test "extern union most-aligned field is smaller" {...@@ -1226,8 +1216,8 @@ test "extern union most-aligned field is smaller" {
1226}1216}
12271217
1228test "return an extern union from C calling convention" {1218test "return an extern union from C calling convention" {
1219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1229 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1230 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1231 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1232 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12331223
...@@ -1258,7 +1248,7 @@ test "return an extern union from C calling convention" {...@@ -1258,7 +1248,7 @@ test "return an extern union from C calling convention" {
1258}1248}
12591249
1260test "noreturn field in union" {1250test "noreturn field in union" {
1261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1251 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1252 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1253 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12641254
...@@ -1309,7 +1299,7 @@ test "noreturn field in union" {...@@ -1309,7 +1299,7 @@ test "noreturn field in union" {
1309}1299}
13101300
1311test "@unionInit uses tag value instead of field index" {1301test "@unionInit uses tag value instead of field index" {
1312 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1313 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1314 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1304 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1315 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1305 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1339,7 +1329,6 @@ test "@unionInit uses tag value instead of field index" {...@@ -1339,7 +1329,6 @@ test "@unionInit uses tag value instead of field index" {
1339}1329}
13401330
1341test "union field ptr - zero sized payload" {1331test "union field ptr - zero sized payload" {
1342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1343 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1332 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1344 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1333 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1345 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1334 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1354,7 +1343,6 @@ test "union field ptr - zero sized payload" {...@@ -1354,7 +1343,6 @@ test "union field ptr - zero sized payload" {
1354}1343}
13551344
1356test "union field ptr - zero sized field" {1345test "union field ptr - zero sized field" {
1357 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1358 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1346 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1359 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1347 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1360 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1348 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1369,7 +1357,7 @@ test "union field ptr - zero sized field" {...@@ -1369,7 +1357,7 @@ test "union field ptr - zero sized field" {
1369}1357}
13701358
1371test "packed union in packed struct" {1359test "packed union in packed struct" {
1372 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1361 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1362 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13751363
...@@ -1420,8 +1408,8 @@ test "union int tag type is properly managed" {...@@ -1420,8 +1408,8 @@ test "union int tag type is properly managed" {
1420}1408}
14211409
1422test "no dependency loop when function pointer in union returns the union" {1410test "no dependency loop when function pointer in union returns the union" {
1411 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1423 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1412 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1424 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1425 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1413 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1426 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1414 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14271415
...@@ -1442,7 +1430,7 @@ test "no dependency loop when function pointer in union returns the union" {...@@ -1442,7 +1430,7 @@ test "no dependency loop when function pointer in union returns the union" {
1442}1430}
14431431
1444test "union reassignment can use previous value" {1432test "union reassignment can use previous value" {
1445 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1433 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1446 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1434 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1447 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1435 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14481436
...@@ -1456,7 +1444,7 @@ test "union reassignment can use previous value" {...@@ -1456,7 +1444,7 @@ test "union reassignment can use previous value" {
1456}1444}
14571445
1458test "packed union with zero-bit field" {1446test "packed union with zero-bit field" {
1459 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1447 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1460 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1448 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1461 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1449 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14621450
...@@ -1475,7 +1463,7 @@ test "packed union with zero-bit field" {...@@ -1475,7 +1463,7 @@ test "packed union with zero-bit field" {
1475}1463}
14761464
1477test "reinterpreting enum value inside packed union" {1465test "reinterpreting enum value inside packed union" {
1478 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1466 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1479 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1467 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14801468
1481 const U = packed union {1469 const U = packed union {
...@@ -1493,7 +1481,7 @@ test "reinterpreting enum value inside packed union" {...@@ -1493,7 +1481,7 @@ test "reinterpreting enum value inside packed union" {
1493}1481}
14941482
1495test "access the tag of a global tagged union" {1483test "access the tag of a global tagged union" {
1496 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1484 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14971485
1498 const U = union(enum) {1486 const U = union(enum) {
1499 a,1487 a,
...@@ -1504,7 +1492,7 @@ test "access the tag of a global tagged union" {...@@ -1504,7 +1492,7 @@ test "access the tag of a global tagged union" {
1504}1492}
15051493
1506test "coerce enum literal to union in result loc" {1494test "coerce enum literal to union in result loc" {
1507 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1495 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15081496
1509 const U = union(enum) {1497 const U = union(enum) {
1510 a,1498 a,
...@@ -1522,7 +1510,6 @@ test "coerce enum literal to union in result loc" {...@@ -1522,7 +1510,6 @@ test "coerce enum literal to union in result loc" {
1522test "defined-layout union field pointer has correct alignment" {1510test "defined-layout union field pointer has correct alignment" {
1523 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1511 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1524 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1512 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1525 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1526 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1513 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15271514
1528 const S = struct {1515 const S = struct {
...@@ -1557,7 +1544,6 @@ test "defined-layout union field pointer has correct alignment" {...@@ -1557,7 +1544,6 @@ test "defined-layout union field pointer has correct alignment" {
1557test "undefined-layout union field pointer has correct alignment" {1544test "undefined-layout union field pointer has correct alignment" {
1558 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1545 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1559 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1546 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1560 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1561 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1547 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15621548
1563 const S = struct {1549 const S = struct {
...@@ -1590,8 +1576,8 @@ test "undefined-layout union field pointer has correct alignment" {...@@ -1590,8 +1576,8 @@ test "undefined-layout union field pointer has correct alignment" {
1590}1576}
15911577
1592test "packed union field pointer has correct alignment" {1578test "packed union field pointer has correct alignment" {
1579 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1593 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1580 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1594 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1595 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1581 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1596 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO1582 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
15971583
...@@ -1624,6 +1610,7 @@ test "packed union field pointer has correct alignment" {...@@ -1624,6 +1610,7 @@ test "packed union field pointer has correct alignment" {
1624}1610}
16251611
1626test "union with 128 bit integer" {1612test "union with 128 bit integer" {
1613 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1627 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1614 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16281615
1629 const ValueTag = enum { int, other };1616 const ValueTag = enum { int, other };
...@@ -1647,6 +1634,7 @@ test "union with 128 bit integer" {...@@ -1647,6 +1634,7 @@ test "union with 128 bit integer" {
1647}1634}
16481635
1649test "memset extern union" {1636test "memset extern union" {
1637 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1650 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1638 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16511639
1652 const U = extern union {1640 const U = extern union {
...@@ -1668,6 +1656,7 @@ test "memset extern union" {...@@ -1668,6 +1656,7 @@ test "memset extern union" {
1668}1656}
16691657
1670test "memset packed union" {1658test "memset packed union" {
1659 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1671 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1660 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
16721661
1673 const U = packed union {1662 const U = packed union {
...@@ -1768,6 +1757,7 @@ test "reinterpret extern union" {...@@ -1768,6 +1757,7 @@ test "reinterpret extern union" {
1768}1757}
17691758
1770test "reinterpret packed union" {1759test "reinterpret packed union" {
1760 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1771 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1761 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17721762
1773 const U = packed union {1763 const U = packed union {
...@@ -1840,6 +1830,7 @@ test "reinterpret packed union" {...@@ -1840,6 +1830,7 @@ test "reinterpret packed union" {
1840}1830}
18411831
1842test "reinterpret packed union inside packed struct" {1832test "reinterpret packed union inside packed struct" {
1833 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1843 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1834 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1844 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO1835 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
18451836
...@@ -1945,6 +1936,8 @@ test "extern union initialized via reintepreted struct field initializer" {...@@ -1945,6 +1936,8 @@ test "extern union initialized via reintepreted struct field initializer" {
1945}1936}
19461937
1947test "packed union initialized via reintepreted struct field initializer" {1938test "packed union initialized via reintepreted struct field initializer" {
1939 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1940
1948 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };1941 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
19491942
1950 const U = packed union {1943 const U = packed union {
...@@ -1963,6 +1956,7 @@ test "packed union initialized via reintepreted struct field initializer" {...@@ -1963,6 +1956,7 @@ test "packed union initialized via reintepreted struct field initializer" {
1963}1956}
19641957
1965test "store of comptime reinterpreted memory to extern union" {1958test "store of comptime reinterpreted memory to extern union" {
1959 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1966 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1960 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
19671961
1968 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };1962 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
...@@ -1985,6 +1979,8 @@ test "store of comptime reinterpreted memory to extern union" {...@@ -1985,6 +1979,8 @@ test "store of comptime reinterpreted memory to extern union" {
1985}1979}
19861980
1987test "store of comptime reinterpreted memory to packed union" {1981test "store of comptime reinterpreted memory to packed union" {
1982 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1983
1988 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };1984 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
19891985
1990 const U = packed union {1986 const U = packed union {
...@@ -2005,7 +2001,6 @@ test "store of comptime reinterpreted memory to packed union" {...@@ -2005,7 +2001,6 @@ test "store of comptime reinterpreted memory to packed union" {
2005}2001}
20062002
2007test "union field is a pointer to an aligned version of itself" {2003test "union field is a pointer to an aligned version of itself" {
2008 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2009 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2004 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2010 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2005 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
20112006
...@@ -2019,6 +2014,7 @@ test "union field is a pointer to an aligned version of itself" {...@@ -2019,6 +2014,7 @@ test "union field is a pointer to an aligned version of itself" {
2019}2014}
20202015
2021test "pass register-sized field as non-register-sized union" {2016test "pass register-sized field as non-register-sized union" {
2017 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2022 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2018 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2023 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2019 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
20242020
...@@ -2067,6 +2063,7 @@ test "circular dependency through pointer field of a union" {...@@ -2067,6 +2063,7 @@ test "circular dependency through pointer field of a union" {
2067}2063}
20682064
2069test "pass nested union with rls" {2065test "pass nested union with rls" {
2066 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2070 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2067 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2071 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2068 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
20722069
...@@ -2088,8 +2085,8 @@ test "pass nested union with rls" {...@@ -2088,8 +2085,8 @@ test "pass nested union with rls" {
2088}2085}
20892086
2090test "runtime union init, most-aligned field != largest" {2087test "runtime union init, most-aligned field != largest" {
2088 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2091 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2089 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2092 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2093 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2090 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2094 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2091 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2095 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2092 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -2114,8 +2111,8 @@ test "runtime union init, most-aligned field != largest" {...@@ -2114,8 +2111,8 @@ test "runtime union init, most-aligned field != largest" {
2114}2111}
21152112
2116test "copied union field doesn't alias source" {2113test "copied union field doesn't alias source" {
2114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2116 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2120 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2117 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
21212118
...@@ -2134,7 +2131,7 @@ test "copied union field doesn't alias source" {...@@ -2134,7 +2131,7 @@ test "copied union field doesn't alias source" {
2134}2131}
21352132
2136test "create union(enum) from other union(enum)" {2133test "create union(enum) from other union(enum)" {
2137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2134 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2135 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2139 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2136 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2140 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2137 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -2258,7 +2255,7 @@ test "matching captures causes union equivalence" {...@@ -2258,7 +2255,7 @@ test "matching captures causes union equivalence" {
2258}2255}
22592256
2260test "signed enum tag with negative value" {2257test "signed enum tag with negative value" {
2261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2258 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2259 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2263 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2260 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2264 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2261 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -2315,6 +2312,7 @@ test "extern union @FieldType" {...@@ -2315,6 +2312,7 @@ test "extern union @FieldType" {
2315}2312}
23162313
2317test "assign global tagged union" {2314test "assign global tagged union" {
2315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2318 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2316 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
23192317
2320 const U = union(enum) {2318 const U = union(enum) {
...@@ -2336,6 +2334,8 @@ test "assign global tagged union" {...@@ -2336,6 +2334,8 @@ test "assign global tagged union" {
2336}2334}
23372335
2338test "set mutable union by switching on same union" {2336test "set mutable union by switching on same union" {
2337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2338
2339 const U = union(enum) {2339 const U = union(enum) {
2340 foo,2340 foo,
2341 bar: usize,2341 bar: usize,
test/behavior/union_with_members.zig+1-1
...@@ -17,8 +17,8 @@ const ET = union(enum) {...@@ -17,8 +17,8 @@ const ET = union(enum) {
17};17};
1818
19test "enum with members" {19test "enum with members" {
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;23 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2424
test/behavior/var_args.zig+10-12
...@@ -28,7 +28,6 @@ test "send void arg to var args" {...@@ -28,7 +28,6 @@ test "send void arg to var args" {
28}28}
2929
30test "pass args directly" {30test "pass args directly" {
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3332
34 try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);33 try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
...@@ -41,7 +40,6 @@ fn addSomeStuff(args: anytype) i32 {...@@ -41,7 +40,6 @@ fn addSomeStuff(args: anytype) i32 {
41}40}
4241
43test "runtime parameter before var args" {42test "runtime parameter before var args" {
44 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO43 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4644
47 try expect((try extraFn(10, .{})) == 0);45 try expect((try extraFn(10, .{})) == 0);
...@@ -94,13 +92,13 @@ fn doNothingWithFirstArg(args: anytype) void {...@@ -94,13 +92,13 @@ fn doNothingWithFirstArg(args: anytype) void {
94}92}
9593
96test "simple variadic function" {94test "simple variadic function" {
97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO95 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
98 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO96 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO97 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO98 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
101 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;99 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
102 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;100 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
103 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {101 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
104 // https://github.com/ziglang/zig/issues/14096102 // https://github.com/ziglang/zig/issues/14096
105 return error.SkipZigTest;103 return error.SkipZigTest;
106 }104 }
...@@ -156,13 +154,13 @@ test "simple variadic function" {...@@ -156,13 +154,13 @@ test "simple variadic function" {
156}154}
157155
158test "coerce reference to var arg" {156test "coerce reference to var arg" {
159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO157 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO160 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;161 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;162 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
165 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {163 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
166 // https://github.com/ziglang/zig/issues/14096164 // https://github.com/ziglang/zig/issues/14096
167 return error.SkipZigTest;165 return error.SkipZigTest;
168 }166 }
...@@ -189,13 +187,13 @@ test "coerce reference to var arg" {...@@ -189,13 +187,13 @@ test "coerce reference to var arg" {
189}187}
190188
191test "variadic functions" {189test "variadic functions" {
192 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO190 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO191 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
194 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO192 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
195 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO193 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
196 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;194 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
197 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;195 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
198 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {196 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
199 // https://github.com/ziglang/zig/issues/14096197 // https://github.com/ziglang/zig/issues/14096
200 return error.SkipZigTest;198 return error.SkipZigTest;
201 }199 }
...@@ -236,12 +234,12 @@ test "variadic functions" {...@@ -236,12 +234,12 @@ test "variadic functions" {
236}234}
237235
238test "copy VaList" {236test "copy VaList" {
239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO237 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
240 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO238 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
241 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO239 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
242 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;240 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
243 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;241 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
244 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {242 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
245 // https://github.com/ziglang/zig/issues/14096243 // https://github.com/ziglang/zig/issues/14096
246 return error.SkipZigTest;244 return error.SkipZigTest;
247 }245 }
...@@ -271,12 +269,12 @@ test "copy VaList" {...@@ -271,12 +269,12 @@ test "copy VaList" {
271}269}
272270
273test "unused VaList arg" {271test "unused VaList arg" {
274 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO272 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
275 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO273 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
276 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO274 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
277 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;275 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
278 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;276 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
279 if (builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {277 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag != .macos and builtin.cpu.arch.isAARCH64()) {
280 // https://github.com/ziglang/zig/issues/14096278 // https://github.com/ziglang/zig/issues/14096
281 return error.SkipZigTest;279 return error.SkipZigTest;
282 }280 }
test/behavior/vector.zig+43-55
...@@ -8,7 +8,6 @@ const expectEqual = std.testing.expectEqual;...@@ -8,7 +8,6 @@ const expectEqual = std.testing.expectEqual;
88
9test "implicit cast vector to array - bool" {9test "implicit cast vector to array - bool" {
10 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;13 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -25,8 +24,8 @@ test "implicit cast vector to array - bool" {...@@ -25,8 +24,8 @@ test "implicit cast vector to array - bool" {
25}24}
2625
27test "vector wrap operators" {26test "vector wrap operators" {
27 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO28 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;31 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -49,8 +48,8 @@ test "vector wrap operators" {...@@ -49,8 +48,8 @@ test "vector wrap operators" {
49}48}
5049
51test "vector bin compares with mem.eql" {50test "vector bin compares with mem.eql" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
53 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
54 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO54 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;55 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -74,8 +73,8 @@ test "vector bin compares with mem.eql" {...@@ -74,8 +73,8 @@ test "vector bin compares with mem.eql" {
74}73}
7574
76test "vector int operators" {75test "vector int operators" {
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
80 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
81 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;80 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -97,8 +96,8 @@ test "vector int operators" {...@@ -97,8 +96,8 @@ test "vector int operators" {
97}96}
9897
99test "vector float operators" {98test "vector float operators" {
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
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_aarch64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;103 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -141,8 +140,8 @@ test "vector float operators" {...@@ -141,8 +140,8 @@ test "vector float operators" {
141}140}
142141
143test "vector bit operators" {142test "vector bit operators" {
143 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
144 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO144 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO145 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
147 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO146 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
148 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;147 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -173,7 +172,7 @@ test "vector bit operators" {...@@ -173,7 +172,7 @@ test "vector bit operators" {
173}172}
174173
175test "implicit cast vector to array" {174test "implicit cast vector to array" {
176 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO175 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
177 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO176 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
178 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO177 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
179 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;178 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -193,7 +192,7 @@ test "implicit cast vector to array" {...@@ -193,7 +192,7 @@ test "implicit cast vector to array" {
193}192}
194193
195test "array to vector" {194test "array to vector" {
196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO195 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
197 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO196 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
198 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO197 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
199 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;198 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -212,7 +211,7 @@ test "array to vector" {...@@ -212,7 +211,7 @@ test "array to vector" {
212}211}
213212
214test "array vector coercion - odd sizes" {213test "array vector coercion - odd sizes" {
215 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO214 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
216 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO215 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
217 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO216 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
218 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;217 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
...@@ -251,7 +250,7 @@ test "array vector coercion - odd sizes" {...@@ -251,7 +250,7 @@ test "array vector coercion - odd sizes" {
251}250}
252251
253test "array to vector with element type coercion" {252test "array to vector with element type coercion" {
254 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO253 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
255 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO254 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
256 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO255 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
257 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO256 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
...@@ -273,7 +272,6 @@ test "array to vector with element type coercion" {...@@ -273,7 +272,6 @@ test "array to vector with element type coercion" {
273272
274test "peer type resolution with coercible element types" {273test "peer type resolution with coercible element types" {
275 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO274 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
276 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO275 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO276 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
279277
...@@ -291,8 +289,8 @@ test "peer type resolution with coercible element types" {...@@ -291,8 +289,8 @@ test "peer type resolution with coercible element types" {
291}289}
292290
293test "tuple to vector" {291test "tuple to vector" {
292 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
294 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO293 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
295 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
296 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO294 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
297 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO295 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
298 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;296 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -314,8 +312,8 @@ test "tuple to vector" {...@@ -314,8 +312,8 @@ test "tuple to vector" {
314}312}
315313
316test "vector casts of sizes not divisible by 8" {314test "vector casts of sizes not divisible by 8" {
315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
317 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO316 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
319 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO317 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
320 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO318 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
321 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;319 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -354,7 +352,7 @@ test "vector casts of sizes not divisible by 8" {...@@ -354,7 +352,7 @@ test "vector casts of sizes not divisible by 8" {
354}352}
355353
356test "vector @splat" {354test "vector @splat" {
357 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
358 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO356 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
359 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO357 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
360 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;358 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -395,7 +393,7 @@ test "vector @splat" {...@@ -395,7 +393,7 @@ test "vector @splat" {
395}393}
396394
397test "load vector elements via comptime index" {395test "load vector elements via comptime index" {
398 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO396 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
399 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
400 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO398 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
401399
...@@ -416,7 +414,7 @@ test "load vector elements via comptime index" {...@@ -416,7 +414,7 @@ test "load vector elements via comptime index" {
416}414}
417415
418test "store vector elements via comptime index" {416test "store vector elements via comptime index" {
419 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO417 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO418 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
421 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO419 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
422420
...@@ -443,7 +441,6 @@ test "store vector elements via comptime index" {...@@ -443,7 +441,6 @@ test "store vector elements via comptime index" {
443}441}
444442
445test "load vector elements via runtime index" {443test "load vector elements via runtime index" {
446 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
447 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO444 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO445 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
449446
...@@ -465,7 +462,7 @@ test "load vector elements via runtime index" {...@@ -465,7 +462,7 @@ test "load vector elements via runtime index" {
465}462}
466463
467test "store vector elements via runtime index" {464test "store vector elements via runtime index" {
468 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO465 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
469 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO466 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
470 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO467 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
471468
...@@ -487,7 +484,6 @@ test "store vector elements via runtime index" {...@@ -487,7 +484,6 @@ test "store vector elements via runtime index" {
487}484}
488485
489test "initialize vector which is a struct field" {486test "initialize vector which is a struct field" {
490 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO487 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
492 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO488 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
493489
...@@ -508,8 +504,8 @@ test "initialize vector which is a struct field" {...@@ -508,8 +504,8 @@ test "initialize vector which is a struct field" {
508}504}
509505
510test "vector comparison operators" {506test "vector comparison operators" {
507 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
511 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO508 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
512 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
513 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO509 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO510 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
515 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;511 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -554,8 +550,8 @@ test "vector comparison operators" {...@@ -554,8 +550,8 @@ test "vector comparison operators" {
554}550}
555551
556test "vector division operators" {552test "vector division operators" {
553 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
557 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO554 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
558 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
559 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO555 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
560 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO556 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
561 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;557 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -647,9 +643,9 @@ test "vector division operators" {...@@ -647,9 +643,9 @@ test "vector division operators" {
647}643}
648644
649test "vector bitwise not operator" {645test "vector bitwise not operator" {
646 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
650 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO647 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
651 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;648 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
652 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
653 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO649 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
654 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO650 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
655 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;651 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -681,9 +677,9 @@ test "vector bitwise not operator" {...@@ -681,9 +677,9 @@ test "vector bitwise not operator" {
681}677}
682678
683test "vector boolean not operator" {679test "vector boolean not operator" {
680 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
684 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO681 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
685 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;682 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
686 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO683 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
688 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO684 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
689 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;685 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -705,8 +701,8 @@ test "vector boolean not operator" {...@@ -705,8 +701,8 @@ test "vector boolean not operator" {
705}701}
706702
707test "vector shift operators" {703test "vector shift operators" {
704 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
708 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO705 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
710 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO706 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO707 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
712 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;708 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -776,8 +772,8 @@ test "vector shift operators" {...@@ -776,8 +772,8 @@ test "vector shift operators" {
776}772}
777773
778test "vector reduce operation" {774test "vector reduce operation" {
775 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
779 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO776 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
780 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
781 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO777 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
782 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO778 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
783 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;779 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -908,7 +904,6 @@ test "vector reduce operation" {...@@ -908,7 +904,6 @@ test "vector reduce operation" {
908904
909test "vector @reduce comptime" {905test "vector @reduce comptime" {
910 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO906 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
911 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
912 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO907 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
913 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO908 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
914909
...@@ -924,7 +919,7 @@ test "vector @reduce comptime" {...@@ -924,7 +919,7 @@ test "vector @reduce comptime" {
924}919}
925920
926test "mask parameter of @shuffle is comptime scope" {921test "mask parameter of @shuffle is comptime scope" {
927 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO922 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
928 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO923 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
929 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO924 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
930 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;925 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -946,8 +941,8 @@ test "mask parameter of @shuffle is comptime scope" {...@@ -946,8 +941,8 @@ test "mask parameter of @shuffle is comptime scope" {
946}941}
947942
948test "saturating add" {943test "saturating add" {
944 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
949 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO945 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
950 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
951 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO946 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
952 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO947 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
953 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;948 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -980,8 +975,8 @@ test "saturating add" {...@@ -980,8 +975,8 @@ test "saturating add" {
980}975}
981976
982test "saturating subtraction" {977test "saturating subtraction" {
978 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
983 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO979 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
984 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
985 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO980 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
986 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO981 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
987 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;982 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1004,8 +999,8 @@ test "saturating subtraction" {...@@ -1004,8 +999,8 @@ test "saturating subtraction" {
1004}999}
10051000
1006test "saturating multiplication" {1001test "saturating multiplication" {
1002 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1007 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1003 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1008 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1009 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1004 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1010 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1005 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1011 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1006 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1032,8 +1027,8 @@ test "saturating multiplication" {...@@ -1032,8 +1027,8 @@ test "saturating multiplication" {
1032}1027}
10331028
1034test "saturating shift-left" {1029test "saturating shift-left" {
1030 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1035 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1031 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1036 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1037 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1032 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1038 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1033 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1039 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1034 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1056,8 +1051,8 @@ test "saturating shift-left" {...@@ -1056,8 +1051,8 @@ test "saturating shift-left" {
1056}1051}
10571052
1058test "multiplication-assignment operator with an array operand" {1053test "multiplication-assignment operator with an array operand" {
1054 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1059 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1055 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1060 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1061 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1056 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1062 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1057 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1063 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1058 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1077,8 +1072,8 @@ test "multiplication-assignment operator with an array operand" {...@@ -1077,8 +1072,8 @@ test "multiplication-assignment operator with an array operand" {
1077}1072}
10781073
1079test "@addWithOverflow" {1074test "@addWithOverflow" {
1075 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1080 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1076 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1081 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1082 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1077 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1083 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1078 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1084 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1079 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1127,8 +1122,8 @@ test "@addWithOverflow" {...@@ -1127,8 +1122,8 @@ test "@addWithOverflow" {
1127}1122}
11281123
1129test "@subWithOverflow" {1124test "@subWithOverflow" {
1125 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1130 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1126 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1131 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1132 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1127 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1133 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1128 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1134 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1129 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1161,8 +1156,8 @@ test "@subWithOverflow" {...@@ -1161,8 +1156,8 @@ test "@subWithOverflow" {
1161}1156}
11621157
1163test "@mulWithOverflow" {1158test "@mulWithOverflow" {
1159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1164 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1160 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1165 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1166 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1167 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1168 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1163 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1184,8 +1179,8 @@ test "@mulWithOverflow" {...@@ -1184,8 +1179,8 @@ test "@mulWithOverflow" {
1184}1179}
11851180
1186test "@shlWithOverflow" {1181test "@shlWithOverflow" {
1182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1187 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1183 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1188 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1189 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1184 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1190 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1185 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1191 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1186 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1229,8 +1224,8 @@ test "alignment of vectors" {...@@ -1229,8 +1224,8 @@ test "alignment of vectors" {
1229}1224}
12301225
1231test "loading the second vector from a slice of vectors" {1226test "loading the second vector from a slice of vectors" {
1227 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1232 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1228 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1233 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1234 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1229 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1235 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1230 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1236 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1231 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1246,8 +1241,8 @@ test "loading the second vector from a slice of vectors" {...@@ -1246,8 +1241,8 @@ test "loading the second vector from a slice of vectors" {
1246}1241}
12471242
1248test "array of vectors is copied" {1243test "array of vectors is copied" {
1244 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1249 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1245 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1250 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1251 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1252 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1253 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1248 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1270,8 +1265,8 @@ test "array of vectors is copied" {...@@ -1270,8 +1265,8 @@ test "array of vectors is copied" {
1270}1265}
12711266
1272test "byte vector initialized in inline function" {1267test "byte vector initialized in inline function" {
1268 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1273 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1269 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1274 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1275 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1270 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1276 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1271 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1277 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1272 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1297,7 +1292,6 @@ test "byte vector initialized in inline function" {...@@ -1297,7 +1292,6 @@ test "byte vector initialized in inline function" {
12971292
1298test "zero divisor" {1293test "zero divisor" {
1299 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1294 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1300 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1301 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1295 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1302 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1296 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13031297
...@@ -1317,7 +1311,6 @@ test "zero divisor" {...@@ -1317,7 +1311,6 @@ test "zero divisor" {
13171311
1318test "zero multiplicand" {1312test "zero multiplicand" {
1319 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1313 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1320 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1321 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1314 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1322 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1315 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1323 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO1316 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
...@@ -1341,7 +1334,6 @@ test "zero multiplicand" {...@@ -1341,7 +1334,6 @@ test "zero multiplicand" {
13411334
1342test "@intCast to u0" {1335test "@intCast to u0" {
1343 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1336 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1344 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1345 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1337 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1346 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1338 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1347 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1339 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1364,8 +1356,8 @@ test "modRem with zero divisor" {...@@ -1364,8 +1356,8 @@ test "modRem with zero divisor" {
1364}1356}
13651357
1366test "array operands to shuffle are coerced to vectors" {1358test "array operands to shuffle are coerced to vectors" {
1359 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1367 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1360 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1368 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1369 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1361 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1370 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1362 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1371 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1363 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1379,7 +1371,7 @@ test "array operands to shuffle are coerced to vectors" {...@@ -1379,7 +1371,7 @@ test "array operands to shuffle are coerced to vectors" {
1379}1371}
13801372
1381test "load packed vector element" {1373test "load packed vector element" {
1382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1383 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1375 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1384 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1376 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1385 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1377 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
...@@ -1391,7 +1383,7 @@ test "load packed vector element" {...@@ -1391,7 +1383,7 @@ test "load packed vector element" {
1391}1383}
13921384
1393test "store packed vector element" {1385test "store packed vector element" {
1394 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1386 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1395 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1387 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1396 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1388 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1397 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1389 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
...@@ -1408,7 +1400,7 @@ test "store packed vector element" {...@@ -1408,7 +1400,7 @@ test "store packed vector element" {
1408}1400}
14091401
1410test "store to vector in slice" {1402test "store to vector in slice" {
1411 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1403 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1412 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1413 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1405 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1414 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1406 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1426,7 +1418,7 @@ test "store to vector in slice" {...@@ -1426,7 +1418,7 @@ test "store to vector in slice" {
1426}1418}
14271419
1428test "store vector with memset" {1420test "store vector with memset" {
1429 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1421 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1430 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1422 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1431 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1423 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1432 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1424 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1459,7 +1451,7 @@ test "store vector with memset" {...@@ -1459,7 +1451,7 @@ test "store vector with memset" {
1459}1451}
14601452
1461test "addition of vectors represented as strings" {1453test "addition of vectors represented as strings" {
1462 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1454 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1455 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14641456
1465 const V = @Vector(3, u8);1457 const V = @Vector(3, u8);
...@@ -1469,7 +1461,7 @@ test "addition of vectors represented as strings" {...@@ -1469,7 +1461,7 @@ test "addition of vectors represented as strings" {
1469}1461}
14701462
1471test "compare vectors with different element types" {1463test "compare vectors with different element types" {
1472 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1464 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1473 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1465 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1474 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1466 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1475 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1467 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1482,7 +1474,6 @@ test "compare vectors with different element types" {...@@ -1482,7 +1474,6 @@ test "compare vectors with different element types" {
1482}1474}
14831475
1484test "vector pointer is indexable" {1476test "vector pointer is indexable" {
1485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1486 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1477 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1487 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1478 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1488 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1479 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1506,7 +1497,6 @@ test "vector pointer is indexable" {...@@ -1506,7 +1497,6 @@ test "vector pointer is indexable" {
1506}1497}
15071498
1508test "boolean vector with 2 or more booleans" {1499test "boolean vector with 2 or more booleans" {
1509 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1510 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1500 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1511 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1501 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1512 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1502 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1519,7 +1509,7 @@ test "boolean vector with 2 or more booleans" {...@@ -1519,7 +1509,7 @@ test "boolean vector with 2 or more booleans" {
1519}1509}
15201510
1521test "bitcast to vector with different child type" {1511test "bitcast to vector with different child type" {
1522 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1512 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1523 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1513 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1524 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1514 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1525 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1551,7 +1541,6 @@ test "index into comptime-known vector is comptime-known" {...@@ -1551,7 +1541,6 @@ test "index into comptime-known vector is comptime-known" {
15511541
1552test "arithmetic on zero-length vectors" {1542test "arithmetic on zero-length vectors" {
1553 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1543 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1555 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1544 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
15561545
1557 {1546 {
...@@ -1568,7 +1557,6 @@ test "arithmetic on zero-length vectors" {...@@ -1568,7 +1557,6 @@ test "arithmetic on zero-length vectors" {
15681557
1569test "@reduce on bool vector" {1558test "@reduce on bool vector" {
1570 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1559 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1571 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1560 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15731561
1574 const a = @Vector(2, bool){ true, true };1562 const a = @Vector(2, bool){ true, true };
...@@ -1578,7 +1566,7 @@ test "@reduce on bool vector" {...@@ -1578,7 +1566,7 @@ test "@reduce on bool vector" {
1578}1566}
15791567
1580test "bitcast vector to array of smaller vectors" {1568test "bitcast vector to array of smaller vectors" {
1581 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1569 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1582 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1570 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1583 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1571 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
15841572
test/behavior/void.zig-1
...@@ -36,7 +36,6 @@ fn times(n: usize) []const void {...@@ -36,7 +36,6 @@ fn times(n: usize) []const void {
3636
37test "void optional" {37test "void optional" {
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
40 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO39 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4140
42 var x: ?void = {};41 var x: ?void = {};
test/behavior/while.zig+3-9
...@@ -124,8 +124,6 @@ test "while copies its payload" {...@@ -124,8 +124,6 @@ test "while copies its payload" {
124}124}
125125
126test "continue and break" {126test "continue and break" {
127 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
128
129 try runContinueAndBreakTest();127 try runContinueAndBreakTest();
130 try expect(continue_and_break_counter == 8);128 try expect(continue_and_break_counter == 8);
131}129}
...@@ -176,6 +174,7 @@ test "while with optional as condition with else" {...@@ -176,6 +174,7 @@ test "while with optional as condition with else" {
176}174}
177175
178test "while with error union condition" {176test "while with error union condition" {
177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
179 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO178 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
180 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;179 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
181 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;180 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -209,7 +208,6 @@ test "while on bool with else result follow break prong" {...@@ -209,7 +208,6 @@ test "while on bool with else result follow break prong" {
209208
210test "while on optional with else result follow else prong" {209test "while on optional with else result follow else prong" {
211 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
213 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO211 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
214212
215 const result = while (returnNull()) |value| {213 const result = while (returnNull()) |value| {
...@@ -220,7 +218,6 @@ test "while on optional with else result follow else prong" {...@@ -220,7 +218,6 @@ test "while on optional with else result follow else prong" {
220218
221test "while on optional with else result follow break prong" {219test "while on optional with else result follow break prong" {
222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
223 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
224 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
225222
226 const result = while (returnOptional(10)) |value| {223 const result = while (returnOptional(10)) |value| {
...@@ -292,7 +289,6 @@ test "while bool 2 break statements and an else" {...@@ -292,7 +289,6 @@ test "while bool 2 break statements and an else" {
292289
293test "while optional 2 break statements and an else" {290test "while optional 2 break statements and an else" {
294 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO291 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
295 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
296 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO292 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
297293
298 const S = struct {294 const S = struct {
...@@ -310,8 +306,8 @@ test "while optional 2 break statements and an else" {...@@ -310,8 +306,8 @@ test "while optional 2 break statements and an else" {
310}306}
311307
312test "while error 2 break statements and an else" {308test "while error 2 break statements and an else" {
309 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
313 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO310 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
314 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
315 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO311 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
316312
317 const S = struct {313 const S = struct {
...@@ -348,8 +344,8 @@ test "else continue outer while" {...@@ -348,8 +344,8 @@ test "else continue outer while" {
348}344}
349345
350test "try terminating an infinite loop" {346test "try terminating an infinite loop" {
347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
351 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO348 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
352 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
353 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;349 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
354350
355 // Test coverage for https://github.com/ziglang/zig/issues/13546351 // Test coverage for https://github.com/ziglang/zig/issues/13546
...@@ -376,7 +372,6 @@ test "while loop with comptime true condition needs no else block to return valu...@@ -376,7 +372,6 @@ test "while loop with comptime true condition needs no else block to return valu
376}372}
377373
378test "int returned from switch in while" {374test "int returned from switch in while" {
379 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO375 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
381376
382 var x: u32 = 3;377 var x: u32 = 3;
...@@ -389,7 +384,6 @@ test "int returned from switch in while" {...@@ -389,7 +384,6 @@ test "int returned from switch in while" {
389384
390test "breaking from a loop in an if statement" {385test "breaking from a loop in an if statement" {
391 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;386 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
392 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
393 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO387 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
394388
395 const S = struct {389 const S = struct {
test/behavior/widening.zig-5
...@@ -4,7 +4,6 @@ const mem = std.mem;...@@ -4,7 +4,6 @@ const mem = std.mem;
4const builtin = @import("builtin");4const builtin = @import("builtin");
55
6test "integer widening" {6test "integer widening" {
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -29,7 +28,6 @@ test "integer widening u0 to u8" {...@@ -29,7 +28,6 @@ test "integer widening u0 to u8" {
29}28}
3029
31test "implicit unsigned integer to signed integer" {30test "implicit unsigned integer to signed integer" {
32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
34 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;32 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
3533
...@@ -40,7 +38,6 @@ test "implicit unsigned integer to signed integer" {...@@ -40,7 +38,6 @@ test "implicit unsigned integer to signed integer" {
40}38}
4139
42test "float widening" {40test "float widening" {
43 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO41 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO42 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
46 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;43 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -60,7 +57,6 @@ test "float widening" {...@@ -60,7 +57,6 @@ test "float widening" {
60}57}
6158
62test "float widening f16 to f128" {59test "float widening f16 to f128" {
63 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
64 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO60 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
65 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO61 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;62 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -73,7 +69,6 @@ test "float widening f16 to f128" {...@@ -73,7 +69,6 @@ test "float widening f16 to f128" {
73}69}
7470
75test "cast small unsigned to larger signed" {71test "cast small unsigned to larger signed" {
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO72 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO73 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;74 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/c_import/macros.zig-12
...@@ -25,7 +25,6 @@ test "casting to void with a macro" {...@@ -25,7 +25,6 @@ test "casting to void with a macro" {
2525
26test "initializer list expression" {26test "initializer list expression" {
27 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO27 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO28 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;29 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
3130
...@@ -38,7 +37,6 @@ test "initializer list expression" {...@@ -38,7 +37,6 @@ test "initializer list expression" {
38}37}
3938
40test "sizeof in macros" {39test "sizeof in macros" {
41 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
42 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO40 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
43 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;41 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
4442
...@@ -55,7 +53,6 @@ test "reference to a struct type" {...@@ -55,7 +53,6 @@ test "reference to a struct type" {
5553
56test "cast negative integer to pointer" {54test "cast negative integer to pointer" {
57 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
59 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
60 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;57 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
6158
...@@ -64,7 +61,6 @@ test "cast negative integer to pointer" {...@@ -64,7 +61,6 @@ test "cast negative integer to pointer" {
6461
65test "casting to union with a macro" {62test "casting to union with a macro" {
66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO63 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
68 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO64 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
69 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;65 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
7066
...@@ -80,7 +76,6 @@ test "casting to union with a macro" {...@@ -80,7 +76,6 @@ test "casting to union with a macro" {
8076
81test "casting or calling a value with a paren-surrounded macro" {77test "casting or calling a value with a paren-surrounded macro" {
82 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
83 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;80 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
8681
...@@ -99,7 +94,6 @@ test "casting or calling a value with a paren-surrounded macro" {...@@ -99,7 +94,6 @@ test "casting or calling a value with a paren-surrounded macro" {
9994
100test "nested comma operator" {95test "nested comma operator" {
101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO96 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO97 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;98 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10599
...@@ -109,7 +103,6 @@ test "nested comma operator" {...@@ -109,7 +103,6 @@ test "nested comma operator" {
109103
110test "cast functions" {104test "cast functions" {
111 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
112 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
113 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
114 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;107 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
115108
...@@ -123,7 +116,6 @@ test "cast functions" {...@@ -123,7 +116,6 @@ test "cast functions" {
123test "large integer macro" {116test "large integer macro" {
124 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO117 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
128 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;120 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
129121
...@@ -132,7 +124,6 @@ test "large integer macro" {...@@ -132,7 +124,6 @@ test "large integer macro" {
132124
133test "string literal macro with embedded tab character" {125test "string literal macro with embedded tab character" {
134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO126 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;128 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
138129
...@@ -141,7 +132,6 @@ test "string literal macro with embedded tab character" {...@@ -141,7 +132,6 @@ test "string literal macro with embedded tab character" {
141132
142test "string and char literals that are not UTF-8 encoded. Issue #12784" {133test "string and char literals that are not UTF-8 encoded. Issue #12784" {
143 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO135 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;136 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
147137
...@@ -152,7 +142,6 @@ test "string and char literals that are not UTF-8 encoded. Issue #12784" {...@@ -152,7 +142,6 @@ test "string and char literals that are not UTF-8 encoded. Issue #12784" {
152test "Macro that uses division operator. Issue #13162" {142test "Macro that uses division operator. Issue #13162" {
153 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO143 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
154 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
156 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
157 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
158 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;147 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
...@@ -196,7 +185,6 @@ test "Macro that uses division operator. Issue #13162" {...@@ -196,7 +185,6 @@ test "Macro that uses division operator. Issue #13162" {
196test "Macro that uses remainder operator. Issue #13346" {185test "Macro that uses remainder operator. Issue #13346" {
197 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO186 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
198 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO187 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
199 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
200 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO188 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
201 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;189 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
202190
test/tests.zig+37-3
...@@ -116,8 +116,6 @@ const test_targets = blk: {...@@ -116,8 +116,6 @@ const test_targets = blk: {
116 .abi = .eabihf,116 .abi = .eabihf,
117 },117 },
118 .link_libc = true,118 .link_libc = true,
119 // https://github.com/ziglang/zig/issues/23949
120 .skip_modules = &.{"std"},
121 },119 },
122120
123 .{121 .{
...@@ -191,6 +189,30 @@ const test_targets = blk: {...@@ -191,6 +189,30 @@ const test_targets = blk: {
191 .link_libc = true,189 .link_libc = true,
192 },190 },
193191
192 .{
193 .target = .{
194 .cpu_arch = .aarch64,
195 .os_tag = .linux,
196 .abi = .none,
197 },
198 .use_llvm = false,
199 .use_lld = false,
200 .optimize_mode = .ReleaseFast,
201 .strip = true,
202 },
203 .{
204 .target = .{
205 .cpu_arch = .aarch64,
206 .cpu_model = .{ .explicit = &std.Target.aarch64.cpu.neoverse_n1 },
207 .os_tag = .linux,
208 .abi = .none,
209 },
210 .use_llvm = false,
211 .use_lld = false,
212 .optimize_mode = .ReleaseFast,
213 .strip = true,
214 },
215
194 .{216 .{
195 .target = .{217 .target = .{
196 .cpu_arch = .aarch64_be,218 .cpu_arch = .aarch64_be,
...@@ -1182,6 +1204,18 @@ const test_targets = blk: {...@@ -1182,6 +1204,18 @@ const test_targets = blk: {
1182 },1204 },
1183 },1205 },
11841206
1207 .{
1208 .target = .{
1209 .cpu_arch = .aarch64,
1210 .os_tag = .macos,
1211 .abi = .none,
1212 },
1213 .use_llvm = false,
1214 .use_lld = false,
1215 .optimize_mode = .ReleaseFast,
1216 .strip = true,
1217 },
1218
1185 .{1219 .{
1186 .target = .{1220 .target = .{
1187 .cpu_arch = .x86_64,1221 .cpu_arch = .x86_64,
...@@ -2260,7 +2294,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -2260,7 +2294,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
2260 continue;2294 continue;
22612295
2262 // TODO get compiler-rt tests passing for self-hosted backends.2296 // TODO get compiler-rt tests passing for self-hosted backends.
2263 if ((target.cpu.arch != .x86_64 or target.ofmt != .elf) and2297 if (((target.cpu.arch != .x86_64 and target.cpu.arch != .aarch64) or target.ofmt == .coff) and
2264 test_target.use_llvm == false and mem.eql(u8, options.name, "compiler-rt"))2298 test_target.use_llvm == false and mem.eql(u8, options.name, "compiler-rt"))
2265 continue;2299 continue;
22662300