zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob 4e57bbf9 (41454B) - Raw


      1 const std = @import("std");
      2 const TestContext = @import("../../src/test.zig").TestContext;
      3 
      4 // Self-hosted has differing levels of support for various architectures. For now we pass explicit
      5 // target parameters to each test case. At some point we will take this to the next level and have
      6 // a set of targets that all test cases run on unless specifically overridden. For now, each test
      7 // case applies to only the specified target.
      8 
      9 const linux_x64 = std.zig.CrossTarget{
     10     .cpu_arch = .x86_64,
     11     .os_tag = .linux,
     12 };
     13 
     14 const macosx_x64 = std.zig.CrossTarget{
     15     .cpu_arch = .x86_64,
     16     .os_tag = .macos,
     17 };
     18 
     19 const linux_riscv64 = std.zig.CrossTarget{
     20     .cpu_arch = .riscv64,
     21     .os_tag = .linux,
     22 };
     23 
     24 const wasi = std.zig.CrossTarget{
     25     .cpu_arch = .wasm32,
     26     .os_tag = .wasi,
     27 };
     28 
     29 pub fn addCases(ctx: *TestContext) !void {
     30     try @import("zir.zig").addCases(ctx);
     31     try @import("cbe.zig").addCases(ctx);
     32     try @import("spu-ii.zig").addCases(ctx);
     33     try @import("arm.zig").addCases(ctx);
     34     try @import("aarch64.zig").addCases(ctx);
     35 
     36     {
     37         var case = ctx.exe("hello world with updates", linux_x64);
     38 
     39         case.addError("", &[_][]const u8{"no entry point found"});
     40 
     41         // Incorrect return type
     42         case.addError(
     43             \\export fn _start() noreturn {
     44             \\}
     45         , &[_][]const u8{":2:1: error: expected noreturn, found void"});
     46 
     47         // Regular old hello world
     48         case.addCompareOutput(
     49             \\export fn _start() noreturn {
     50             \\    print();
     51             \\
     52             \\    exit();
     53             \\}
     54             \\
     55             \\fn print() void {
     56             \\    asm volatile ("syscall"
     57             \\        :
     58             \\        : [number] "{rax}" (1),
     59             \\          [arg1] "{rdi}" (1),
     60             \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
     61             \\          [arg3] "{rdx}" (14)
     62             \\        : "rcx", "r11", "memory"
     63             \\    );
     64             \\    return;
     65             \\}
     66             \\
     67             \\fn exit() noreturn {
     68             \\    asm volatile ("syscall"
     69             \\        :
     70             \\        : [number] "{rax}" (231),
     71             \\          [arg1] "{rdi}" (0)
     72             \\        : "rcx", "r11", "memory"
     73             \\    );
     74             \\    unreachable;
     75             \\}
     76         ,
     77             "Hello, World!\n",
     78         );
     79         // Now change the message only
     80         case.addCompareOutput(
     81             \\export fn _start() noreturn {
     82             \\    print();
     83             \\
     84             \\    exit();
     85             \\}
     86             \\
     87             \\fn print() void {
     88             \\    asm volatile ("syscall"
     89             \\        :
     90             \\        : [number] "{rax}" (1),
     91             \\          [arg1] "{rdi}" (1),
     92             \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
     93             \\          [arg3] "{rdx}" (104)
     94             \\        : "rcx", "r11", "memory"
     95             \\    );
     96             \\    return;
     97             \\}
     98             \\
     99             \\fn exit() noreturn {
    100             \\    asm volatile ("syscall"
    101             \\        :
    102             \\        : [number] "{rax}" (231),
    103             \\          [arg1] "{rdi}" (0)
    104             \\        : "rcx", "r11", "memory"
    105             \\    );
    106             \\    unreachable;
    107             \\}
    108         ,
    109             "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
    110         );
    111         // Now we print it twice.
    112         case.addCompareOutput(
    113             \\export fn _start() noreturn {
    114             \\    print();
    115             \\    print();
    116             \\
    117             \\    exit();
    118             \\}
    119             \\
    120             \\fn print() void {
    121             \\    asm volatile ("syscall"
    122             \\        :
    123             \\        : [number] "{rax}" (1),
    124             \\          [arg1] "{rdi}" (1),
    125             \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
    126             \\          [arg3] "{rdx}" (104)
    127             \\        : "rcx", "r11", "memory"
    128             \\    );
    129             \\    return;
    130             \\}
    131             \\
    132             \\fn exit() noreturn {
    133             \\    asm volatile ("syscall"
    134             \\        :
    135             \\        : [number] "{rax}" (231),
    136             \\          [arg1] "{rdi}" (0)
    137             \\        : "rcx", "r11", "memory"
    138             \\    );
    139             \\    unreachable;
    140             \\}
    141         ,
    142             \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
    143             \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
    144             \\
    145         );
    146     }
    147 
    148     {
    149         var case = ctx.exe("hello world with updates", macosx_x64);
    150         case.addError("", &[_][]const u8{"no entry point found"});
    151 
    152         // Incorrect return type
    153         case.addError(
    154             \\export fn _start() noreturn {
    155             \\}
    156         , &[_][]const u8{":2:1: error: expected noreturn, found void"});
    157 
    158         // Regular old hello world
    159         case.addCompareOutput(
    160             \\export fn _start() noreturn {
    161             \\    print();
    162             \\
    163             \\    exit();
    164             \\}
    165             \\
    166             \\fn print() void {
    167             \\    asm volatile ("syscall"
    168             \\        :
    169             \\        : [number] "{rax}" (0x2000004),
    170             \\          [arg1] "{rdi}" (1),
    171             \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
    172             \\          [arg3] "{rdx}" (14)
    173             \\        : "memory"
    174             \\    );
    175             \\    return;
    176             \\}
    177             \\
    178             \\fn exit() noreturn {
    179             \\    asm volatile ("syscall"
    180             \\        :
    181             \\        : [number] "{rax}" (0x2000001),
    182             \\          [arg1] "{rdi}" (0)
    183             \\        : "memory"
    184             \\    );
    185             \\    unreachable;
    186             \\}
    187         ,
    188             "Hello, World!\n",
    189         );
    190         // Now change the message only
    191         case.addCompareOutput(
    192             \\export fn _start() noreturn {
    193             \\    print();
    194             \\
    195             \\    exit();
    196             \\}
    197             \\
    198             \\fn print() void {
    199             \\    asm volatile ("syscall"
    200             \\        :
    201             \\        : [number] "{rax}" (0x2000004),
    202             \\          [arg1] "{rdi}" (1),
    203             \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
    204             \\          [arg3] "{rdx}" (104)
    205             \\        : "memory"
    206             \\    );
    207             \\    return;
    208             \\}
    209             \\
    210             \\fn exit() noreturn {
    211             \\    asm volatile ("syscall"
    212             \\        :
    213             \\        : [number] "{rax}" (0x2000001),
    214             \\          [arg1] "{rdi}" (0)
    215             \\        : "memory"
    216             \\    );
    217             \\    unreachable;
    218             \\}
    219         ,
    220             "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
    221         );
    222         // Now we print it twice.
    223         case.addCompareOutput(
    224             \\export fn _start() noreturn {
    225             \\    print();
    226             \\    print();
    227             \\
    228             \\    exit();
    229             \\}
    230             \\
    231             \\fn print() void {
    232             \\    asm volatile ("syscall"
    233             \\        :
    234             \\        : [number] "{rax}" (0x2000004),
    235             \\          [arg1] "{rdi}" (1),
    236             \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
    237             \\          [arg3] "{rdx}" (104)
    238             \\        : "memory"
    239             \\    );
    240             \\    return;
    241             \\}
    242             \\
    243             \\fn exit() noreturn {
    244             \\    asm volatile ("syscall"
    245             \\        :
    246             \\        : [number] "{rax}" (0x2000001),
    247             \\          [arg1] "{rdi}" (0)
    248             \\        : "memory"
    249             \\    );
    250             \\    unreachable;
    251             \\}
    252         ,
    253             \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
    254             \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
    255             \\
    256         );
    257     }
    258 
    259     {
    260         var case = ctx.exe("hello world", linux_riscv64);
    261         // Regular old hello world
    262         case.addCompareOutput(
    263             \\export fn _start() noreturn {
    264             \\    print();
    265             \\
    266             \\    exit();
    267             \\}
    268             \\
    269             \\fn print() void {
    270             \\    asm volatile ("ecall"
    271             \\        :
    272             \\        : [number] "{a7}" (64),
    273             \\          [arg1] "{a0}" (1),
    274             \\          [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
    275             \\          [arg3] "{a2}" ("Hello, World!\n".len)
    276             \\        : "rcx", "r11", "memory"
    277             \\    );
    278             \\    return;
    279             \\}
    280             \\
    281             \\fn exit() noreturn {
    282             \\    asm volatile ("ecall"
    283             \\        :
    284             \\        : [number] "{a7}" (94),
    285             \\          [arg1] "{a0}" (0)
    286             \\        : "rcx", "r11", "memory"
    287             \\    );
    288             \\    unreachable;
    289             \\}
    290         ,
    291             "Hello, World!\n",
    292         );
    293     }
    294 
    295     {
    296         var case = ctx.exe("adding numbers at comptime", linux_x64);
    297         case.addCompareOutput(
    298             \\export fn _start() noreturn {
    299             \\    asm volatile ("syscall"
    300             \\        :
    301             \\        : [number] "{rax}" (1),
    302             \\          [arg1] "{rdi}" (1),
    303             \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
    304             \\          [arg3] "{rdx}" (10 + 4)
    305             \\        : "rcx", "r11", "memory"
    306             \\    );
    307             \\    asm volatile ("syscall"
    308             \\        :
    309             \\        : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)),
    310             \\          [arg1] "{rdi}" (0)
    311             \\        : "rcx", "r11", "memory"
    312             \\    );
    313             \\    unreachable;
    314             \\}
    315         ,
    316             "Hello, World!\n",
    317         );
    318     }
    319 
    320     {
    321         var case = ctx.exe("adding numbers at runtime", linux_x64);
    322         case.addCompareOutput(
    323             \\export fn _start() noreturn {
    324             \\    add(3, 4);
    325             \\
    326             \\    exit();
    327             \\}
    328             \\
    329             \\fn add(a: u32, b: u32) void {
    330             \\    if (a + b != 7) unreachable;
    331             \\}
    332             \\
    333             \\fn exit() noreturn {
    334             \\    asm volatile ("syscall"
    335             \\        :
    336             \\        : [number] "{rax}" (231),
    337             \\          [arg1] "{rdi}" (0)
    338             \\        : "rcx", "r11", "memory"
    339             \\    );
    340             \\    unreachable;
    341             \\}
    342         ,
    343             "",
    344         );
    345     }
    346 
    347     {
    348         var case = ctx.exe("subtracting numbers at runtime", linux_x64);
    349         case.addCompareOutput(
    350             \\export fn _start() noreturn {
    351             \\    sub(7, 4);
    352             \\
    353             \\    exit();
    354             \\}
    355             \\
    356             \\fn sub(a: u32, b: u32) void {
    357             \\    if (a - b != 3) unreachable;
    358             \\}
    359             \\
    360             \\fn exit() noreturn {
    361             \\    asm volatile ("syscall"
    362             \\        :
    363             \\        : [number] "{rax}" (231),
    364             \\          [arg1] "{rdi}" (0)
    365             \\        : "rcx", "r11", "memory"
    366             \\    );
    367             \\    unreachable;
    368             \\}
    369         ,
    370             "",
    371         );
    372     }
    373     {
    374         var case = ctx.exe("@TypeOf", linux_x64);
    375         case.addCompareOutput(
    376             \\export fn _start() noreturn {
    377             \\    var x: usize = 0;
    378             \\    const z = @TypeOf(x, @as(u128, 5));
    379             \\    assert(z == u128);
    380             \\
    381             \\    exit();
    382             \\}
    383             \\
    384             \\pub fn assert(ok: bool) void {
    385             \\    if (!ok) unreachable; // assertion failure
    386             \\}
    387             \\
    388             \\fn exit() noreturn {
    389             \\    asm volatile ("syscall"
    390             \\        :
    391             \\        : [number] "{rax}" (231),
    392             \\          [arg1] "{rdi}" (0)
    393             \\        : "rcx", "r11", "memory"
    394             \\    );
    395             \\    unreachable;
    396             \\}
    397         ,
    398             "",
    399         );
    400         case.addCompareOutput(
    401             \\export fn _start() noreturn {
    402             \\    const z = @TypeOf(true);
    403             \\    assert(z == bool);
    404             \\
    405             \\    exit();
    406             \\}
    407             \\
    408             \\pub fn assert(ok: bool) void {
    409             \\    if (!ok) unreachable; // assertion failure
    410             \\}
    411             \\
    412             \\fn exit() noreturn {
    413             \\    asm volatile ("syscall"
    414             \\        :
    415             \\        : [number] "{rax}" (231),
    416             \\          [arg1] "{rdi}" (0)
    417             \\        : "rcx", "r11", "memory"
    418             \\    );
    419             \\    unreachable;
    420             \\}
    421         ,
    422             "",
    423         );
    424         case.addError(
    425             \\export fn _start() noreturn {
    426             \\    const z = @TypeOf(true, 1);
    427             \\    unreachable;
    428             \\}
    429         , &[_][]const u8{":2:29: error: incompatible types: 'bool' and 'comptime_int'"});
    430     }
    431 
    432     {
    433         var case = ctx.exe("assert function", linux_x64);
    434         case.addCompareOutput(
    435             \\export fn _start() noreturn {
    436             \\    add(3, 4);
    437             \\
    438             \\    exit();
    439             \\}
    440             \\
    441             \\fn add(a: u32, b: u32) void {
    442             \\    assert(a + b == 7);
    443             \\}
    444             \\
    445             \\pub fn assert(ok: bool) void {
    446             \\    if (!ok) unreachable; // assertion failure
    447             \\}
    448             \\
    449             \\fn exit() noreturn {
    450             \\    asm volatile ("syscall"
    451             \\        :
    452             \\        : [number] "{rax}" (231),
    453             \\          [arg1] "{rdi}" (0)
    454             \\        : "rcx", "r11", "memory"
    455             \\    );
    456             \\    unreachable;
    457             \\}
    458         ,
    459             "",
    460         );
    461 
    462         // Tests copying a register. For the `c = a + b`, it has to
    463         // preserve both a and b, because they are both used later.
    464         case.addCompareOutput(
    465             \\export fn _start() noreturn {
    466             \\    add(3, 4);
    467             \\
    468             \\    exit();
    469             \\}
    470             \\
    471             \\fn add(a: u32, b: u32) void {
    472             \\    const c = a + b; // 7
    473             \\    const d = a + c; // 10
    474             \\    const e = d + b; // 14
    475             \\    assert(e == 14);
    476             \\}
    477             \\
    478             \\pub fn assert(ok: bool) void {
    479             \\    if (!ok) unreachable; // assertion failure
    480             \\}
    481             \\
    482             \\fn exit() noreturn {
    483             \\    asm volatile ("syscall"
    484             \\        :
    485             \\        : [number] "{rax}" (231),
    486             \\          [arg1] "{rdi}" (0)
    487             \\        : "rcx", "r11", "memory"
    488             \\    );
    489             \\    unreachable;
    490             \\}
    491         ,
    492             "",
    493         );
    494 
    495         // More stress on the liveness detection.
    496         case.addCompareOutput(
    497             \\export fn _start() noreturn {
    498             \\    add(3, 4);
    499             \\
    500             \\    exit();
    501             \\}
    502             \\
    503             \\fn add(a: u32, b: u32) void {
    504             \\    const c = a + b; // 7
    505             \\    const d = a + c; // 10
    506             \\    const e = d + b; // 14
    507             \\    const f = d + e; // 24
    508             \\    const g = e + f; // 38
    509             \\    const h = f + g; // 62
    510             \\    const i = g + h; // 100
    511             \\    assert(i == 100);
    512             \\}
    513             \\
    514             \\pub fn assert(ok: bool) void {
    515             \\    if (!ok) unreachable; // assertion failure
    516             \\}
    517             \\
    518             \\fn exit() noreturn {
    519             \\    asm volatile ("syscall"
    520             \\        :
    521             \\        : [number] "{rax}" (231),
    522             \\          [arg1] "{rdi}" (0)
    523             \\        : "rcx", "r11", "memory"
    524             \\    );
    525             \\    unreachable;
    526             \\}
    527         ,
    528             "",
    529         );
    530 
    531         // Requires a second move. The register allocator should figure out to re-use rax.
    532         case.addCompareOutput(
    533             \\export fn _start() noreturn {
    534             \\    add(3, 4);
    535             \\
    536             \\    exit();
    537             \\}
    538             \\
    539             \\fn add(a: u32, b: u32) void {
    540             \\    const c = a + b; // 7
    541             \\    const d = a + c; // 10
    542             \\    const e = d + b; // 14
    543             \\    const f = d + e; // 24
    544             \\    const g = e + f; // 38
    545             \\    const h = f + g; // 62
    546             \\    const i = g + h; // 100
    547             \\    const j = i + d; // 110
    548             \\    assert(j == 110);
    549             \\}
    550             \\
    551             \\pub fn assert(ok: bool) void {
    552             \\    if (!ok) unreachable; // assertion failure
    553             \\}
    554             \\
    555             \\fn exit() noreturn {
    556             \\    asm volatile ("syscall"
    557             \\        :
    558             \\        : [number] "{rax}" (231),
    559             \\          [arg1] "{rdi}" (0)
    560             \\        : "rcx", "r11", "memory"
    561             \\    );
    562             \\    unreachable;
    563             \\}
    564         ,
    565             "",
    566         );
    567 
    568         // Now we test integer return values.
    569         case.addCompareOutput(
    570             \\export fn _start() noreturn {
    571             \\    assert(add(3, 4) == 7);
    572             \\    assert(add(20, 10) == 30);
    573             \\
    574             \\    exit();
    575             \\}
    576             \\
    577             \\fn add(a: u32, b: u32) u32 {
    578             \\    return a + b;
    579             \\}
    580             \\
    581             \\pub fn assert(ok: bool) void {
    582             \\    if (!ok) unreachable; // assertion failure
    583             \\}
    584             \\
    585             \\fn exit() noreturn {
    586             \\    asm volatile ("syscall"
    587             \\        :
    588             \\        : [number] "{rax}" (231),
    589             \\          [arg1] "{rdi}" (0)
    590             \\        : "rcx", "r11", "memory"
    591             \\    );
    592             \\    unreachable;
    593             \\}
    594         ,
    595             "",
    596         );
    597 
    598         // Local mutable variables.
    599         case.addCompareOutput(
    600             \\export fn _start() noreturn {
    601             \\    assert(add(3, 4) == 7);
    602             \\    assert(add(20, 10) == 30);
    603             \\
    604             \\    exit();
    605             \\}
    606             \\
    607             \\fn add(a: u32, b: u32) u32 {
    608             \\    var x: u32 = undefined;
    609             \\    x = 0;
    610             \\    x += a;
    611             \\    x += b;
    612             \\    return x;
    613             \\}
    614             \\
    615             \\pub fn assert(ok: bool) void {
    616             \\    if (!ok) unreachable; // assertion failure
    617             \\}
    618             \\
    619             \\fn exit() noreturn {
    620             \\    asm volatile ("syscall"
    621             \\        :
    622             \\        : [number] "{rax}" (231),
    623             \\          [arg1] "{rdi}" (0)
    624             \\        : "rcx", "r11", "memory"
    625             \\    );
    626             \\    unreachable;
    627             \\}
    628         ,
    629             "",
    630         );
    631 
    632         // Optionals
    633         case.addCompareOutput(
    634             \\export fn _start() noreturn {
    635             \\    const a: u32 = 2;
    636             \\    const b: ?u32 = a;
    637             \\    const c = b.?;
    638             \\    if (c != 2) unreachable;
    639             \\
    640             \\    exit();
    641             \\}
    642             \\
    643             \\fn exit() noreturn {
    644             \\    asm volatile ("syscall"
    645             \\        :
    646             \\        : [number] "{rax}" (231),
    647             \\          [arg1] "{rdi}" (0)
    648             \\        : "rcx", "r11", "memory"
    649             \\    );
    650             \\    unreachable;
    651             \\}
    652         ,
    653             "",
    654         );
    655 
    656         // While loops
    657         case.addCompareOutput(
    658             \\export fn _start() noreturn {
    659             \\    var i: u32 = 0;
    660             \\    while (i < 4) : (i += 1) print();
    661             \\    assert(i == 4);
    662             \\
    663             \\    exit();
    664             \\}
    665             \\
    666             \\fn print() void {
    667             \\    asm volatile ("syscall"
    668             \\        :
    669             \\        : [number] "{rax}" (1),
    670             \\          [arg1] "{rdi}" (1),
    671             \\          [arg2] "{rsi}" (@ptrToInt("hello\n")),
    672             \\          [arg3] "{rdx}" (6)
    673             \\        : "rcx", "r11", "memory"
    674             \\    );
    675             \\    return;
    676             \\}
    677             \\
    678             \\pub fn assert(ok: bool) void {
    679             \\    if (!ok) unreachable; // assertion failure
    680             \\}
    681             \\
    682             \\fn exit() noreturn {
    683             \\    asm volatile ("syscall"
    684             \\        :
    685             \\        : [number] "{rax}" (231),
    686             \\          [arg1] "{rdi}" (0)
    687             \\        : "rcx", "r11", "memory"
    688             \\    );
    689             \\    unreachable;
    690             \\}
    691         ,
    692             "hello\nhello\nhello\nhello\n",
    693         );
    694 
    695         // Labeled blocks (no conditional branch)
    696         case.addCompareOutput(
    697             \\export fn _start() noreturn {
    698             \\    assert(add(3, 4) == 20);
    699             \\
    700             \\    exit();
    701             \\}
    702             \\
    703             \\fn add(a: u32, b: u32) u32 {
    704             \\    const x: u32 = blk: {
    705             \\        const c = a + b; // 7
    706             \\        const d = a + c; // 10
    707             \\        const e = d + b; // 14
    708             \\        break :blk e;
    709             \\    };
    710             \\    const y = x + a; // 17
    711             \\    const z = y + a; // 20
    712             \\    return z;
    713             \\}
    714             \\
    715             \\pub fn assert(ok: bool) void {
    716             \\    if (!ok) unreachable; // assertion failure
    717             \\}
    718             \\
    719             \\fn exit() noreturn {
    720             \\    asm volatile ("syscall"
    721             \\        :
    722             \\        : [number] "{rax}" (231),
    723             \\          [arg1] "{rdi}" (0)
    724             \\        : "rcx", "r11", "memory"
    725             \\    );
    726             \\    unreachable;
    727             \\}
    728         ,
    729             "",
    730         );
    731 
    732         // This catches a possible bug in the logic for re-using dying operands.
    733         case.addCompareOutput(
    734             \\export fn _start() noreturn {
    735             \\    assert(add(3, 4) == 116);
    736             \\
    737             \\    exit();
    738             \\}
    739             \\
    740             \\fn add(a: u32, b: u32) u32 {
    741             \\    const x: u32 = blk: {
    742             \\        const c = a + b; // 7
    743             \\        const d = a + c; // 10
    744             \\        const e = d + b; // 14
    745             \\        const f = d + e; // 24
    746             \\        const g = e + f; // 38
    747             \\        const h = f + g; // 62
    748             \\        const i = g + h; // 100
    749             \\        const j = i + d; // 110
    750             \\        break :blk j;
    751             \\    };
    752             \\    const y = x + a; // 113
    753             \\    const z = y + a; // 116
    754             \\    return z;
    755             \\}
    756             \\
    757             \\pub fn assert(ok: bool) void {
    758             \\    if (!ok) unreachable; // assertion failure
    759             \\}
    760             \\
    761             \\fn exit() noreturn {
    762             \\    asm volatile ("syscall"
    763             \\        :
    764             \\        : [number] "{rax}" (231),
    765             \\          [arg1] "{rdi}" (0)
    766             \\        : "rcx", "r11", "memory"
    767             \\    );
    768             \\    unreachable;
    769             \\}
    770         ,
    771             "",
    772         );
    773 
    774         // Spilling registers to the stack.
    775         case.addCompareOutput(
    776             \\export fn _start() noreturn {
    777             \\    assert(add(3, 4) == 791);
    778             \\
    779             \\    exit();
    780             \\}
    781             \\
    782             \\fn add(a: u32, b: u32) u32 {
    783             \\    const x: u32 = blk: {
    784             \\        const c = a + b; // 7
    785             \\        const d = a + c; // 10
    786             \\        const e = d + b; // 14
    787             \\        const f = d + e; // 24
    788             \\        const g = e + f; // 38
    789             \\        const h = f + g; // 62
    790             \\        const i = g + h; // 100
    791             \\        const j = i + d; // 110
    792             \\        const k = i + j; // 210
    793             \\        const l = k + c; // 217
    794             \\        const m = l + d; // 227
    795             \\        const n = m + e; // 241
    796             \\        const o = n + f; // 265
    797             \\        const p = o + g; // 303
    798             \\        const q = p + h; // 365
    799             \\        const r = q + i; // 465
    800             \\        const s = r + j; // 575
    801             \\        const t = s + k; // 785
    802             \\        break :blk t;
    803             \\    };
    804             \\    const y = x + a; // 788
    805             \\    const z = y + a; // 791
    806             \\    return z;
    807             \\}
    808             \\
    809             \\pub fn assert(ok: bool) void {
    810             \\    if (!ok) unreachable; // assertion failure
    811             \\}
    812             \\
    813             \\fn exit() noreturn {
    814             \\    asm volatile ("syscall"
    815             \\        :
    816             \\        : [number] "{rax}" (231),
    817             \\          [arg1] "{rdi}" (0)
    818             \\        : "rcx", "r11", "memory"
    819             \\    );
    820             \\    unreachable;
    821             \\}
    822         ,
    823             "",
    824         );
    825 
    826         // Reusing the registers of dead operands playing nicely with conditional branching.
    827         case.addCompareOutput(
    828             \\export fn _start() noreturn {
    829             \\    assert(add(3, 4) == 791);
    830             \\    assert(add(4, 3) == 79);
    831             \\
    832             \\    exit();
    833             \\}
    834             \\
    835             \\fn add(a: u32, b: u32) u32 {
    836             \\    const x: u32 = if (a < b) blk: {
    837             \\        const c = a + b; // 7
    838             \\        const d = a + c; // 10
    839             \\        const e = d + b; // 14
    840             \\        const f = d + e; // 24
    841             \\        const g = e + f; // 38
    842             \\        const h = f + g; // 62
    843             \\        const i = g + h; // 100
    844             \\        const j = i + d; // 110
    845             \\        const k = i + j; // 210
    846             \\        const l = k + c; // 217
    847             \\        const m = l + d; // 227
    848             \\        const n = m + e; // 241
    849             \\        const o = n + f; // 265
    850             \\        const p = o + g; // 303
    851             \\        const q = p + h; // 365
    852             \\        const r = q + i; // 465
    853             \\        const s = r + j; // 575
    854             \\        const t = s + k; // 785
    855             \\        break :blk t;
    856             \\    } else blk: {
    857             \\        const t = b + b + a; // 10
    858             \\        const c = a + t; // 14
    859             \\        const d = c + t; // 24
    860             \\        const e = d + t; // 34
    861             \\        const f = e + t; // 44
    862             \\        const g = f + t; // 54
    863             \\        const h = c + g; // 68
    864             \\        break :blk h + b; // 71
    865             \\    };
    866             \\    const y = x + a; // 788, 75
    867             \\    const z = y + a; // 791, 79
    868             \\    return z;
    869             \\}
    870             \\
    871             \\pub fn assert(ok: bool) void {
    872             \\    if (!ok) unreachable; // assertion failure
    873             \\}
    874             \\
    875             \\fn exit() noreturn {
    876             \\    asm volatile ("syscall"
    877             \\        :
    878             \\        : [number] "{rax}" (231),
    879             \\          [arg1] "{rdi}" (0)
    880             \\        : "rcx", "r11", "memory"
    881             \\    );
    882             \\    unreachable;
    883             \\}
    884         ,
    885             "",
    886         );
    887 
    888         // Character literals and multiline strings.
    889         case.addCompareOutput(
    890             \\export fn _start() noreturn {
    891             \\    const ignore =
    892             \\        \\ cool thx
    893             \\        \\
    894             \\    ;
    895             \\    add('ぁ', '\x03');
    896             \\
    897             \\    exit();
    898             \\}
    899             \\
    900             \\fn add(a: u32, b: u32) void {
    901             \\    assert(a + b == 12356);
    902             \\}
    903             \\
    904             \\pub fn assert(ok: bool) void {
    905             \\    if (!ok) unreachable; // assertion failure
    906             \\}
    907             \\
    908             \\fn exit() noreturn {
    909             \\    asm volatile ("syscall"
    910             \\        :
    911             \\        : [number] "{rax}" (231),
    912             \\          [arg1] "{rdi}" (0)
    913             \\        : "rcx", "r11", "memory"
    914             \\    );
    915             \\    unreachable;
    916             \\}
    917         ,
    918             "",
    919         );
    920 
    921         // Global const.
    922         case.addCompareOutput(
    923             \\export fn _start() noreturn {
    924             \\    add(aa, bb);
    925             \\
    926             \\    exit();
    927             \\}
    928             \\
    929             \\const aa = 'ぁ';
    930             \\const bb = '\x03';
    931             \\
    932             \\fn add(a: u32, b: u32) void {
    933             \\    assert(a + b == 12356);
    934             \\}
    935             \\
    936             \\pub fn assert(ok: bool) void {
    937             \\    if (!ok) unreachable; // assertion failure
    938             \\}
    939             \\
    940             \\fn exit() noreturn {
    941             \\    asm volatile ("syscall"
    942             \\        :
    943             \\        : [number] "{rax}" (231),
    944             \\          [arg1] "{rdi}" (0)
    945             \\        : "rcx", "r11", "memory"
    946             \\    );
    947             \\    unreachable;
    948             \\}
    949         ,
    950             "",
    951         );
    952 
    953         // Array access.
    954         case.addCompareOutput(
    955             \\export fn _start() noreturn {
    956             \\    assert("hello"[0] == 'h');
    957             \\
    958             \\    exit();
    959             \\}
    960             \\
    961             \\pub fn assert(ok: bool) void {
    962             \\    if (!ok) unreachable; // assertion failure
    963             \\}
    964             \\
    965             \\fn exit() noreturn {
    966             \\    asm volatile ("syscall"
    967             \\        :
    968             \\        : [number] "{rax}" (231),
    969             \\          [arg1] "{rdi}" (0)
    970             \\        : "rcx", "r11", "memory"
    971             \\    );
    972             \\    unreachable;
    973             \\}
    974         ,
    975             "",
    976         );
    977 
    978         // 64bit set stack
    979         case.addCompareOutput(
    980             \\export fn _start() noreturn {
    981             \\    var i: u64 = 0xFFEEDDCCBBAA9988;
    982             \\    assert(i == 0xFFEEDDCCBBAA9988);
    983             \\
    984             \\    exit();
    985             \\}
    986             \\
    987             \\pub fn assert(ok: bool) void {
    988             \\    if (!ok) unreachable; // assertion failure
    989             \\}
    990             \\
    991             \\fn exit() noreturn {
    992             \\    asm volatile ("syscall"
    993             \\        :
    994             \\        : [number] "{rax}" (231),
    995             \\          [arg1] "{rdi}" (0)
    996             \\        : "rcx", "r11", "memory"
    997             \\    );
    998             \\    unreachable;
    999             \\}
   1000         ,
   1001             "",
   1002         );
   1003 
   1004         // Basic for loop
   1005         case.addCompareOutput(
   1006             \\export fn _start() noreturn {
   1007             \\    for ("hello") |_| print();
   1008             \\
   1009             \\    exit();
   1010             \\}
   1011             \\
   1012             \\fn print() void {
   1013             \\    asm volatile ("syscall"
   1014             \\        :
   1015             \\        : [number] "{rax}" (1),
   1016             \\          [arg1] "{rdi}" (1),
   1017             \\          [arg2] "{rsi}" (@ptrToInt("hello\n")),
   1018             \\          [arg3] "{rdx}" (6)
   1019             \\        : "rcx", "r11", "memory"
   1020             \\    );
   1021             \\    return;
   1022             \\}
   1023             \\
   1024             \\fn exit() noreturn {
   1025             \\    asm volatile ("syscall"
   1026             \\        :
   1027             \\        : [number] "{rax}" (231),
   1028             \\          [arg1] "{rdi}" (0)
   1029             \\        : "rcx", "r11", "memory"
   1030             \\    );
   1031             \\    unreachable;
   1032             \\}
   1033         ,
   1034             "hello\nhello\nhello\nhello\nhello\n",
   1035         );
   1036 
   1037         // comptime switch
   1038 
   1039         // Basic for loop
   1040         case.addCompareOutput(
   1041             \\pub export fn _start() noreturn {
   1042             \\    assert(foo() == 1);
   1043             \\    exit();
   1044             \\}
   1045             \\
   1046             \\fn foo() u32 {
   1047             \\    const a: comptime_int = 1;
   1048             \\    var b: u32 = 0;
   1049             \\    switch (a) {
   1050             \\        1 => b = 1,
   1051             \\        2 => b = 2,
   1052             \\        else => unreachable,
   1053             \\    }
   1054             \\    return b;
   1055             \\}
   1056             \\
   1057             \\pub fn assert(ok: bool) void {
   1058             \\    if (!ok) unreachable; // assertion failure
   1059             \\}
   1060             \\
   1061             \\fn exit() noreturn {
   1062             \\    asm volatile ("syscall"
   1063             \\        :
   1064             \\        : [number] "{rax}" (231),
   1065             \\          [arg1] "{rdi}" (0)
   1066             \\        : "rcx", "r11", "memory"
   1067             \\    );
   1068             \\    unreachable;
   1069             \\}
   1070         ,
   1071             "",
   1072         );
   1073     }
   1074 
   1075     {
   1076         var case = ctx.exe("basic import", linux_x64);
   1077         case.addCompareOutput(
   1078             \\export fn _start() noreturn {
   1079             \\    @import("print.zig").print();
   1080             \\    exit();
   1081             \\}
   1082             \\
   1083             \\fn exit() noreturn {
   1084             \\    asm volatile ("syscall"
   1085             \\        :
   1086             \\        : [number] "{rax}" (231),
   1087             \\          [arg1] "{rdi}" (@as(usize, 0))
   1088             \\        : "rcx", "r11", "memory"
   1089             \\    );
   1090             \\    unreachable;
   1091             \\}
   1092         ,
   1093             "Hello, World!\n",
   1094         );
   1095         try case.files.append(.{
   1096             .src =
   1097             \\pub fn print() void {
   1098             \\    asm volatile ("syscall"
   1099             \\        :
   1100             \\        : [number] "{rax}" (@as(usize, 1)),
   1101             \\          [arg1] "{rdi}" (@as(usize, 1)),
   1102             \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
   1103             \\          [arg3] "{rdx}" (@as(usize, 14))
   1104             \\        : "rcx", "r11", "memory"
   1105             \\    );
   1106             \\    return;
   1107             \\}
   1108             ,
   1109             .path = "print.zig",
   1110         });
   1111     }
   1112 
   1113     {
   1114         var case = ctx.exe("wasm function calls", wasi);
   1115 
   1116         case.addCompareOutput(
   1117             \\export fn _start() u32 {
   1118             \\    foo();
   1119             \\    bar();
   1120             \\    return 42;
   1121             \\}
   1122             \\fn foo() void {
   1123             \\    bar();
   1124             \\    bar();
   1125             \\}
   1126             \\fn bar() void {}
   1127         ,
   1128             "42\n",
   1129         );
   1130 
   1131         case.addCompareOutput(
   1132             \\export fn _start() i64 {
   1133             \\    bar();
   1134             \\    foo();
   1135             \\    foo();
   1136             \\    bar();
   1137             \\    foo();
   1138             \\    bar();
   1139             \\    return 42;
   1140             \\}
   1141             \\fn foo() void {
   1142             \\    bar();
   1143             \\}
   1144             \\fn bar() void {}
   1145         ,
   1146             "42\n",
   1147         );
   1148 
   1149         case.addCompareOutput(
   1150             \\export fn _start() f32 {
   1151             \\    bar();
   1152             \\    foo();
   1153             \\    return 42.0;
   1154             \\}
   1155             \\fn foo() void {
   1156             \\    bar();
   1157             \\    bar();
   1158             \\    bar();
   1159             \\}
   1160             \\fn bar() void {}
   1161         ,
   1162         // This is what you get when you take the bits of the IEE-754
   1163         // representation of 42.0 and reinterpret them as an unsigned
   1164         // integer. Guess that's a bug in wasmtime.
   1165             "1109917696\n",
   1166         );
   1167     }
   1168 
   1169     ctx.compileError("function redefinition", linux_x64,
   1170         \\fn entry() void {}
   1171         \\fn entry() void {}
   1172     , &[_][]const u8{":2:4: error: redefinition of 'entry'"});
   1173 
   1174     ctx.compileError("compileLog", linux_x64,
   1175         \\export fn _start() noreturn {
   1176         \\  const b = true;
   1177         \\  var f: u32 = 1;
   1178         \\  @compileLog(b, 20, f, x, .foo);
   1179         \\  var y: u32 = true;
   1180         \\  unreachable;
   1181         \\}
   1182         \\fn x() void {}
   1183     , &[_][]const u8{
   1184         ":4:3: error: found compile log statement", ":5:16: error: expected u32, found bool",
   1185     });
   1186 
   1187     // "| true, 20, (runtime value), (function)" // TODO if this is here it invalidates the compile error checker. Need a way to check though.
   1188 
   1189     ctx.compileError("compileError", linux_x64,
   1190         \\export fn _start() noreturn {
   1191         \\  @compileError("this is an error");
   1192         \\  unreachable;
   1193         \\}
   1194     , &[_][]const u8{":2:3: error: this is an error"});
   1195     {
   1196         var case = ctx.obj("variable shadowing", linux_x64);
   1197         case.addError(
   1198             \\export fn _start() noreturn {
   1199             \\    var i: u32 = 10;
   1200             \\    var i: u32 = 10;
   1201             \\    unreachable;
   1202             \\}
   1203         , &[_][]const u8{":3:9: error: redefinition of 'i'"});
   1204         case.addError(
   1205             \\var testing: i64 = 10;
   1206             \\export fn _start() noreturn {
   1207             \\    var testing: i64 = 20;
   1208             \\    unreachable;
   1209             \\}
   1210         , &[_][]const u8{":3:9: error: redefinition of 'testing'"});
   1211     }
   1212 
   1213     {
   1214         var case = ctx.obj("extern variable has no type", linux_x64);
   1215         case.addError(
   1216             \\comptime {
   1217             \\    _ = foo;
   1218             \\}
   1219             \\extern var foo: i32;
   1220         , &[_][]const u8{":2:9: error: unable to resolve comptime value"});
   1221         case.addError(
   1222             \\export fn entry() void {
   1223             \\    _ = foo;
   1224             \\}
   1225             \\extern var foo;
   1226         , &[_][]const u8{":4:1: error: unable to infer variable type"});
   1227     }
   1228 
   1229     {
   1230         var case = ctx.exe("break/continue", linux_x64);
   1231 
   1232         // Break out of loop
   1233         case.addCompareOutput(
   1234             \\export fn _start() noreturn {
   1235             \\    while (true) {
   1236             \\        break;
   1237             \\    }
   1238             \\
   1239             \\    exit();
   1240             \\}
   1241             \\
   1242             \\fn exit() noreturn {
   1243             \\    asm volatile ("syscall"
   1244             \\        :
   1245             \\        : [number] "{rax}" (231),
   1246             \\          [arg1] "{rdi}" (0)
   1247             \\        : "rcx", "r11", "memory"
   1248             \\    );
   1249             \\    unreachable;
   1250             \\}
   1251         ,
   1252             "",
   1253         );
   1254         case.addCompareOutput(
   1255             \\export fn _start() noreturn {
   1256             \\    foo: while (true) {
   1257             \\        break :foo;
   1258             \\    }
   1259             \\
   1260             \\    exit();
   1261             \\}
   1262             \\
   1263             \\fn exit() noreturn {
   1264             \\    asm volatile ("syscall"
   1265             \\        :
   1266             \\        : [number] "{rax}" (231),
   1267             \\          [arg1] "{rdi}" (0)
   1268             \\        : "rcx", "r11", "memory"
   1269             \\    );
   1270             \\    unreachable;
   1271             \\}
   1272         ,
   1273             "",
   1274         );
   1275 
   1276         // Continue in loop
   1277         case.addCompareOutput(
   1278             \\export fn _start() noreturn {
   1279             \\    var i: u64 = 0;
   1280             \\    while (true) : (i+=1) {
   1281             \\        if (i == 4) exit();
   1282             \\        continue;
   1283             \\    }
   1284             \\}
   1285             \\
   1286             \\fn exit() noreturn {
   1287             \\    asm volatile ("syscall"
   1288             \\        :
   1289             \\        : [number] "{rax}" (231),
   1290             \\          [arg1] "{rdi}" (0)
   1291             \\        : "rcx", "r11", "memory"
   1292             \\    );
   1293             \\    unreachable;
   1294             \\}
   1295         ,
   1296             "",
   1297         );
   1298         case.addCompareOutput(
   1299             \\export fn _start() noreturn {
   1300             \\    var i: u64 = 0;
   1301             \\    foo: while (true) : (i+=1) {
   1302             \\        if (i == 4) exit();
   1303             \\        continue :foo;
   1304             \\    }
   1305             \\}
   1306             \\
   1307             \\fn exit() noreturn {
   1308             \\    asm volatile ("syscall"
   1309             \\        :
   1310             \\        : [number] "{rax}" (231),
   1311             \\          [arg1] "{rdi}" (0)
   1312             \\        : "rcx", "r11", "memory"
   1313             \\    );
   1314             \\    unreachable;
   1315             \\}
   1316         ,
   1317             "",
   1318         );
   1319     }
   1320 
   1321     {
   1322         var case = ctx.exe("unused labels", linux_x64);
   1323         case.addError(
   1324             \\comptime {
   1325             \\    foo: {}
   1326             \\}
   1327         , &[_][]const u8{":2:5: error: unused block label"});
   1328         case.addError(
   1329             \\comptime {
   1330             \\    foo: while (true) {}
   1331             \\}
   1332         , &[_][]const u8{":2:5: error: unused while label"});
   1333         case.addError(
   1334             \\comptime {
   1335             \\    foo: for ("foo") |_| {}
   1336             \\}
   1337         , &[_][]const u8{":2:5: error: unused for label"});
   1338     }
   1339 }