From ed51a5d02af58b3d11b555233781d71e6bde60af Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 28 Apr 2022 00:09:26 +0200 Subject: [PATCH] test: migrate arm incremental tests --- test/cases.zig | 1 - .../arm-linux/arithmetic_operations.0.zig | 21 + .../arm-linux/arithmetic_operations.1.zig | 20 + .../arm-linux/arithmetic_operations.2.zig | 20 + .../arm-linux/arithmetic_operations.3.zig | 20 + .../arm-linux/arithmetic_operations.4.zig | 20 + .../arm-linux/arithmetic_operations.5.zig | 15 + .../arm-linux/arithmetic_operations.6.zig | 21 + test/incremental/arm-linux/errors.0.zig | 21 + test/incremental/arm-linux/errors.1.zig | 24 + test/incremental/arm-linux/errors.2.zig | 27 + test/incremental/arm-linux/errors.3.zig | 12 + .../arm-linux/function_pointers.zig | 44 + .../arm-linux/hello_world_with_updates.0.zig | 32 + .../arm-linux/hello_world_with_updates.1.zig | 37 + .../arm-linux/hello_world_with_updates.2.zig | 22 + .../parameters_and_return_values.0.zig | 28 + .../parameters_and_return_values.1.zig | 14 + test/incremental/arm-linux/print_u32s.zig | 40 + .../arm-linux/spilling_registers.0.zig | 38 + .../arm-linux/spilling_registers.1.zig | 37 + test/incremental/non_leaf_functions.zig | 12 + test/incremental/recursive_fibonacci.zig | 24 + ...rn_values_in_callee_preserved_register.zig | 22 + test/stage2/arm.zig | 798 ------------------ 25 files changed, 571 insertions(+), 799 deletions(-) create mode 100644 test/incremental/arm-linux/arithmetic_operations.0.zig create mode 100644 test/incremental/arm-linux/arithmetic_operations.1.zig create mode 100644 test/incremental/arm-linux/arithmetic_operations.2.zig create mode 100644 test/incremental/arm-linux/arithmetic_operations.3.zig create mode 100644 test/incremental/arm-linux/arithmetic_operations.4.zig create mode 100644 test/incremental/arm-linux/arithmetic_operations.5.zig create mode 100644 test/incremental/arm-linux/arithmetic_operations.6.zig create mode 100644 test/incremental/arm-linux/errors.0.zig create mode 100644 test/incremental/arm-linux/errors.1.zig create mode 100644 test/incremental/arm-linux/errors.2.zig create mode 100644 test/incremental/arm-linux/errors.3.zig create mode 100644 test/incremental/arm-linux/function_pointers.zig create mode 100644 test/incremental/arm-linux/hello_world_with_updates.0.zig create mode 100644 test/incremental/arm-linux/hello_world_with_updates.1.zig create mode 100644 test/incremental/arm-linux/hello_world_with_updates.2.zig create mode 100644 test/incremental/arm-linux/parameters_and_return_values.0.zig create mode 100644 test/incremental/arm-linux/parameters_and_return_values.1.zig create mode 100644 test/incremental/arm-linux/print_u32s.zig create mode 100644 test/incremental/arm-linux/spilling_registers.0.zig create mode 100644 test/incremental/arm-linux/spilling_registers.1.zig create mode 100644 test/incremental/non_leaf_functions.zig create mode 100644 test/incremental/recursive_fibonacci.zig create mode 100644 test/incremental/save_function_return_values_in_callee_preserved_register.zig delete mode 100644 test/stage2/arm.zig diff --git a/test/cases.zig b/test/cases.zig index c615d84099..f90233df0f 100644 --- a/test/cases.zig +++ b/test/cases.zig @@ -9,7 +9,6 @@ const TestContext = @import("../src/test.zig").TestContext; pub fn addCases(ctx: *TestContext) !void { try @import("compile_errors.zig").addCases(ctx); try @import("stage2/cbe.zig").addCases(ctx); - try @import("stage2/arm.zig").addCases(ctx); try @import("stage2/llvm.zig").addCases(ctx); try @import("stage2/plan9.zig").addCases(ctx); try @import("stage2/x86_64.zig").addCases(ctx); diff --git a/test/incremental/arm-linux/arithmetic_operations.0.zig b/test/incremental/arm-linux/arithmetic_operations.0.zig new file mode 100644 index 0000000000..51a2dbd700 --- /dev/null +++ b/test/incremental/arm-linux/arithmetic_operations.0.zig @@ -0,0 +1,21 @@ +pub fn main() void { + print(2, 4); + print(1, 7); +} + +fn print(a: u32, b: u32) void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg3] "{r2}" (a + b), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("123456789")), + : "memory" + ); + return; +} + +// run +// target=arm-linux +// +// 12345612345678 diff --git a/test/incremental/arm-linux/arithmetic_operations.1.zig b/test/incremental/arm-linux/arithmetic_operations.1.zig new file mode 100644 index 0000000000..1e3793ed38 --- /dev/null +++ b/test/incremental/arm-linux/arithmetic_operations.1.zig @@ -0,0 +1,20 @@ +pub fn main() void { + print(10, 5); + print(4, 3); +} + +fn print(a: u32, b: u32) void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg3] "{r2}" (a - b), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("123456789")), + : "memory" + ); + return; +} + +// run +// +// 123451 diff --git a/test/incremental/arm-linux/arithmetic_operations.2.zig b/test/incremental/arm-linux/arithmetic_operations.2.zig new file mode 100644 index 0000000000..6b81e62198 --- /dev/null +++ b/test/incremental/arm-linux/arithmetic_operations.2.zig @@ -0,0 +1,20 @@ +pub fn main() void { + print(8, 9); + print(3, 7); +} + +fn print(a: u32, b: u32) void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg3] "{r2}" (a & b), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("123456789")), + : "memory" + ); + return; +} + +// run +// +// 12345678123 diff --git a/test/incremental/arm-linux/arithmetic_operations.3.zig b/test/incremental/arm-linux/arithmetic_operations.3.zig new file mode 100644 index 0000000000..23089127f5 --- /dev/null +++ b/test/incremental/arm-linux/arithmetic_operations.3.zig @@ -0,0 +1,20 @@ +pub fn main() void { + print(4, 2); + print(3, 7); +} + +fn print(a: u32, b: u32) void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg3] "{r2}" (a | b), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("123456789")), + : "memory" + ); + return; +} + +// run +// +// 1234561234567 diff --git a/test/incremental/arm-linux/arithmetic_operations.4.zig b/test/incremental/arm-linux/arithmetic_operations.4.zig new file mode 100644 index 0000000000..ce5133c465 --- /dev/null +++ b/test/incremental/arm-linux/arithmetic_operations.4.zig @@ -0,0 +1,20 @@ +pub fn main() void { + print(42, 42); + print(3, 5); +} + +fn print(a: u32, b: u32) void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg3] "{r2}" (a ^ b), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("123456789")), + : "memory" + ); + return; +} + +// run +// +// 123456 diff --git a/test/incremental/arm-linux/arithmetic_operations.5.zig b/test/incremental/arm-linux/arithmetic_operations.5.zig new file mode 100644 index 0000000000..b1c18ca7da --- /dev/null +++ b/test/incremental/arm-linux/arithmetic_operations.5.zig @@ -0,0 +1,15 @@ +pub fn main() void { + var x: u32 = 1; + assert(x << 1 == 2); + + x <<= 1; + assert(x << 2 == 8); + assert(x << 3 == 16); +} + +pub fn assert(ok: bool) void { + if (!ok) unreachable; // assertion failure +} + +// run +// diff --git a/test/incremental/arm-linux/arithmetic_operations.6.zig b/test/incremental/arm-linux/arithmetic_operations.6.zig new file mode 100644 index 0000000000..e03731173c --- /dev/null +++ b/test/incremental/arm-linux/arithmetic_operations.6.zig @@ -0,0 +1,21 @@ +pub fn main() void { + var a: u32 = 1024; + assert(a >> 1 == 512); + + a >>= 1; + assert(a >> 2 == 128); + assert(a >> 3 == 64); + assert(a >> 4 == 32); + assert(a >> 5 == 16); + assert(a >> 6 == 8); + assert(a >> 7 == 4); + assert(a >> 8 == 2); + assert(a >> 9 == 1); +} + +pub fn assert(ok: bool) void { + if (!ok) unreachable; // assertion failure +} + +// run +// diff --git a/test/incremental/arm-linux/errors.0.zig b/test/incremental/arm-linux/errors.0.zig new file mode 100644 index 0000000000..3e20d1d973 --- /dev/null +++ b/test/incremental/arm-linux/errors.0.zig @@ -0,0 +1,21 @@ +pub fn main() void { + foo() catch print(); +} + +fn foo() anyerror!void {} + +fn print() void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("Hello, World!\n")), + [arg3] "{r2}" ("Hello, World!\n".len), + : "memory" + ); + return; +} + +// run +// target=arm-linux +// diff --git a/test/incremental/arm-linux/errors.1.zig b/test/incremental/arm-linux/errors.1.zig new file mode 100644 index 0000000000..43fbb12675 --- /dev/null +++ b/test/incremental/arm-linux/errors.1.zig @@ -0,0 +1,24 @@ +pub fn main() void { + foo() catch print(); +} + +fn foo() anyerror!void { + return error.Test; +} + +fn print() void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("Hello, World!\n")), + [arg3] "{r2}" ("Hello, World!\n".len), + : "memory" + ); + return; +} + +// run +// +// Hello, World! +// diff --git a/test/incremental/arm-linux/errors.2.zig b/test/incremental/arm-linux/errors.2.zig new file mode 100644 index 0000000000..a1b9aef97d --- /dev/null +++ b/test/incremental/arm-linux/errors.2.zig @@ -0,0 +1,27 @@ +pub fn main() void { + foo() catch |err| { + assert(err == error.Foo); + assert(err != error.Bar); + assert(err != error.Baz); + }; + bar() catch |err| { + assert(err != error.Foo); + assert(err == error.Bar); + assert(err != error.Baz); + }; +} + +fn assert(ok: bool) void { + if (!ok) unreachable; +} + +fn foo() anyerror!void { + return error.Foo; +} + +fn bar() anyerror!void { + return error.Bar; +} + +// run +// diff --git a/test/incremental/arm-linux/errors.3.zig b/test/incremental/arm-linux/errors.3.zig new file mode 100644 index 0000000000..390696fcfc --- /dev/null +++ b/test/incremental/arm-linux/errors.3.zig @@ -0,0 +1,12 @@ +pub fn main() void { + foo() catch unreachable; +} + +fn foo() anyerror!void { + try bar(); +} + +fn bar() anyerror!void {} + +// run +// diff --git a/test/incremental/arm-linux/function_pointers.zig b/test/incremental/arm-linux/function_pointers.zig new file mode 100644 index 0000000000..0ef5df6745 --- /dev/null +++ b/test/incremental/arm-linux/function_pointers.zig @@ -0,0 +1,44 @@ +const PrintFn = *const fn () void; + +pub fn main() void { + var printFn: PrintFn = stopSayingThat; + var i: u32 = 0; + while (i < 4) : (i += 1) printFn(); + + printFn = moveEveryZig; + printFn(); +} + +fn stopSayingThat() void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("Hello, my name is Inigo Montoya; you killed my father, prepare to die.\n")), + [arg3] "{r2}" ("Hello, my name is Inigo Montoya; you killed my father, prepare to die.\n".len), + : "memory" + ); + return; +} + +fn moveEveryZig() void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("All your codebase are belong to us\n")), + [arg3] "{r2}" ("All your codebase are belong to us\n".len), + : "memory" + ); + return; +} + +// run +// target=arm-linux +// +// Hello, my name is Inigo Montoya; you killed my father, prepare to die. +// Hello, my name is Inigo Montoya; you killed my father, prepare to die. +// Hello, my name is Inigo Montoya; you killed my father, prepare to die. +// Hello, my name is Inigo Montoya; you killed my father, prepare to die. +// All your codebase are belong to us +// diff --git a/test/incremental/arm-linux/hello_world_with_updates.0.zig b/test/incremental/arm-linux/hello_world_with_updates.0.zig new file mode 100644 index 0000000000..4ffdc2ae0f --- /dev/null +++ b/test/incremental/arm-linux/hello_world_with_updates.0.zig @@ -0,0 +1,32 @@ +pub export fn _start() noreturn { + print(); + exit(); +} + +fn print() void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("Hello, World!\n")), + [arg3] "{r2}" (14), + : "memory" + ); + return; +} + +fn exit() noreturn { + asm volatile ("svc #0" + : + : [number] "{r7}" (1), + [arg1] "{r0}" (0), + : "memory" + ); + unreachable; +} + +// run +// target=arm-linux +// +// Hello, World! +// diff --git a/test/incremental/arm-linux/hello_world_with_updates.1.zig b/test/incremental/arm-linux/hello_world_with_updates.1.zig new file mode 100644 index 0000000000..8372d757ad --- /dev/null +++ b/test/incremental/arm-linux/hello_world_with_updates.1.zig @@ -0,0 +1,37 @@ +pub export fn _start() noreturn { + print(); + print(); + print(); + print(); + exit(); +} + +fn print() void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("Hello, World!\n")), + [arg3] "{r2}" (14), + : "memory" + ); + return; +} + +fn exit() noreturn { + asm volatile ("svc #0" + : + : [number] "{r7}" (1), + [arg1] "{r0}" (0), + : "memory" + ); + unreachable; +} + +// run +// +// Hello, World! +// Hello, World! +// Hello, World! +// Hello, World! +// diff --git a/test/incremental/arm-linux/hello_world_with_updates.2.zig b/test/incremental/arm-linux/hello_world_with_updates.2.zig new file mode 100644 index 0000000000..0b97bf2360 --- /dev/null +++ b/test/incremental/arm-linux/hello_world_with_updates.2.zig @@ -0,0 +1,22 @@ +pub fn main() void { + print(); + print(); +} + +fn print() void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("Hello, World!\n")), + [arg3] "{r2}" (14), + : "memory" + ); + return; +} + +// run +// +// Hello, World! +// Hello, World! +// diff --git a/test/incremental/arm-linux/parameters_and_return_values.0.zig b/test/incremental/arm-linux/parameters_and_return_values.0.zig new file mode 100644 index 0000000000..6a306d802c --- /dev/null +++ b/test/incremental/arm-linux/parameters_and_return_values.0.zig @@ -0,0 +1,28 @@ +pub fn main() void { + print(id(14)); +} + +fn id(x: u32) u32 { + return x; +} + +// TODO: The parameters to the asm statement in print() had to +// be in a specific order because otherwise the write to r0 +// would overwrite the len parameter which resides in r0 +fn print(len: u32) void { + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg3] "{r2}" (len), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("Hello, World!\n")), + : "memory" + ); + return; +} + +// run +// target=arm-linux +// +// Hello, World! +// diff --git a/test/incremental/arm-linux/parameters_and_return_values.1.zig b/test/incremental/arm-linux/parameters_and_return_values.1.zig new file mode 100644 index 0000000000..f2bc35d22e --- /dev/null +++ b/test/incremental/arm-linux/parameters_and_return_values.1.zig @@ -0,0 +1,14 @@ +pub fn main() void { + assert(add(1, 2, 3, 4, 5, 6) == 21); +} + +fn add(a: u32, b: u32, c: u32, d: u32, e: u32, f: u32) u32 { + return a + b + c + d + e + f; +} + +pub fn assert(ok: bool) void { + if (!ok) unreachable; // assertion failure +} + +// run +// diff --git a/test/incremental/arm-linux/print_u32s.zig b/test/incremental/arm-linux/print_u32s.zig new file mode 100644 index 0000000000..92fad75ddf --- /dev/null +++ b/test/incremental/arm-linux/print_u32s.zig @@ -0,0 +1,40 @@ +pub fn main() void { + printNumberHex(0x00000000); + printNumberHex(0xaaaaaaaa); + printNumberHex(0xdeadbeef); + printNumberHex(0x31415926); +} + +fn printNumberHex(x: u32) void { + var i: u5 = 28; + while (true) : (i -= 4) { + const digit = (x >> i) & 0xf; + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("0123456789abcdef") + digit), + [arg3] "{r2}" (1), + : "memory" + ); + + if (i == 0) break; + } + asm volatile ("svc #0" + : + : [number] "{r7}" (4), + [arg1] "{r0}" (1), + [arg2] "{r1}" (@ptrToInt("\n")), + [arg3] "{r2}" (1), + : "memory" + ); +} + +// run +// target=arm-linux +// +// 00000000 +// aaaaaaaa +// deadbeef +// 31415926 +// diff --git a/test/incremental/arm-linux/spilling_registers.0.zig b/test/incremental/arm-linux/spilling_registers.0.zig new file mode 100644 index 0000000000..ac74e071ad --- /dev/null +++ b/test/incremental/arm-linux/spilling_registers.0.zig @@ -0,0 +1,38 @@ +pub fn main() void { + assert(add(3, 4) == 791); +} + +fn add(a: u32, b: u32) u32 { + const x: u32 = blk: { + const c = a + b; // 7 + const d = a + c; // 10 + const e = d + b; // 14 + const f = d + e; // 24 + const g = e + f; // 38 + const h = f + g; // 62 + const i = g + h; // 100 + const j = i + d; // 110 + const k = i + j; // 210 + const l = k + c; // 217 + const m = l + d; // 227 + const n = m + e; // 241 + const o = n + f; // 265 + const p = o + g; // 303 + const q = p + h; // 365 + const r = q + i; // 465 + const s = r + j; // 575 + const t = s + k; // 785 + break :blk t; + }; + const y = x + a; // 788 + const z = y + a; // 791 + return z; +} + +fn assert(ok: bool) void { + if (!ok) unreachable; +} + +// run +// target=arm-linux +// diff --git a/test/incremental/arm-linux/spilling_registers.1.zig b/test/incremental/arm-linux/spilling_registers.1.zig new file mode 100644 index 0000000000..f401a5d7b7 --- /dev/null +++ b/test/incremental/arm-linux/spilling_registers.1.zig @@ -0,0 +1,37 @@ +pub fn main() void { + assert(addMul(3, 4) == 357747496); +} + +fn addMul(a: u32, b: u32) u32 { + const x: u32 = blk: { + const c = a + b; // 7 + const d = a + c; // 10 + const e = d + b; // 14 + const f = d + e; // 24 + const g = e + f; // 38 + const h = f + g; // 62 + const i = g + h; // 100 + const j = i + d; // 110 + const k = i + j; // 210 + const l = k + c; // 217 + const m = l * d; // 2170 + const n = m + e; // 2184 + const o = n * f; // 52416 + const p = o + g; // 52454 + const q = p * h; // 3252148 + const r = q + i; // 3252248 + const s = r * j; // 357747280 + const t = s + k; // 357747490 + break :blk t; + }; + const y = x + a; // 357747493 + const z = y + a; // 357747496 + return z; +} + +fn assert(ok: bool) void { + if (!ok) unreachable; +} + +// run +// diff --git a/test/incremental/non_leaf_functions.zig b/test/incremental/non_leaf_functions.zig new file mode 100644 index 0000000000..cb1737130e --- /dev/null +++ b/test/incremental/non_leaf_functions.zig @@ -0,0 +1,12 @@ +pub fn main() void { + foo(); +} + +fn foo() void { + bar(); +} + +fn bar() void {} + +// run +// diff --git a/test/incremental/recursive_fibonacci.zig b/test/incremental/recursive_fibonacci.zig new file mode 100644 index 0000000000..4e284e3fc1 --- /dev/null +++ b/test/incremental/recursive_fibonacci.zig @@ -0,0 +1,24 @@ +pub fn main() void { + assert(fib(0) == 0); + assert(fib(1) == 1); + assert(fib(2) == 1); + assert(fib(3) == 2); + assert(fib(10) == 55); + assert(fib(20) == 6765); +} + +fn fib(n: u32) u32 { + if (n < 2) { + return n; + } else { + return fib(n - 2) + fib(n - 1); + } +} + +fn assert(ok: bool) void { + if (!ok) unreachable; +} + +// run +// target=arm-linux,x86_64-linux,x86_64-macos,wasm32-wasi +// diff --git a/test/incremental/save_function_return_values_in_callee_preserved_register.zig b/test/incremental/save_function_return_values_in_callee_preserved_register.zig new file mode 100644 index 0000000000..a201903808 --- /dev/null +++ b/test/incremental/save_function_return_values_in_callee_preserved_register.zig @@ -0,0 +1,22 @@ +pub fn main() void { + assert(foo() == 43); +} + +fn foo() u32 { + return bar() + baz(42); +} + +fn bar() u32 { + return 1; +} + +fn baz(x: u32) u32 { + return x; +} + +fn assert(ok: bool) void { + if (!ok) unreachable; +} + +// run +// diff --git a/test/stage2/arm.zig b/test/stage2/arm.zig deleted file mode 100644 index a0afcf9d6f..0000000000 --- a/test/stage2/arm.zig +++ /dev/null @@ -1,798 +0,0 @@ -const std = @import("std"); -const TestContext = @import("../../src/test.zig").TestContext; - -const linux_arm = std.zig.CrossTarget{ - .cpu_arch = .arm, - .os_tag = .linux, -}; - -pub fn addCases(ctx: *TestContext) !void { - { - var case = ctx.exe("linux_arm hello world", linux_arm); - // Hello world using _start and inline asm. - case.addCompareOutput( - \\pub export fn _start() noreturn { - \\ print(); - \\ exit(); - \\} - \\ - \\fn print() void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("Hello, World!\n")), - \\ [arg3] "{r2}" (14) - \\ : "memory" - \\ ); - \\ return; - \\} - \\ - \\fn exit() noreturn { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (1), - \\ [arg1] "{r0}" (0) - \\ : "memory" - \\ ); - \\ unreachable; - \\} - , - "Hello, World!\n", - ); - } - - { - var case = ctx.exe("parameters and return values", linux_arm); - // Testing simple parameters and return values - // - // TODO: The parameters to the asm statement in print() had to - // be in a specific order because otherwise the write to r0 - // would overwrite the len parameter which resides in r0 - case.addCompareOutput( - \\pub fn main() void { - \\ print(id(14)); - \\} - \\ - \\fn id(x: u32) u32 { - \\ return x; - \\} - \\ - \\fn print(len: u32) void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg3] "{r2}" (len), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("Hello, World!\n")) - \\ : "memory" - \\ ); - \\ return; - \\} - , - "Hello, World!\n", - ); - - case.addCompareOutput( - \\pub fn main() void { - \\ assert(add(1, 2, 3, 4, 5, 6) == 21); - \\} - \\ - \\fn add(a: u32, b: u32, c: u32, d: u32, e: u32, f: u32) u32 { - \\ return a + b + c + d + e + f; - \\} - \\ - \\pub fn assert(ok: bool) void { - \\ if (!ok) unreachable; // assertion failure - \\} - , - "", - ); - } - - { - var case = ctx.exe("non-leaf functions", linux_arm); - // Testing non-leaf functions - case.addCompareOutput( - \\pub fn main() void { - \\ foo(); - \\} - \\ - \\fn foo() void { - \\ bar(); - \\} - \\ - \\fn bar() void {} - , - "", - ); - } - - { - var case = ctx.exe("arithmetic operations", linux_arm); - - // Add two numbers - case.addCompareOutput( - \\pub fn main() void { - \\ print(2, 4); - \\ print(1, 7); - \\} - \\ - \\fn print(a: u32, b: u32) void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg3] "{r2}" (a + b), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("123456789")) - \\ : "memory" - \\ ); - \\ return; - \\} - , - "12345612345678", - ); - - // Subtract two numbers - case.addCompareOutput( - \\pub fn main() void { - \\ print(10, 5); - \\ print(4, 3); - \\} - \\ - \\fn print(a: u32, b: u32) void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg3] "{r2}" (a - b), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("123456789")) - \\ : "memory" - \\ ); - \\ return; - \\} - , - "123451", - ); - - // Bitwise And - case.addCompareOutput( - \\pub fn main() void { - \\ print(8, 9); - \\ print(3, 7); - \\} - \\ - \\fn print(a: u32, b: u32) void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg3] "{r2}" (a & b), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("123456789")) - \\ : "memory" - \\ ); - \\ return; - \\} - , - "12345678123", - ); - - // Bitwise Or - case.addCompareOutput( - \\pub fn main() void { - \\ print(4, 2); - \\ print(3, 7); - \\} - \\ - \\fn print(a: u32, b: u32) void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg3] "{r2}" (a | b), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("123456789")) - \\ : "memory" - \\ ); - \\ return; - \\} - , - "1234561234567", - ); - - // Bitwise Xor - case.addCompareOutput( - \\pub fn main() void { - \\ print(42, 42); - \\ print(3, 5); - \\} - \\ - \\fn print(a: u32, b: u32) void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg3] "{r2}" (a ^ b), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("123456789")) - \\ : "memory" - \\ ); - \\ return; - \\} - , - "123456", - ); - - // Bit Shift Left - case.addCompareOutput( - \\pub fn main() void { - \\ var x: u32 = 1; - \\ assert(x << 1 == 2); - \\ - \\ x <<= 1; - \\ assert(x << 2 == 8); - \\ assert(x << 3 == 16); - \\} - \\ - \\pub fn assert(ok: bool) void { - \\ if (!ok) unreachable; // assertion failure - \\} - , - "", - ); - - // Bit Shift Right - case.addCompareOutput( - \\pub fn main() void { - \\ var a: u32 = 1024; - \\ assert(a >> 1 == 512); - \\ - \\ a >>= 1; - \\ assert(a >> 2 == 128); - \\ assert(a >> 3 == 64); - \\ assert(a >> 4 == 32); - \\ assert(a >> 5 == 16); - \\ assert(a >> 6 == 8); - \\ assert(a >> 7 == 4); - \\ assert(a >> 8 == 2); - \\ assert(a >> 9 == 1); - \\} - \\ - \\pub fn assert(ok: bool) void { - \\ if (!ok) unreachable; // assertion failure - \\} - , - "", - ); - } - - { - var case = ctx.exe("if statements", linux_arm); - // Simple if statement in assert - case.addCompareOutput( - \\pub fn main() void { - \\ var x: u32 = 123; - \\ var y: u32 = 42; - \\ assert(x > y); - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - } - - { - var case = ctx.exe("while loops", linux_arm); - // Simple while loop with assert - case.addCompareOutput( - \\pub fn main() void { - \\ var x: u32 = 2020; - \\ var i: u32 = 0; - \\ while (x > 0) { - \\ x -= 2; - \\ i += 1; - \\ } - \\ assert(i == 1010); - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - } - - { - var case = ctx.exe("integer multiplication", linux_arm); - // Simple u32 integer multiplication - case.addCompareOutput( - \\pub fn main() void { - \\ assert(mul(1, 1) == 1); - \\ assert(mul(42, 1) == 42); - \\ assert(mul(1, 42) == 42); - \\ assert(mul(123, 42) == 5166); - \\} - \\ - \\fn mul(x: u32, y: u32) u32 { - \\ return x * y; - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - } - - { - var case = ctx.exe("save function return values in callee preserved register", linux_arm); - // Here, it is necessary to save the result of bar() into a - // callee preserved register, otherwise it will be overwritten - // by the first parameter to baz. - case.addCompareOutput( - \\pub fn main() void { - \\ assert(foo() == 43); - \\} - \\ - \\fn foo() u32 { - \\ return bar() + baz(42); - \\} - \\ - \\fn bar() u32 { - \\ return 1; - \\} - \\ - \\fn baz(x: u32) u32 { - \\ return x; - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - } - - { - var case = ctx.exe("enums", linux_arm); - case.addCompareOutput( - \\const Number = enum { one, two, three }; - \\ - \\pub fn main() void { - \\ var x: Number = .one; - \\ var y = Number.two; - \\ var z = @intToEnum(Number, 2); - \\ assert(@enumToInt(x) == 0); - \\ assert(@enumToInt(y) == 1); - \\ assert(@enumToInt(z) == 2); - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; // assertion failure - \\} - , - "", - ); - - case.addCompareOutput( - \\const Number = enum { one, two, three }; - \\ - \\pub fn main() void { - \\ var x: Number = .one; - \\ var y = Number.two; - \\ assert(@enumToInt(x) < @enumToInt(y)); - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; // assertion failure - \\} - , - "", - ); - } - - { - var case = ctx.exe("recursive fibonacci", linux_arm); - case.addCompareOutput( - \\pub fn main() void { - \\ assert(fib(0) == 0); - \\ assert(fib(1) == 1); - \\ assert(fib(2) == 1); - \\ assert(fib(3) == 2); - \\ assert(fib(10) == 55); - \\ assert(fib(20) == 6765); - \\} - \\ - \\fn fib(n: u32) u32 { - \\ if (n < 2) { - \\ return n; - \\ } else { - \\ return fib(n - 2) + fib(n - 1); - \\ } - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - } - - { - var case = ctx.exe("spilling registers", linux_arm); - case.addCompareOutput( - \\pub fn main() void { - \\ assert(add(3, 4) == 791); - \\} - \\ - \\fn add(a: u32, b: u32) u32 { - \\ const x: u32 = blk: { - \\ const c = a + b; // 7 - \\ const d = a + c; // 10 - \\ const e = d + b; // 14 - \\ const f = d + e; // 24 - \\ const g = e + f; // 38 - \\ const h = f + g; // 62 - \\ const i = g + h; // 100 - \\ const j = i + d; // 110 - \\ const k = i + j; // 210 - \\ const l = k + c; // 217 - \\ const m = l + d; // 227 - \\ const n = m + e; // 241 - \\ const o = n + f; // 265 - \\ const p = o + g; // 303 - \\ const q = p + h; // 365 - \\ const r = q + i; // 465 - \\ const s = r + j; // 575 - \\ const t = s + k; // 785 - \\ break :blk t; - \\ }; - \\ const y = x + a; // 788 - \\ const z = y + a; // 791 - \\ return z; - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - - case.addCompareOutput( - \\pub fn main() void { - \\ assert(addMul(3, 4) == 357747496); - \\} - \\ - \\fn addMul(a: u32, b: u32) u32 { - \\ const x: u32 = blk: { - \\ const c = a + b; // 7 - \\ const d = a + c; // 10 - \\ const e = d + b; // 14 - \\ const f = d + e; // 24 - \\ const g = e + f; // 38 - \\ const h = f + g; // 62 - \\ const i = g + h; // 100 - \\ const j = i + d; // 110 - \\ const k = i + j; // 210 - \\ const l = k + c; // 217 - \\ const m = l * d; // 2170 - \\ const n = m + e; // 2184 - \\ const o = n * f; // 52416 - \\ const p = o + g; // 52454 - \\ const q = p * h; // 3252148 - \\ const r = q + i; // 3252248 - \\ const s = r * j; // 357747280 - \\ const t = s + k; // 357747490 - \\ break :blk t; - \\ }; - \\ const y = x + a; // 357747493 - \\ const z = y + a; // 357747496 - \\ return z; - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - } - - { - var case = ctx.exe("print u32s", linux_arm); - case.addCompareOutput( - \\pub fn main() void { - \\ printNumberHex(0x00000000); - \\ printNumberHex(0xaaaaaaaa); - \\ printNumberHex(0xdeadbeef); - \\ printNumberHex(0x31415926); - \\} - \\ - \\fn printNumberHex(x: u32) void { - \\ var i: u5 = 28; - \\ while (true) : (i -= 4) { - \\ const digit = (x >> i) & 0xf; - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("0123456789abcdef") + digit), - \\ [arg3] "{r2}" (1) - \\ : "memory" - \\ ); - \\ - \\ if (i == 0) break; - \\ } - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("\n")), - \\ [arg3] "{r2}" (1) - \\ : "memory" - \\ ); - \\} - , - \\00000000 - \\aaaaaaaa - \\deadbeef - \\31415926 - \\ - , - ); - } - - { - var case = ctx.exe("save compare flags", linux_arm); - case.addCompareOutput( - \\pub fn main() void { - \\ foo(2, 1); - \\} - \\ - \\fn foo(x: u32, y: u32) void { - \\ const b = x > y; - \\ assert(b); - \\ assert(b); - \\} - \\ - \\pub fn assert(ok: bool) void { - \\ if (!ok) unreachable; // assertion failure - \\} - , - "", - ); - } - - { - var case = ctx.exe("optionals", linux_arm); - case.addCompareOutput( - \\var x: u32 = 42; - \\ - \\pub fn main() void { - \\ var p: ?*u32 = null; - \\ assert(p == null); - \\ p = &x; - \\ assert(p != null); - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - } - - { - var case = ctx.exe("errors", linux_arm); - case.addCompareOutput( - \\pub fn main() void { - \\ foo() catch print(); - \\} - \\ - \\fn foo() anyerror!void {} - \\ - \\fn print() void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("Hello, World!\n")), - \\ [arg3] "{r2}" ("Hello, World!\n".len), - \\ : "memory" - \\ ); - \\ return; - \\} - , - "", - ); - - case.addCompareOutput( - \\pub fn main() void { - \\ foo() catch print(); - \\} - \\ - \\fn foo() anyerror!void { - \\ return error.Test; - \\} - \\ - \\fn print() void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("Hello, World!\n")), - \\ [arg3] "{r2}" ("Hello, World!\n".len), - \\ : "memory" - \\ ); - \\ return; - \\} - , - "Hello, World!\n", - ); - - case.addCompareOutput( - \\pub fn main() void { - \\ foo() catch |err| { - \\ assert(err == error.Foo); - \\ assert(err != error.Bar); - \\ assert(err != error.Baz); - \\ }; - \\ bar() catch |err| { - \\ assert(err != error.Foo); - \\ assert(err == error.Bar); - \\ assert(err != error.Baz); - \\ }; - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - \\ - \\fn foo() anyerror!void { - \\ return error.Foo; - \\} - \\ - \\fn bar() anyerror!void { - \\ return error.Bar; - \\} - , - "", - ); - - case.addCompareOutput( - \\pub fn main() void { - \\ foo() catch unreachable; - \\} - \\ - \\fn foo() anyerror!void { - \\ try bar(); - \\} - \\ - \\fn bar() anyerror!void {} - , - "", - ); - } - - { - var case = ctx.exe("slices", linux_arm); - case.addCompareOutput( - \\var array = [_]u32{ 0, 42, 123, 69 }; - \\var s: []const u32 = &array; - \\ - \\pub fn main() void { - \\ assert(s[0] == 0); - \\ assert(s[1] == 42); - \\ assert(s[2] == 123); - \\ assert(s[3] == 69); - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - } - - { - var case = ctx.exe("structs", linux_arm); - case.addCompareOutput( - \\var array = [_]SomeStruct{ - \\ .{ .a = 0, .b = 42, .c = 69 }, - \\ .{ .a = 1, .b = 2, .c = 3 }, - \\ .{ .a = 123, .b = 456, .c = 789 }, - \\}; - \\var s: []const SomeStruct = &array; - \\ - \\var some_struct: SomeStruct = .{ - \\ .a = 0, - \\ .b = 42, - \\ .c = 69, - \\}; - \\ - \\const SomeStruct = struct { - \\ a: u32, - \\ b: u32, - \\ c: u32, - \\}; - \\ - \\pub fn main() void { - \\ assert(some_struct.a == 0); - \\ assert(some_struct.b == 42); - \\ assert(some_struct.c == 69); - \\ - \\ assert(s[0].a == 0); - \\ assert(s[0].b == 42); - \\ assert(s[0].c == 69); - \\ assert(s[1].a == 1); - \\ assert(s[1].b == 2); - \\ assert(s[1].c == 3); - \\ assert(s[2].a == 123); - \\ assert(s[2].b == 456); - \\ assert(s[2].c == 789); - \\} - \\ - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - , - "", - ); - } - - { - var case = ctx.exe("function pointers", linux_arm); - case.addCompareOutput( - \\const PrintFn = *const fn () void; - \\ - \\pub fn main() void { - \\ var printFn: PrintFn = stopSayingThat; - \\ var i: u32 = 0; - \\ while (i < 4) : (i += 1) printFn(); - \\ - \\ printFn = moveEveryZig; - \\ printFn(); - \\} - \\ - \\fn stopSayingThat() void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("Hello, my name is Inigo Montoya; you killed my father, prepare to die.\n")), - \\ [arg3] "{r2}" ("Hello, my name is Inigo Montoya; you killed my father, prepare to die.\n".len), - \\ : "memory" - \\ ); - \\ return; - \\} - \\ - \\fn moveEveryZig() void { - \\ asm volatile ("svc #0" - \\ : - \\ : [number] "{r7}" (4), - \\ [arg1] "{r0}" (1), - \\ [arg2] "{r1}" (@ptrToInt("All your codebase are belong to us\n")), - \\ [arg3] "{r2}" ("All your codebase are belong to us\n".len), - \\ : "memory" - \\ ); - \\ return; - \\} - , - \\Hello, my name is Inigo Montoya; you killed my father, prepare to die. - \\Hello, my name is Inigo Montoya; you killed my father, prepare to die. - \\Hello, my name is Inigo Montoya; you killed my father, prepare to die. - \\Hello, my name is Inigo Montoya; you killed my father, prepare to die. - \\All your codebase are belong to us - \\ - , - ); - } -}