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 }