Commit 73d16d015e

Andrew Kelley <andrew@ziglang.org>
2020-08-21 02:25:09
stage2: reorganize tests
The main test cases are now in `test/stage2/test.zig` which can then call addCases on other files if it wants to organize things differently.
1 parent 56ea04c
Changed files (2)
test/stage2/compare_output.zig
@@ -1,723 +0,0 @@
-const std = @import("std");
-const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
-// self-hosted does not yet support PE executable files / COFF object files
-// or mach-o files. So we do these test cases cross compiling for x86_64-linux.
-const linux_x64 = std.zig.CrossTarget{
-    .cpu_arch = .x86_64,
-    .os_tag = .linux,
-};
-
-const linux_riscv64 = std.zig.CrossTarget{
-    .cpu_arch = .riscv64,
-    .os_tag = .linux,
-};
-
-const wasi = std.zig.CrossTarget{
-    .cpu_arch = .wasm32,
-    .os_tag = .wasi,
-};
-
-pub fn addCases(ctx: *TestContext) !void {
-    {
-        var case = ctx.exe("hello world with updates", linux_x64);
-
-        case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
-
-        // Incorrect return type
-        case.addError(
-            \\export fn _start() noreturn {
-            \\}
-        , &[_][]const u8{":2:1: error: expected noreturn, found void"});
-
-        // Regular old hello world
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    print();
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn print() void {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (1),
-            \\          [arg1] "{rdi}" (1),
-            \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
-            \\          [arg3] "{rdx}" (14)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    return;
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "Hello, World!\n",
-        );
-        // Now change the message only
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    print();
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn print() void {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (1),
-            \\          [arg1] "{rdi}" (1),
-            \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
-            \\          [arg3] "{rdx}" (104)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    return;
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
-        );
-        // Now we print it twice.
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    print();
-            \\    print();
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn print() void {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (1),
-            \\          [arg1] "{rdi}" (1),
-            \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
-            \\          [arg3] "{rdx}" (104)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    return;
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
-            \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
-            \\
-        );
-    }
-
-    {
-        var case = ctx.exe("hello world", linux_riscv64);
-        // Regular old hello world
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    print();
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn print() void {
-            \\    asm volatile ("ecall"
-            \\        :
-            \\        : [number] "{a7}" (64),
-            \\          [arg1] "{a0}" (1),
-            \\          [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
-            \\          [arg3] "{a2}" ("Hello, World!\n".len)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    return;
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("ecall"
-            \\        :
-            \\        : [number] "{a7}" (94),
-            \\          [arg1] "{a0}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "Hello, World!\n",
-        );
-    }
-
-    {
-        var case = ctx.exe("adding numbers at comptime", linux_x64);
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (1),
-            \\          [arg1] "{rdi}" (1),
-            \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
-            \\          [arg3] "{rdx}" (10 + 4)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "Hello, World!\n",
-        );
-    }
-
-    {
-        var case = ctx.exe("adding numbers at runtime", linux_x64);
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    add(3, 4);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn add(a: u32, b: u32) void {
-            \\    if (a + b != 7) unreachable;
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-    }
-
-    {
-        var case = ctx.exe("substracting numbers at runtime", linux_x64);
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    sub(7, 4);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn sub(a: u32, b: u32) void {
-            \\    if (a - b != 3) unreachable;
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-    }
-
-    {
-        var case = ctx.exe("assert function", linux_x64);
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    add(3, 4);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn add(a: u32, b: u32) void {
-            \\    assert(a + b == 7);
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // Tests copying a register. For the `c = a + b`, it has to
-        // preserve both a and b, because they are both used later.
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    add(3, 4);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn add(a: u32, b: u32) void {
-            \\    const c = a + b; // 7
-            \\    const d = a + c; // 10
-            \\    const e = d + b; // 14
-            \\    assert(e == 14);
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // More stress on the liveness detection.
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    add(3, 4);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn add(a: u32, b: u32) void {
-            \\    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
-            \\    assert(i == 100);
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // Requires a second move. The register allocator should figure out to re-use rax.
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    add(3, 4);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn add(a: u32, b: u32) void {
-            \\    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
-            \\    assert(j == 110);
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // Now we test integer return values.
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    assert(add(3, 4) == 7);
-            \\    assert(add(20, 10) == 30);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn add(a: u32, b: u32) u32 {
-            \\    return a + b;
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // Local mutable variables.
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    assert(add(3, 4) == 7);
-            \\    assert(add(20, 10) == 30);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn add(a: u32, b: u32) u32 {
-            \\    var x: u32 = undefined;
-            \\    x = 0;
-            \\    x += a;
-            \\    x += b;
-            \\    return x;
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // Optionals
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    const a: u32 = 2;
-            \\    const b: ?u32 = a;
-            \\    const c = b.?;
-            \\    if (c != 2) unreachable;
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // While loops
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    var i: u32 = 0;
-            \\    while (i < 4) : (i += 1) print();
-            \\    assert(i == 4);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn print() void {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (1),
-            \\          [arg1] "{rdi}" (1),
-            \\          [arg2] "{rsi}" (@ptrToInt("hello\n")),
-            \\          [arg3] "{rdx}" (6)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    return;
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "hello\nhello\nhello\nhello\n",
-        );
-
-        // Labeled blocks (no conditional branch)
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    assert(add(3, 4) == 20);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\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
-            \\        break :blk e;
-            \\    };
-            \\    const y = x + a; // 17
-            \\    const z = y + a; // 20
-            \\    return z;
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // This catches a possible bug in the logic for re-using dying operands.
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    assert(add(3, 4) == 116);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\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
-            \\        break :blk j;
-            \\    };
-            \\    const y = x + a; // 113
-            \\    const z = y + a; // 116
-            \\    return z;
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // Character literals and multiline strings.
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    const ignore = 
-            \\        \\ cool thx
-            \\        \\
-            \\    ;
-            \\    add('ぁ', '\x03');
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn add(a: u32, b: u32) void {
-            \\    assert(a + b == 12356);
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-
-        // Global const.
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    add(aa, bb);
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\const aa = 'ぁ';
-            \\const bb = '\x03';
-            \\
-            \\fn add(a: u32, b: u32) void {
-            \\    assert(a + b == 12356);
-            \\}
-            \\
-            \\pub fn assert(ok: bool) void {
-            \\    if (!ok) unreachable; // assertion failure
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("syscall"
-            \\        :
-            \\        : [number] "{rax}" (231),
-            \\          [arg1] "{rdi}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "",
-        );
-    }
-
-    {
-        var case = ctx.exe("wasm function calls", wasi);
-
-        case.addCompareOutput(
-            \\export fn _start() u32 {
-            \\    foo();
-            \\    bar();
-            \\    return 42;
-            \\}
-            \\fn foo() void {
-            \\    bar();
-            \\    bar();
-            \\}
-            \\fn bar() void {}
-        ,
-            "42\n",
-        );
-
-        case.addCompareOutput(
-            \\export fn _start() i64 {
-            \\    bar();
-            \\    foo();
-            \\    foo();
-            \\    bar();
-            \\    foo();
-            \\    bar();
-            \\    return 42;
-            \\}
-            \\fn foo() void {
-            \\    bar();
-            \\}
-            \\fn bar() void {}
-        ,
-            "42\n",
-        );
-
-        case.addCompareOutput(
-            \\export fn _start() f32 {
-            \\    bar();
-            \\    foo();
-            \\    return 42.0;
-            \\}
-            \\fn foo() void {
-            \\    bar();
-            \\    bar();
-            \\    bar();
-            \\}
-            \\fn bar() void {}
-        ,
-            // This is what you get when you take the bits of the IEE-754
-            // representation of 42.0 and reinterpret them as an unsigned
-            // integer. Guess that's a bug in wasmtime.
-            "1109917696\n",
-        );
-    }
-
-    ctx.compileError("function redefinition", linux_x64,
-        \\fn entry() void {}
-        \\fn entry() void {}
-    , &[_][]const u8{":2:4: error: redefinition of 'entry'"});
-
-    ctx.compileError("extern variable has no type", linux_x64,
-        \\comptime {
-        \\    _ = foo;
-        \\}
-        \\extern var foo;
-    , &[_][]const u8{":4:1: error: unable to infer variable type"});
-}
test/stage2/test.zig
@@ -1,7 +1,726 @@
+const std = @import("std");
 const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
 
+// self-hosted does not yet support PE executable files / COFF object files
+// or mach-o files. So we do these test cases cross compiling for x86_64-linux.
+const linux_x64 = std.zig.CrossTarget{
+    .cpu_arch = .x86_64,
+    .os_tag = .linux,
+};
+
+const linux_riscv64 = std.zig.CrossTarget{
+    .cpu_arch = .riscv64,
+    .os_tag = .linux,
+};
+
+const wasi = std.zig.CrossTarget{
+    .cpu_arch = .wasm32,
+    .os_tag = .wasi,
+};
+
 pub fn addCases(ctx: *TestContext) !void {
-    try @import("compare_output.zig").addCases(ctx);
     try @import("zir.zig").addCases(ctx);
     try @import("cbe.zig").addCases(ctx);
+    {
+        var case = ctx.exe("hello world with updates", linux_x64);
+
+        case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
+
+        // Incorrect return type
+        case.addError(
+            \\export fn _start() noreturn {
+            \\}
+        , &[_][]const u8{":2:1: error: expected noreturn, found void"});
+
+        // Regular old hello world
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    print();
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn print() void {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (1),
+            \\          [arg1] "{rdi}" (1),
+            \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
+            \\          [arg3] "{rdx}" (14)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    return;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "Hello, World!\n",
+        );
+        // Now change the message only
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    print();
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn print() void {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (1),
+            \\          [arg1] "{rdi}" (1),
+            \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
+            \\          [arg3] "{rdx}" (104)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    return;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
+        );
+        // Now we print it twice.
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    print();
+            \\    print();
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn print() void {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (1),
+            \\          [arg1] "{rdi}" (1),
+            \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
+            \\          [arg3] "{rdx}" (104)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    return;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
+            \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
+            \\
+        );
+    }
+
+    {
+        var case = ctx.exe("hello world", linux_riscv64);
+        // Regular old hello world
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    print();
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn print() void {
+            \\    asm volatile ("ecall"
+            \\        :
+            \\        : [number] "{a7}" (64),
+            \\          [arg1] "{a0}" (1),
+            \\          [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
+            \\          [arg3] "{a2}" ("Hello, World!\n".len)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    return;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("ecall"
+            \\        :
+            \\        : [number] "{a7}" (94),
+            \\          [arg1] "{a0}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "Hello, World!\n",
+        );
+    }
+
+    {
+        var case = ctx.exe("adding numbers at comptime", linux_x64);
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (1),
+            \\          [arg1] "{rdi}" (1),
+            \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
+            \\          [arg3] "{rdx}" (10 + 4)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "Hello, World!\n",
+        );
+    }
+
+    {
+        var case = ctx.exe("adding numbers at runtime", linux_x64);
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    add(3, 4);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn add(a: u32, b: u32) void {
+            \\    if (a + b != 7) unreachable;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+    }
+
+    {
+        var case = ctx.exe("substracting numbers at runtime", linux_x64);
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    sub(7, 4);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn sub(a: u32, b: u32) void {
+            \\    if (a - b != 3) unreachable;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+    }
+
+    {
+        var case = ctx.exe("assert function", linux_x64);
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    add(3, 4);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn add(a: u32, b: u32) void {
+            \\    assert(a + b == 7);
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // Tests copying a register. For the `c = a + b`, it has to
+        // preserve both a and b, because they are both used later.
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    add(3, 4);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn add(a: u32, b: u32) void {
+            \\    const c = a + b; // 7
+            \\    const d = a + c; // 10
+            \\    const e = d + b; // 14
+            \\    assert(e == 14);
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // More stress on the liveness detection.
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    add(3, 4);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn add(a: u32, b: u32) void {
+            \\    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
+            \\    assert(i == 100);
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // Requires a second move. The register allocator should figure out to re-use rax.
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    add(3, 4);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn add(a: u32, b: u32) void {
+            \\    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
+            \\    assert(j == 110);
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // Now we test integer return values.
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    assert(add(3, 4) == 7);
+            \\    assert(add(20, 10) == 30);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn add(a: u32, b: u32) u32 {
+            \\    return a + b;
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // Local mutable variables.
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    assert(add(3, 4) == 7);
+            \\    assert(add(20, 10) == 30);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn add(a: u32, b: u32) u32 {
+            \\    var x: u32 = undefined;
+            \\    x = 0;
+            \\    x += a;
+            \\    x += b;
+            \\    return x;
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // Optionals
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    const a: u32 = 2;
+            \\    const b: ?u32 = a;
+            \\    const c = b.?;
+            \\    if (c != 2) unreachable;
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // While loops
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    var i: u32 = 0;
+            \\    while (i < 4) : (i += 1) print();
+            \\    assert(i == 4);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn print() void {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (1),
+            \\          [arg1] "{rdi}" (1),
+            \\          [arg2] "{rsi}" (@ptrToInt("hello\n")),
+            \\          [arg3] "{rdx}" (6)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    return;
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "hello\nhello\nhello\nhello\n",
+        );
+
+        // Labeled blocks (no conditional branch)
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    assert(add(3, 4) == 20);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\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
+            \\        break :blk e;
+            \\    };
+            \\    const y = x + a; // 17
+            \\    const z = y + a; // 20
+            \\    return z;
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // This catches a possible bug in the logic for re-using dying operands.
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    assert(add(3, 4) == 116);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\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
+            \\        break :blk j;
+            \\    };
+            \\    const y = x + a; // 113
+            \\    const z = y + a; // 116
+            \\    return z;
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // Character literals and multiline strings.
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    const ignore = 
+            \\        \\ cool thx
+            \\        \\
+            \\    ;
+            \\    add('ぁ', '\x03');
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn add(a: u32, b: u32) void {
+            \\    assert(a + b == 12356);
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+
+        // Global const.
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    add(aa, bb);
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\const aa = 'ぁ';
+            \\const bb = '\x03';
+            \\
+            \\fn add(a: u32, b: u32) void {
+            \\    assert(a + b == 12356);
+            \\}
+            \\
+            \\pub fn assert(ok: bool) void {
+            \\    if (!ok) unreachable; // assertion failure
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("syscall"
+            \\        :
+            \\        : [number] "{rax}" (231),
+            \\          [arg1] "{rdi}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "",
+        );
+    }
+
+    {
+        var case = ctx.exe("wasm function calls", wasi);
+
+        case.addCompareOutput(
+            \\export fn _start() u32 {
+            \\    foo();
+            \\    bar();
+            \\    return 42;
+            \\}
+            \\fn foo() void {
+            \\    bar();
+            \\    bar();
+            \\}
+            \\fn bar() void {}
+        ,
+            "42\n",
+        );
+
+        case.addCompareOutput(
+            \\export fn _start() i64 {
+            \\    bar();
+            \\    foo();
+            \\    foo();
+            \\    bar();
+            \\    foo();
+            \\    bar();
+            \\    return 42;
+            \\}
+            \\fn foo() void {
+            \\    bar();
+            \\}
+            \\fn bar() void {}
+        ,
+            "42\n",
+        );
+
+        case.addCompareOutput(
+            \\export fn _start() f32 {
+            \\    bar();
+            \\    foo();
+            \\    return 42.0;
+            \\}
+            \\fn foo() void {
+            \\    bar();
+            \\    bar();
+            \\    bar();
+            \\}
+            \\fn bar() void {}
+        ,
+            // This is what you get when you take the bits of the IEE-754
+            // representation of 42.0 and reinterpret them as an unsigned
+            // integer. Guess that's a bug in wasmtime.
+            "1109917696\n",
+        );
+    }
+
+    ctx.compileError("function redefinition", linux_x64,
+        \\fn entry() void {}
+        \\fn entry() void {}
+    , &[_][]const u8{":2:4: error: redefinition of 'entry'"});
+
+    ctx.compileError("extern variable has no type", linux_x64,
+        \\comptime {
+        \\    _ = foo;
+        \\}
+        \\extern var foo;
+    , &[_][]const u8{":4:1: error: unable to infer variable type"});
 }