zig

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

blob 281bd0a6 (31674B) - 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 = .macosx,
     17 };
     18 
     19 const linux_riscv64 = std.zig.CrossTarget{
     20     .cpu_arch = .riscv64,
     21     .os_tag = .linux,
     22 };
     23 
     24 const linux_arm = std.zig.CrossTarget{
     25     .cpu_arch = .arm,
     26     .os_tag = .linux,
     27 };
     28 
     29 const wasi = std.zig.CrossTarget{
     30     .cpu_arch = .wasm32,
     31     .os_tag = .wasi,
     32 };
     33 
     34 pub fn addCases(ctx: *TestContext) !void {
     35     try @import("zir.zig").addCases(ctx);
     36     try @import("cbe.zig").addCases(ctx);
     37     try @import("spu-ii.zig").addCases(ctx);
     38 
     39     {
     40         var case = ctx.exe("hello world with updates", linux_x64);
     41 
     42         case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
     43 
     44         // Incorrect return type
     45         case.addError(
     46             \\export fn _start() noreturn {
     47             \\}
     48         , &[_][]const u8{":2:1: error: expected noreturn, found void"});
     49 
     50         // Regular old hello world
     51         case.addCompareOutput(
     52             \\export fn _start() noreturn {
     53             \\    print();
     54             \\
     55             \\    exit();
     56             \\}
     57             \\
     58             \\fn print() void {
     59             \\    asm volatile ("syscall"
     60             \\        :
     61             \\        : [number] "{rax}" (1),
     62             \\          [arg1] "{rdi}" (1),
     63             \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
     64             \\          [arg3] "{rdx}" (14)
     65             \\        : "rcx", "r11", "memory"
     66             \\    );
     67             \\    return;
     68             \\}
     69             \\
     70             \\fn exit() noreturn {
     71             \\    asm volatile ("syscall"
     72             \\        :
     73             \\        : [number] "{rax}" (231),
     74             \\          [arg1] "{rdi}" (0)
     75             \\        : "rcx", "r11", "memory"
     76             \\    );
     77             \\    unreachable;
     78             \\}
     79             ,
     80             "Hello, World!\n",
     81         );
     82         // Now change the message only
     83         case.addCompareOutput(
     84             \\export fn _start() noreturn {
     85             \\    print();
     86             \\
     87             \\    exit();
     88             \\}
     89             \\
     90             \\fn print() void {
     91             \\    asm volatile ("syscall"
     92             \\        :
     93             \\        : [number] "{rax}" (1),
     94             \\          [arg1] "{rdi}" (1),
     95             \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
     96             \\          [arg3] "{rdx}" (104)
     97             \\        : "rcx", "r11", "memory"
     98             \\    );
     99             \\    return;
    100             \\}
    101             \\
    102             \\fn exit() noreturn {
    103             \\    asm volatile ("syscall"
    104             \\        :
    105             \\        : [number] "{rax}" (231),
    106             \\          [arg1] "{rdi}" (0)
    107             \\        : "rcx", "r11", "memory"
    108             \\    );
    109             \\    unreachable;
    110             \\}
    111             ,
    112             "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
    113         );
    114         // Now we print it twice.
    115         case.addCompareOutput(
    116             \\export fn _start() noreturn {
    117             \\    print();
    118             \\    print();
    119             \\
    120             \\    exit();
    121             \\}
    122             \\
    123             \\fn print() void {
    124             \\    asm volatile ("syscall"
    125             \\        :
    126             \\        : [number] "{rax}" (1),
    127             \\          [arg1] "{rdi}" (1),
    128             \\          [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
    129             \\          [arg3] "{rdx}" (104)
    130             \\        : "rcx", "r11", "memory"
    131             \\    );
    132             \\    return;
    133             \\}
    134             \\
    135             \\fn exit() noreturn {
    136             \\    asm volatile ("syscall"
    137             \\        :
    138             \\        : [number] "{rax}" (231),
    139             \\          [arg1] "{rdi}" (0)
    140             \\        : "rcx", "r11", "memory"
    141             \\    );
    142             \\    unreachable;
    143             \\}
    144         ,
    145             \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
    146             \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
    147             \\
    148         );
    149     }
    150 
    151     {
    152         var case = ctx.exe("hello world", macosx_x64);
    153         case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
    154 
    155         // Incorrect return type
    156         case.addError(
    157             \\export fn _start() noreturn {
    158             \\}
    159         , &[_][]const u8{":2:1: error: expected noreturn, found void"});
    160 
    161         // Regular old hello world
    162         case.addCompareOutput(
    163             \\export fn _start() noreturn {
    164             \\    print();
    165             \\
    166             \\    exit();
    167             \\}
    168             \\
    169             \\fn print() void {
    170             \\    asm volatile ("syscall"
    171             \\        :
    172             \\        : [number] "{rax}" (0x2000004),
    173             \\          [arg1] "{rdi}" (1),
    174             \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
    175             \\          [arg3] "{rdx}" (14)
    176             \\        : "memory"
    177             \\    );
    178             \\    return;
    179             \\}
    180             \\
    181             \\fn exit() noreturn {
    182             \\    asm volatile ("syscall"
    183             \\        :
    184             \\        : [number] "{rax}" (0x2000001),
    185             \\          [arg1] "{rdi}" (0)
    186             \\        : "memory"
    187             \\    );
    188             \\    unreachable;
    189             \\}
    190             ,
    191             "Hello, World!\n",
    192         );
    193     }
    194 
    195     {
    196         var case = ctx.exe("hello world", linux_riscv64);
    197         // Regular old hello world
    198         case.addCompareOutput(
    199             \\export fn _start() noreturn {
    200             \\    print();
    201             \\
    202             \\    exit();
    203             \\}
    204             \\
    205             \\fn print() void {
    206             \\    asm volatile ("ecall"
    207             \\        :
    208             \\        : [number] "{a7}" (64),
    209             \\          [arg1] "{a0}" (1),
    210             \\          [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
    211             \\          [arg3] "{a2}" ("Hello, World!\n".len)
    212             \\        : "rcx", "r11", "memory"
    213             \\    );
    214             \\    return;
    215             \\}
    216             \\
    217             \\fn exit() noreturn {
    218             \\    asm volatile ("ecall"
    219             \\        :
    220             \\        : [number] "{a7}" (94),
    221             \\          [arg1] "{a0}" (0)
    222             \\        : "rcx", "r11", "memory"
    223             \\    );
    224             \\    unreachable;
    225             \\}
    226             ,
    227             "Hello, World!\n",
    228         );
    229     }
    230 
    231     {
    232         var case = ctx.exe("hello world", linux_arm);
    233         // Regular old hello world
    234         case.addCompareOutput(
    235             \\export fn _start() noreturn {
    236             \\    print();
    237             \\    exit();
    238             \\}
    239             \\
    240             \\fn print() void {
    241             \\    asm volatile ("svc #0"
    242             \\        :
    243             \\        : [number] "{r7}" (4),
    244             \\          [arg1] "{r0}" (1),
    245             \\          [arg2] "{r1}" (@ptrToInt("Hello, World!\n")),
    246             \\          [arg3] "{r2}" (14)
    247             \\        : "memory"
    248             \\    );
    249             \\    return;
    250             \\}
    251             \\
    252             \\fn exit() noreturn {
    253             \\    asm volatile ("svc #0"
    254             \\        :
    255             \\        : [number] "{r7}" (1),
    256             \\          [arg1] "{r0}" (0)
    257             \\        : "memory"
    258             \\    );
    259             \\    unreachable;
    260             \\}
    261             ,
    262             "Hello, World!\n",
    263         );
    264     }
    265 
    266     {
    267         var case = ctx.exe("adding numbers at comptime", linux_x64);
    268         case.addCompareOutput(
    269             \\export fn _start() noreturn {
    270             \\    asm volatile ("syscall"
    271             \\        :
    272             \\        : [number] "{rax}" (1),
    273             \\          [arg1] "{rdi}" (1),
    274             \\          [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
    275             \\          [arg3] "{rdx}" (10 + 4)
    276             \\        : "rcx", "r11", "memory"
    277             \\    );
    278             \\    asm volatile ("syscall"
    279             \\        :
    280             \\        : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)),
    281             \\          [arg1] "{rdi}" (0)
    282             \\        : "rcx", "r11", "memory"
    283             \\    );
    284             \\    unreachable;
    285             \\}
    286             ,
    287             "Hello, World!\n",
    288         );
    289     }
    290 
    291     {
    292         var case = ctx.exe("adding numbers at runtime", linux_x64);
    293         case.addCompareOutput(
    294             \\export fn _start() noreturn {
    295             \\    add(3, 4);
    296             \\
    297             \\    exit();
    298             \\}
    299             \\
    300             \\fn add(a: u32, b: u32) void {
    301             \\    if (a + b != 7) unreachable;
    302             \\}
    303             \\
    304             \\fn exit() noreturn {
    305             \\    asm volatile ("syscall"
    306             \\        :
    307             \\        : [number] "{rax}" (231),
    308             \\          [arg1] "{rdi}" (0)
    309             \\        : "rcx", "r11", "memory"
    310             \\    );
    311             \\    unreachable;
    312             \\}
    313             ,
    314             "",
    315         );
    316     }
    317 
    318     {
    319         var case = ctx.exe("subtracting numbers at runtime", linux_x64);
    320         case.addCompareOutput(
    321             \\export fn _start() noreturn {
    322             \\    sub(7, 4);
    323             \\
    324             \\    exit();
    325             \\}
    326             \\
    327             \\fn sub(a: u32, b: u32) void {
    328             \\    if (a - b != 3) unreachable;
    329             \\}
    330             \\
    331             \\fn exit() noreturn {
    332             \\    asm volatile ("syscall"
    333             \\        :
    334             \\        : [number] "{rax}" (231),
    335             \\          [arg1] "{rdi}" (0)
    336             \\        : "rcx", "r11", "memory"
    337             \\    );
    338             \\    unreachable;
    339             \\}
    340             ,
    341             "",
    342         );
    343     }
    344 
    345     {
    346         var case = ctx.exe("assert function", linux_x64);
    347         case.addCompareOutput(
    348             \\export fn _start() noreturn {
    349             \\    add(3, 4);
    350             \\
    351             \\    exit();
    352             \\}
    353             \\
    354             \\fn add(a: u32, b: u32) void {
    355             \\    assert(a + b == 7);
    356             \\}
    357             \\
    358             \\pub fn assert(ok: bool) void {
    359             \\    if (!ok) unreachable; // assertion failure
    360             \\}
    361             \\
    362             \\fn exit() noreturn {
    363             \\    asm volatile ("syscall"
    364             \\        :
    365             \\        : [number] "{rax}" (231),
    366             \\          [arg1] "{rdi}" (0)
    367             \\        : "rcx", "r11", "memory"
    368             \\    );
    369             \\    unreachable;
    370             \\}
    371             ,
    372             "",
    373         );
    374 
    375         // Tests copying a register. For the `c = a + b`, it has to
    376         // preserve both a and b, because they are both used later.
    377         case.addCompareOutput(
    378             \\export fn _start() noreturn {
    379             \\    add(3, 4);
    380             \\
    381             \\    exit();
    382             \\}
    383             \\
    384             \\fn add(a: u32, b: u32) void {
    385             \\    const c = a + b; // 7
    386             \\    const d = a + c; // 10
    387             \\    const e = d + b; // 14
    388             \\    assert(e == 14);
    389             \\}
    390             \\
    391             \\pub fn assert(ok: bool) void {
    392             \\    if (!ok) unreachable; // assertion failure
    393             \\}
    394             \\
    395             \\fn exit() noreturn {
    396             \\    asm volatile ("syscall"
    397             \\        :
    398             \\        : [number] "{rax}" (231),
    399             \\          [arg1] "{rdi}" (0)
    400             \\        : "rcx", "r11", "memory"
    401             \\    );
    402             \\    unreachable;
    403             \\}
    404             ,
    405             "",
    406         );
    407 
    408         // More stress on the liveness detection.
    409         case.addCompareOutput(
    410             \\export fn _start() noreturn {
    411             \\    add(3, 4);
    412             \\
    413             \\    exit();
    414             \\}
    415             \\
    416             \\fn add(a: u32, b: u32) void {
    417             \\    const c = a + b; // 7
    418             \\    const d = a + c; // 10
    419             \\    const e = d + b; // 14
    420             \\    const f = d + e; // 24
    421             \\    const g = e + f; // 38
    422             \\    const h = f + g; // 62
    423             \\    const i = g + h; // 100
    424             \\    assert(i == 100);
    425             \\}
    426             \\
    427             \\pub fn assert(ok: bool) void {
    428             \\    if (!ok) unreachable; // assertion failure
    429             \\}
    430             \\
    431             \\fn exit() noreturn {
    432             \\    asm volatile ("syscall"
    433             \\        :
    434             \\        : [number] "{rax}" (231),
    435             \\          [arg1] "{rdi}" (0)
    436             \\        : "rcx", "r11", "memory"
    437             \\    );
    438             \\    unreachable;
    439             \\}
    440             ,
    441             "",
    442         );
    443 
    444         // Requires a second move. The register allocator should figure out to re-use rax.
    445         case.addCompareOutput(
    446             \\export fn _start() noreturn {
    447             \\    add(3, 4);
    448             \\
    449             \\    exit();
    450             \\}
    451             \\
    452             \\fn add(a: u32, b: u32) void {
    453             \\    const c = a + b; // 7
    454             \\    const d = a + c; // 10
    455             \\    const e = d + b; // 14
    456             \\    const f = d + e; // 24
    457             \\    const g = e + f; // 38
    458             \\    const h = f + g; // 62
    459             \\    const i = g + h; // 100
    460             \\    const j = i + d; // 110
    461             \\    assert(j == 110);
    462             \\}
    463             \\
    464             \\pub fn assert(ok: bool) void {
    465             \\    if (!ok) unreachable; // assertion failure
    466             \\}
    467             \\
    468             \\fn exit() noreturn {
    469             \\    asm volatile ("syscall"
    470             \\        :
    471             \\        : [number] "{rax}" (231),
    472             \\          [arg1] "{rdi}" (0)
    473             \\        : "rcx", "r11", "memory"
    474             \\    );
    475             \\    unreachable;
    476             \\}
    477             ,
    478             "",
    479         );
    480 
    481         // Now we test integer return values.
    482         case.addCompareOutput(
    483             \\export fn _start() noreturn {
    484             \\    assert(add(3, 4) == 7);
    485             \\    assert(add(20, 10) == 30);
    486             \\
    487             \\    exit();
    488             \\}
    489             \\
    490             \\fn add(a: u32, b: u32) u32 {
    491             \\    return a + b;
    492             \\}
    493             \\
    494             \\pub fn assert(ok: bool) void {
    495             \\    if (!ok) unreachable; // assertion failure
    496             \\}
    497             \\
    498             \\fn exit() noreturn {
    499             \\    asm volatile ("syscall"
    500             \\        :
    501             \\        : [number] "{rax}" (231),
    502             \\          [arg1] "{rdi}" (0)
    503             \\        : "rcx", "r11", "memory"
    504             \\    );
    505             \\    unreachable;
    506             \\}
    507             ,
    508             "",
    509         );
    510 
    511         // Local mutable variables.
    512         case.addCompareOutput(
    513             \\export fn _start() noreturn {
    514             \\    assert(add(3, 4) == 7);
    515             \\    assert(add(20, 10) == 30);
    516             \\
    517             \\    exit();
    518             \\}
    519             \\
    520             \\fn add(a: u32, b: u32) u32 {
    521             \\    var x: u32 = undefined;
    522             \\    x = 0;
    523             \\    x += a;
    524             \\    x += b;
    525             \\    return x;
    526             \\}
    527             \\
    528             \\pub fn assert(ok: bool) void {
    529             \\    if (!ok) unreachable; // assertion failure
    530             \\}
    531             \\
    532             \\fn exit() noreturn {
    533             \\    asm volatile ("syscall"
    534             \\        :
    535             \\        : [number] "{rax}" (231),
    536             \\          [arg1] "{rdi}" (0)
    537             \\        : "rcx", "r11", "memory"
    538             \\    );
    539             \\    unreachable;
    540             \\}
    541             ,
    542             "",
    543         );
    544 
    545         // Optionals
    546         case.addCompareOutput(
    547             \\export fn _start() noreturn {
    548             \\    const a: u32 = 2;
    549             \\    const b: ?u32 = a;
    550             \\    const c = b.?;
    551             \\    if (c != 2) unreachable;
    552             \\
    553             \\    exit();
    554             \\}
    555             \\
    556             \\fn exit() noreturn {
    557             \\    asm volatile ("syscall"
    558             \\        :
    559             \\        : [number] "{rax}" (231),
    560             \\          [arg1] "{rdi}" (0)
    561             \\        : "rcx", "r11", "memory"
    562             \\    );
    563             \\    unreachable;
    564             \\}
    565             ,
    566             "",
    567         );
    568 
    569         // While loops
    570         case.addCompareOutput(
    571             \\export fn _start() noreturn {
    572             \\    var i: u32 = 0;
    573             \\    while (i < 4) : (i += 1) print();
    574             \\    assert(i == 4);
    575             \\
    576             \\    exit();
    577             \\}
    578             \\
    579             \\fn print() void {
    580             \\    asm volatile ("syscall"
    581             \\        :
    582             \\        : [number] "{rax}" (1),
    583             \\          [arg1] "{rdi}" (1),
    584             \\          [arg2] "{rsi}" (@ptrToInt("hello\n")),
    585             \\          [arg3] "{rdx}" (6)
    586             \\        : "rcx", "r11", "memory"
    587             \\    );
    588             \\    return;
    589             \\}
    590             \\
    591             \\pub fn assert(ok: bool) void {
    592             \\    if (!ok) unreachable; // assertion failure
    593             \\}
    594             \\
    595             \\fn exit() noreturn {
    596             \\    asm volatile ("syscall"
    597             \\        :
    598             \\        : [number] "{rax}" (231),
    599             \\          [arg1] "{rdi}" (0)
    600             \\        : "rcx", "r11", "memory"
    601             \\    );
    602             \\    unreachable;
    603             \\}
    604             ,
    605             "hello\nhello\nhello\nhello\n",
    606         );
    607 
    608         // Labeled blocks (no conditional branch)
    609         case.addCompareOutput(
    610             \\export fn _start() noreturn {
    611             \\    assert(add(3, 4) == 20);
    612             \\
    613             \\    exit();
    614             \\}
    615             \\
    616             \\fn add(a: u32, b: u32) u32 {
    617             \\    const x: u32 = blk: {
    618             \\        const c = a + b; // 7
    619             \\        const d = a + c; // 10
    620             \\        const e = d + b; // 14
    621             \\        break :blk e;
    622             \\    };
    623             \\    const y = x + a; // 17
    624             \\    const z = y + a; // 20
    625             \\    return z;
    626             \\}
    627             \\
    628             \\pub fn assert(ok: bool) void {
    629             \\    if (!ok) unreachable; // assertion failure
    630             \\}
    631             \\
    632             \\fn exit() noreturn {
    633             \\    asm volatile ("syscall"
    634             \\        :
    635             \\        : [number] "{rax}" (231),
    636             \\          [arg1] "{rdi}" (0)
    637             \\        : "rcx", "r11", "memory"
    638             \\    );
    639             \\    unreachable;
    640             \\}
    641             ,
    642             "",
    643         );
    644 
    645         // This catches a possible bug in the logic for re-using dying operands.
    646         case.addCompareOutput(
    647             \\export fn _start() noreturn {
    648             \\    assert(add(3, 4) == 116);
    649             \\
    650             \\    exit();
    651             \\}
    652             \\
    653             \\fn add(a: u32, b: u32) u32 {
    654             \\    const x: u32 = blk: {
    655             \\        const c = a + b; // 7
    656             \\        const d = a + c; // 10
    657             \\        const e = d + b; // 14
    658             \\        const f = d + e; // 24
    659             \\        const g = e + f; // 38
    660             \\        const h = f + g; // 62
    661             \\        const i = g + h; // 100
    662             \\        const j = i + d; // 110
    663             \\        break :blk j;
    664             \\    };
    665             \\    const y = x + a; // 113
    666             \\    const z = y + a; // 116
    667             \\    return z;
    668             \\}
    669             \\
    670             \\pub fn assert(ok: bool) void {
    671             \\    if (!ok) unreachable; // assertion failure
    672             \\}
    673             \\
    674             \\fn exit() noreturn {
    675             \\    asm volatile ("syscall"
    676             \\        :
    677             \\        : [number] "{rax}" (231),
    678             \\          [arg1] "{rdi}" (0)
    679             \\        : "rcx", "r11", "memory"
    680             \\    );
    681             \\    unreachable;
    682             \\}
    683             ,
    684             "",
    685         );
    686 
    687         // Spilling registers to the stack.
    688         case.addCompareOutput(
    689             \\export fn _start() noreturn {
    690             \\    assert(add(3, 4) == 791);
    691             \\
    692             \\    exit();
    693             \\}
    694             \\
    695             \\fn add(a: u32, b: u32) u32 {
    696             \\    const x: u32 = blk: {
    697             \\        const c = a + b; // 7
    698             \\        const d = a + c; // 10
    699             \\        const e = d + b; // 14
    700             \\        const f = d + e; // 24
    701             \\        const g = e + f; // 38
    702             \\        const h = f + g; // 62
    703             \\        const i = g + h; // 100
    704             \\        const j = i + d; // 110
    705             \\        const k = i + j; // 210
    706             \\        const l = k + c; // 217
    707             \\        const m = l + d; // 227
    708             \\        const n = m + e; // 241
    709             \\        const o = n + f; // 265
    710             \\        const p = o + g; // 303
    711             \\        const q = p + h; // 365
    712             \\        const r = q + i; // 465
    713             \\        const s = r + j; // 575
    714             \\        const t = s + k; // 785
    715             \\        break :blk t;
    716             \\    };
    717             \\    const y = x + a; // 788
    718             \\    const z = y + a; // 791
    719             \\    return z;
    720             \\}
    721             \\
    722             \\pub fn assert(ok: bool) void {
    723             \\    if (!ok) unreachable; // assertion failure
    724             \\}
    725             \\
    726             \\fn exit() noreturn {
    727             \\    asm volatile ("syscall"
    728             \\        :
    729             \\        : [number] "{rax}" (231),
    730             \\          [arg1] "{rdi}" (0)
    731             \\        : "rcx", "r11", "memory"
    732             \\    );
    733             \\    unreachable;
    734             \\}
    735             ,
    736             "",
    737         );
    738 
    739         // Reusing the registers of dead operands playing nicely with conditional branching.
    740         case.addCompareOutput(
    741             \\export fn _start() noreturn {
    742             \\    assert(add(3, 4) == 791);
    743             \\    assert(add(4, 3) == 79);
    744             \\
    745             \\    exit();
    746             \\}
    747             \\
    748             \\fn add(a: u32, b: u32) u32 {
    749             \\    const x: u32 = if (a < b) blk: {
    750             \\        const c = a + b; // 7
    751             \\        const d = a + c; // 10
    752             \\        const e = d + b; // 14
    753             \\        const f = d + e; // 24
    754             \\        const g = e + f; // 38
    755             \\        const h = f + g; // 62
    756             \\        const i = g + h; // 100
    757             \\        const j = i + d; // 110
    758             \\        const k = i + j; // 210
    759             \\        const l = k + c; // 217
    760             \\        const m = l + d; // 227
    761             \\        const n = m + e; // 241
    762             \\        const o = n + f; // 265
    763             \\        const p = o + g; // 303
    764             \\        const q = p + h; // 365
    765             \\        const r = q + i; // 465
    766             \\        const s = r + j; // 575
    767             \\        const t = s + k; // 785
    768             \\        break :blk t;
    769             \\    } else blk: {
    770             \\        const t = b + b + a; // 10
    771             \\        const c = a + t; // 14
    772             \\        const d = c + t; // 24
    773             \\        const e = d + t; // 34
    774             \\        const f = e + t; // 44
    775             \\        const g = f + t; // 54
    776             \\        const h = c + g; // 68
    777             \\        break :blk h + b; // 71
    778             \\    };
    779             \\    const y = x + a; // 788, 75
    780             \\    const z = y + a; // 791, 79
    781             \\    return z;
    782             \\}
    783             \\
    784             \\pub fn assert(ok: bool) void {
    785             \\    if (!ok) unreachable; // assertion failure
    786             \\}
    787             \\
    788             \\fn exit() noreturn {
    789             \\    asm volatile ("syscall"
    790             \\        :
    791             \\        : [number] "{rax}" (231),
    792             \\          [arg1] "{rdi}" (0)
    793             \\        : "rcx", "r11", "memory"
    794             \\    );
    795             \\    unreachable;
    796             \\}
    797             ,
    798             "",
    799         );
    800 
    801         // Character literals and multiline strings.
    802         case.addCompareOutput(
    803             \\export fn _start() noreturn {
    804             \\    const ignore = 
    805             \\        \\ cool thx
    806             \\        \\
    807             \\    ;
    808             \\    add('ぁ', '\x03');
    809             \\
    810             \\    exit();
    811             \\}
    812             \\
    813             \\fn add(a: u32, b: u32) void {
    814             \\    assert(a + b == 12356);
    815             \\}
    816             \\
    817             \\pub fn assert(ok: bool) void {
    818             \\    if (!ok) unreachable; // assertion failure
    819             \\}
    820             \\
    821             \\fn exit() noreturn {
    822             \\    asm volatile ("syscall"
    823             \\        :
    824             \\        : [number] "{rax}" (231),
    825             \\          [arg1] "{rdi}" (0)
    826             \\        : "rcx", "r11", "memory"
    827             \\    );
    828             \\    unreachable;
    829             \\}
    830             ,
    831             "",
    832         );
    833 
    834         // Global const.
    835         case.addCompareOutput(
    836             \\export fn _start() noreturn {
    837             \\    add(aa, bb);
    838             \\
    839             \\    exit();
    840             \\}
    841             \\
    842             \\const aa = 'ぁ';
    843             \\const bb = '\x03';
    844             \\
    845             \\fn add(a: u32, b: u32) void {
    846             \\    assert(a + b == 12356);
    847             \\}
    848             \\
    849             \\pub fn assert(ok: bool) void {
    850             \\    if (!ok) unreachable; // assertion failure
    851             \\}
    852             \\
    853             \\fn exit() noreturn {
    854             \\    asm volatile ("syscall"
    855             \\        :
    856             \\        : [number] "{rax}" (231),
    857             \\          [arg1] "{rdi}" (0)
    858             \\        : "rcx", "r11", "memory"
    859             \\    );
    860             \\    unreachable;
    861             \\}
    862             ,
    863             "",
    864         );
    865 
    866         // Array access.
    867         case.addCompareOutput(
    868             \\export fn _start() noreturn {
    869             \\    assert("hello"[0] == 'h');
    870             \\
    871             \\    exit();
    872             \\}
    873             \\
    874             \\pub fn assert(ok: bool) void {
    875             \\    if (!ok) unreachable; // assertion failure
    876             \\}
    877             \\
    878             \\fn exit() noreturn {
    879             \\    asm volatile ("syscall"
    880             \\        :
    881             \\        : [number] "{rax}" (231),
    882             \\          [arg1] "{rdi}" (0)
    883             \\        : "rcx", "r11", "memory"
    884             \\    );
    885             \\    unreachable;
    886             \\}
    887             ,
    888             "",
    889         );
    890 
    891         // 64bit set stack
    892         case.addCompareOutput(
    893             \\export fn _start() noreturn {
    894             \\    var i: u64 = 0xFFEEDDCCBBAA9988;
    895             \\    assert(i == 0xFFEEDDCCBBAA9988);
    896             \\
    897             \\    exit();
    898             \\}
    899             \\
    900             \\pub fn assert(ok: bool) void {
    901             \\    if (!ok) unreachable; // assertion failure
    902             \\}
    903             \\
    904             \\fn exit() noreturn {
    905             \\    asm volatile ("syscall"
    906             \\        :
    907             \\        : [number] "{rax}" (231),
    908             \\          [arg1] "{rdi}" (0)
    909             \\        : "rcx", "r11", "memory"
    910             \\    );
    911             \\    unreachable;
    912             \\}
    913             ,
    914             "",
    915         );
    916 
    917         // Basic for loop
    918         case.addCompareOutput(
    919             \\export fn _start() noreturn {
    920             \\    for ("hello") |_| print();
    921             \\
    922             \\    exit();
    923             \\}
    924             \\
    925             \\fn print() void {
    926             \\    asm volatile ("syscall"
    927             \\        :
    928             \\        : [number] "{rax}" (1),
    929             \\          [arg1] "{rdi}" (1),
    930             \\          [arg2] "{rsi}" (@ptrToInt("hello\n")),
    931             \\          [arg3] "{rdx}" (6)
    932             \\        : "rcx", "r11", "memory"
    933             \\    );
    934             \\    return;
    935             \\}
    936             \\
    937             \\fn exit() noreturn {
    938             \\    asm volatile ("syscall"
    939             \\        :
    940             \\        : [number] "{rax}" (231),
    941             \\          [arg1] "{rdi}" (0)
    942             \\        : "rcx", "r11", "memory"
    943             \\    );
    944             \\    unreachable;
    945             \\}
    946             ,
    947             "hello\nhello\nhello\nhello\nhello\n",
    948         );
    949     }
    950 
    951     {
    952         var case = ctx.exe("wasm function calls", wasi);
    953 
    954         case.addCompareOutput(
    955             \\export fn _start() u32 {
    956             \\    foo();
    957             \\    bar();
    958             \\    return 42;
    959             \\}
    960             \\fn foo() void {
    961             \\    bar();
    962             \\    bar();
    963             \\}
    964             \\fn bar() void {}
    965             ,
    966             "42\n",
    967         );
    968 
    969         case.addCompareOutput(
    970             \\export fn _start() i64 {
    971             \\    bar();
    972             \\    foo();
    973             \\    foo();
    974             \\    bar();
    975             \\    foo();
    976             \\    bar();
    977             \\    return 42;
    978             \\}
    979             \\fn foo() void {
    980             \\    bar();
    981             \\}
    982             \\fn bar() void {}
    983             ,
    984             "42\n",
    985         );
    986 
    987         case.addCompareOutput(
    988             \\export fn _start() f32 {
    989             \\    bar();
    990             \\    foo();
    991             \\    return 42.0;
    992             \\}
    993             \\fn foo() void {
    994             \\    bar();
    995             \\    bar();
    996             \\    bar();
    997             \\}
    998             \\fn bar() void {}
    999             ,
   1000             // This is what you get when you take the bits of the IEE-754
   1001             // representation of 42.0 and reinterpret them as an unsigned
   1002             // integer. Guess that's a bug in wasmtime.
   1003             "1109917696\n",
   1004         );
   1005     }
   1006 
   1007     ctx.compileError("function redefinition", linux_x64,
   1008         \\fn entry() void {}
   1009         \\fn entry() void {}
   1010     , &[_][]const u8{":2:4: error: redefinition of 'entry'"});
   1011 
   1012     {
   1013         var case = ctx.obj("extern variable has no type", linux_x64);
   1014         case.addError(
   1015             \\comptime {
   1016             \\    _ = foo;
   1017             \\}
   1018             \\extern var foo: i32;
   1019         , &[_][]const u8{":2:9: error: unable to resolve comptime value"});
   1020         case.addError(
   1021             \\export fn entry() void {
   1022             \\    _ = foo;
   1023             \\}
   1024             \\extern var foo;
   1025         , &[_][]const u8{":4:1: error: unable to infer variable type"});
   1026     }
   1027 }