authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-20 17:25:09-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-20 17:25:09-07:00
log73d16d015e09c05aecba8a58881cbc429e8126fa
treec12be20be24223f37ab9a3c6cfdb9db8e7d263b4
parent56ea04cb6d1b2b87e2a2dbde6de8279e035bec73

stage2: reorganize tests

The main test cases are now in `test/stage2/test.zig` which can then call addCases on other files if it wants to organize things differently.

2 files changed, 720 insertions(+), 724 deletions(-)

test/stage2/compare_output.zig deleted-723
...@@ -1,723 +0,0 @@
1const std = @import("std");
2const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
3// self-hosted does not yet support PE executable files / COFF object files
4// or mach-o files. So we do these test cases cross compiling for x86_64-linux.
5const linux_x64 = std.zig.CrossTarget{
6 .cpu_arch = .x86_64,
7 .os_tag = .linux,
8};
9
10const linux_riscv64 = std.zig.CrossTarget{
11 .cpu_arch = .riscv64,
12 .os_tag = .linux,
13};
14
15const wasi = std.zig.CrossTarget{
16 .cpu_arch = .wasm32,
17 .os_tag = .wasi,
18};
19
20pub fn addCases(ctx: *TestContext) !void {
21 {
22 var case = ctx.exe("hello world with updates", linux_x64);
23
24 case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
25
26 // Incorrect return type
27 case.addError(
28 \\export fn _start() noreturn {
29 \\}
30 , &[_][]const u8{":2:1: error: expected noreturn, found void"});
31
32 // Regular old hello world
33 case.addCompareOutput(
34 \\export fn _start() noreturn {
35 \\ print();
36 \\
37 \\ exit();
38 \\}
39 \\
40 \\fn print() void {
41 \\ asm volatile ("syscall"
42 \\ :
43 \\ : [number] "{rax}" (1),
44 \\ [arg1] "{rdi}" (1),
45 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
46 \\ [arg3] "{rdx}" (14)
47 \\ : "rcx", "r11", "memory"
48 \\ );
49 \\ return;
50 \\}
51 \\
52 \\fn exit() noreturn {
53 \\ asm volatile ("syscall"
54 \\ :
55 \\ : [number] "{rax}" (231),
56 \\ [arg1] "{rdi}" (0)
57 \\ : "rcx", "r11", "memory"
58 \\ );
59 \\ unreachable;
60 \\}
61 ,
62 "Hello, World!\n",
63 );
64 // Now change the message only
65 case.addCompareOutput(
66 \\export fn _start() noreturn {
67 \\ print();
68 \\
69 \\ exit();
70 \\}
71 \\
72 \\fn print() void {
73 \\ asm volatile ("syscall"
74 \\ :
75 \\ : [number] "{rax}" (1),
76 \\ [arg1] "{rdi}" (1),
77 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
78 \\ [arg3] "{rdx}" (104)
79 \\ : "rcx", "r11", "memory"
80 \\ );
81 \\ return;
82 \\}
83 \\
84 \\fn exit() noreturn {
85 \\ asm volatile ("syscall"
86 \\ :
87 \\ : [number] "{rax}" (231),
88 \\ [arg1] "{rdi}" (0)
89 \\ : "rcx", "r11", "memory"
90 \\ );
91 \\ unreachable;
92 \\}
93 ,
94 "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
95 );
96 // Now we print it twice.
97 case.addCompareOutput(
98 \\export fn _start() noreturn {
99 \\ print();
100 \\ print();
101 \\
102 \\ exit();
103 \\}
104 \\
105 \\fn print() void {
106 \\ asm volatile ("syscall"
107 \\ :
108 \\ : [number] "{rax}" (1),
109 \\ [arg1] "{rdi}" (1),
110 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
111 \\ [arg3] "{rdx}" (104)
112 \\ : "rcx", "r11", "memory"
113 \\ );
114 \\ return;
115 \\}
116 \\
117 \\fn exit() noreturn {
118 \\ asm volatile ("syscall"
119 \\ :
120 \\ : [number] "{rax}" (231),
121 \\ [arg1] "{rdi}" (0)
122 \\ : "rcx", "r11", "memory"
123 \\ );
124 \\ unreachable;
125 \\}
126 ,
127 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
128 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
129 \\
130 );
131 }
132
133 {
134 var case = ctx.exe("hello world", linux_riscv64);
135 // Regular old hello world
136 case.addCompareOutput(
137 \\export fn _start() noreturn {
138 \\ print();
139 \\
140 \\ exit();
141 \\}
142 \\
143 \\fn print() void {
144 \\ asm volatile ("ecall"
145 \\ :
146 \\ : [number] "{a7}" (64),
147 \\ [arg1] "{a0}" (1),
148 \\ [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
149 \\ [arg3] "{a2}" ("Hello, World!\n".len)
150 \\ : "rcx", "r11", "memory"
151 \\ );
152 \\ return;
153 \\}
154 \\
155 \\fn exit() noreturn {
156 \\ asm volatile ("ecall"
157 \\ :
158 \\ : [number] "{a7}" (94),
159 \\ [arg1] "{a0}" (0)
160 \\ : "rcx", "r11", "memory"
161 \\ );
162 \\ unreachable;
163 \\}
164 ,
165 "Hello, World!\n",
166 );
167 }
168
169 {
170 var case = ctx.exe("adding numbers at comptime", linux_x64);
171 case.addCompareOutput(
172 \\export fn _start() noreturn {
173 \\ asm volatile ("syscall"
174 \\ :
175 \\ : [number] "{rax}" (1),
176 \\ [arg1] "{rdi}" (1),
177 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
178 \\ [arg3] "{rdx}" (10 + 4)
179 \\ : "rcx", "r11", "memory"
180 \\ );
181 \\ asm volatile ("syscall"
182 \\ :
183 \\ : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)),
184 \\ [arg1] "{rdi}" (0)
185 \\ : "rcx", "r11", "memory"
186 \\ );
187 \\ unreachable;
188 \\}
189 ,
190 "Hello, World!\n",
191 );
192 }
193
194 {
195 var case = ctx.exe("adding numbers at runtime", linux_x64);
196 case.addCompareOutput(
197 \\export fn _start() noreturn {
198 \\ add(3, 4);
199 \\
200 \\ exit();
201 \\}
202 \\
203 \\fn add(a: u32, b: u32) void {
204 \\ if (a + b != 7) unreachable;
205 \\}
206 \\
207 \\fn exit() noreturn {
208 \\ asm volatile ("syscall"
209 \\ :
210 \\ : [number] "{rax}" (231),
211 \\ [arg1] "{rdi}" (0)
212 \\ : "rcx", "r11", "memory"
213 \\ );
214 \\ unreachable;
215 \\}
216 ,
217 "",
218 );
219 }
220
221 {
222 var case = ctx.exe("substracting numbers at runtime", linux_x64);
223 case.addCompareOutput(
224 \\export fn _start() noreturn {
225 \\ sub(7, 4);
226 \\
227 \\ exit();
228 \\}
229 \\
230 \\fn sub(a: u32, b: u32) void {
231 \\ if (a - b != 3) unreachable;
232 \\}
233 \\
234 \\fn exit() noreturn {
235 \\ asm volatile ("syscall"
236 \\ :
237 \\ : [number] "{rax}" (231),
238 \\ [arg1] "{rdi}" (0)
239 \\ : "rcx", "r11", "memory"
240 \\ );
241 \\ unreachable;
242 \\}
243 ,
244 "",
245 );
246 }
247
248 {
249 var case = ctx.exe("assert function", linux_x64);
250 case.addCompareOutput(
251 \\export fn _start() noreturn {
252 \\ add(3, 4);
253 \\
254 \\ exit();
255 \\}
256 \\
257 \\fn add(a: u32, b: u32) void {
258 \\ assert(a + b == 7);
259 \\}
260 \\
261 \\pub fn assert(ok: bool) void {
262 \\ if (!ok) unreachable; // assertion failure
263 \\}
264 \\
265 \\fn exit() noreturn {
266 \\ asm volatile ("syscall"
267 \\ :
268 \\ : [number] "{rax}" (231),
269 \\ [arg1] "{rdi}" (0)
270 \\ : "rcx", "r11", "memory"
271 \\ );
272 \\ unreachable;
273 \\}
274 ,
275 "",
276 );
277
278 // Tests copying a register. For the `c = a + b`, it has to
279 // preserve both a and b, because they are both used later.
280 case.addCompareOutput(
281 \\export fn _start() noreturn {
282 \\ add(3, 4);
283 \\
284 \\ exit();
285 \\}
286 \\
287 \\fn add(a: u32, b: u32) void {
288 \\ const c = a + b; // 7
289 \\ const d = a + c; // 10
290 \\ const e = d + b; // 14
291 \\ assert(e == 14);
292 \\}
293 \\
294 \\pub fn assert(ok: bool) void {
295 \\ if (!ok) unreachable; // assertion failure
296 \\}
297 \\
298 \\fn exit() noreturn {
299 \\ asm volatile ("syscall"
300 \\ :
301 \\ : [number] "{rax}" (231),
302 \\ [arg1] "{rdi}" (0)
303 \\ : "rcx", "r11", "memory"
304 \\ );
305 \\ unreachable;
306 \\}
307 ,
308 "",
309 );
310
311 // More stress on the liveness detection.
312 case.addCompareOutput(
313 \\export fn _start() noreturn {
314 \\ add(3, 4);
315 \\
316 \\ exit();
317 \\}
318 \\
319 \\fn add(a: u32, b: u32) void {
320 \\ const c = a + b; // 7
321 \\ const d = a + c; // 10
322 \\ const e = d + b; // 14
323 \\ const f = d + e; // 24
324 \\ const g = e + f; // 38
325 \\ const h = f + g; // 62
326 \\ const i = g + h; // 100
327 \\ assert(i == 100);
328 \\}
329 \\
330 \\pub fn assert(ok: bool) void {
331 \\ if (!ok) unreachable; // assertion failure
332 \\}
333 \\
334 \\fn exit() noreturn {
335 \\ asm volatile ("syscall"
336 \\ :
337 \\ : [number] "{rax}" (231),
338 \\ [arg1] "{rdi}" (0)
339 \\ : "rcx", "r11", "memory"
340 \\ );
341 \\ unreachable;
342 \\}
343 ,
344 "",
345 );
346
347 // Requires a second move. The register allocator should figure out to re-use rax.
348 case.addCompareOutput(
349 \\export fn _start() noreturn {
350 \\ add(3, 4);
351 \\
352 \\ exit();
353 \\}
354 \\
355 \\fn add(a: u32, b: u32) void {
356 \\ const c = a + b; // 7
357 \\ const d = a + c; // 10
358 \\ const e = d + b; // 14
359 \\ const f = d + e; // 24
360 \\ const g = e + f; // 38
361 \\ const h = f + g; // 62
362 \\ const i = g + h; // 100
363 \\ const j = i + d; // 110
364 \\ assert(j == 110);
365 \\}
366 \\
367 \\pub fn assert(ok: bool) void {
368 \\ if (!ok) unreachable; // assertion failure
369 \\}
370 \\
371 \\fn exit() noreturn {
372 \\ asm volatile ("syscall"
373 \\ :
374 \\ : [number] "{rax}" (231),
375 \\ [arg1] "{rdi}" (0)
376 \\ : "rcx", "r11", "memory"
377 \\ );
378 \\ unreachable;
379 \\}
380 ,
381 "",
382 );
383
384 // Now we test integer return values.
385 case.addCompareOutput(
386 \\export fn _start() noreturn {
387 \\ assert(add(3, 4) == 7);
388 \\ assert(add(20, 10) == 30);
389 \\
390 \\ exit();
391 \\}
392 \\
393 \\fn add(a: u32, b: u32) u32 {
394 \\ return a + b;
395 \\}
396 \\
397 \\pub fn assert(ok: bool) void {
398 \\ if (!ok) unreachable; // assertion failure
399 \\}
400 \\
401 \\fn exit() noreturn {
402 \\ asm volatile ("syscall"
403 \\ :
404 \\ : [number] "{rax}" (231),
405 \\ [arg1] "{rdi}" (0)
406 \\ : "rcx", "r11", "memory"
407 \\ );
408 \\ unreachable;
409 \\}
410 ,
411 "",
412 );
413
414 // Local mutable variables.
415 case.addCompareOutput(
416 \\export fn _start() noreturn {
417 \\ assert(add(3, 4) == 7);
418 \\ assert(add(20, 10) == 30);
419 \\
420 \\ exit();
421 \\}
422 \\
423 \\fn add(a: u32, b: u32) u32 {
424 \\ var x: u32 = undefined;
425 \\ x = 0;
426 \\ x += a;
427 \\ x += b;
428 \\ return x;
429 \\}
430 \\
431 \\pub fn assert(ok: bool) void {
432 \\ if (!ok) unreachable; // assertion failure
433 \\}
434 \\
435 \\fn exit() noreturn {
436 \\ asm volatile ("syscall"
437 \\ :
438 \\ : [number] "{rax}" (231),
439 \\ [arg1] "{rdi}" (0)
440 \\ : "rcx", "r11", "memory"
441 \\ );
442 \\ unreachable;
443 \\}
444 ,
445 "",
446 );
447
448 // Optionals
449 case.addCompareOutput(
450 \\export fn _start() noreturn {
451 \\ const a: u32 = 2;
452 \\ const b: ?u32 = a;
453 \\ const c = b.?;
454 \\ if (c != 2) unreachable;
455 \\
456 \\ exit();
457 \\}
458 \\
459 \\fn exit() noreturn {
460 \\ asm volatile ("syscall"
461 \\ :
462 \\ : [number] "{rax}" (231),
463 \\ [arg1] "{rdi}" (0)
464 \\ : "rcx", "r11", "memory"
465 \\ );
466 \\ unreachable;
467 \\}
468 ,
469 "",
470 );
471
472 // While loops
473 case.addCompareOutput(
474 \\export fn _start() noreturn {
475 \\ var i: u32 = 0;
476 \\ while (i < 4) : (i += 1) print();
477 \\ assert(i == 4);
478 \\
479 \\ exit();
480 \\}
481 \\
482 \\fn print() void {
483 \\ asm volatile ("syscall"
484 \\ :
485 \\ : [number] "{rax}" (1),
486 \\ [arg1] "{rdi}" (1),
487 \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
488 \\ [arg3] "{rdx}" (6)
489 \\ : "rcx", "r11", "memory"
490 \\ );
491 \\ return;
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 "hello\nhello\nhello\nhello\n",
509 );
510
511 // Labeled blocks (no conditional branch)
512 case.addCompareOutput(
513 \\export fn _start() noreturn {
514 \\ assert(add(3, 4) == 20);
515 \\
516 \\ exit();
517 \\}
518 \\
519 \\fn add(a: u32, b: u32) u32 {
520 \\ const x: u32 = blk: {
521 \\ const c = a + b; // 7
522 \\ const d = a + c; // 10
523 \\ const e = d + b; // 14
524 \\ break :blk e;
525 \\ };
526 \\ const y = x + a; // 17
527 \\ const z = y + a; // 20
528 \\ return z;
529 \\}
530 \\
531 \\pub fn assert(ok: bool) void {
532 \\ if (!ok) unreachable; // assertion failure
533 \\}
534 \\
535 \\fn exit() noreturn {
536 \\ asm volatile ("syscall"
537 \\ :
538 \\ : [number] "{rax}" (231),
539 \\ [arg1] "{rdi}" (0)
540 \\ : "rcx", "r11", "memory"
541 \\ );
542 \\ unreachable;
543 \\}
544 ,
545 "",
546 );
547
548 // This catches a possible bug in the logic for re-using dying operands.
549 case.addCompareOutput(
550 \\export fn _start() noreturn {
551 \\ assert(add(3, 4) == 116);
552 \\
553 \\ exit();
554 \\}
555 \\
556 \\fn add(a: u32, b: u32) u32 {
557 \\ const x: u32 = blk: {
558 \\ const c = a + b; // 7
559 \\ const d = a + c; // 10
560 \\ const e = d + b; // 14
561 \\ const f = d + e; // 24
562 \\ const g = e + f; // 38
563 \\ const h = f + g; // 62
564 \\ const i = g + h; // 100
565 \\ const j = i + d; // 110
566 \\ break :blk j;
567 \\ };
568 \\ const y = x + a; // 113
569 \\ const z = y + a; // 116
570 \\ return z;
571 \\}
572 \\
573 \\pub fn assert(ok: bool) void {
574 \\ if (!ok) unreachable; // assertion failure
575 \\}
576 \\
577 \\fn exit() noreturn {
578 \\ asm volatile ("syscall"
579 \\ :
580 \\ : [number] "{rax}" (231),
581 \\ [arg1] "{rdi}" (0)
582 \\ : "rcx", "r11", "memory"
583 \\ );
584 \\ unreachable;
585 \\}
586 ,
587 "",
588 );
589
590 // Character literals and multiline strings.
591 case.addCompareOutput(
592 \\export fn _start() noreturn {
593 \\ const ignore =
594 \\ \\ cool thx
595 \\ \\
596 \\ ;
597 \\ add('ぁ', '\x03');
598 \\
599 \\ exit();
600 \\}
601 \\
602 \\fn add(a: u32, b: u32) void {
603 \\ assert(a + b == 12356);
604 \\}
605 \\
606 \\pub fn assert(ok: bool) void {
607 \\ if (!ok) unreachable; // assertion failure
608 \\}
609 \\
610 \\fn exit() noreturn {
611 \\ asm volatile ("syscall"
612 \\ :
613 \\ : [number] "{rax}" (231),
614 \\ [arg1] "{rdi}" (0)
615 \\ : "rcx", "r11", "memory"
616 \\ );
617 \\ unreachable;
618 \\}
619 ,
620 "",
621 );
622
623 // Global const.
624 case.addCompareOutput(
625 \\export fn _start() noreturn {
626 \\ add(aa, bb);
627 \\
628 \\ exit();
629 \\}
630 \\
631 \\const aa = 'ぁ';
632 \\const bb = '\x03';
633 \\
634 \\fn add(a: u32, b: u32) void {
635 \\ assert(a + b == 12356);
636 \\}
637 \\
638 \\pub fn assert(ok: bool) void {
639 \\ if (!ok) unreachable; // assertion failure
640 \\}
641 \\
642 \\fn exit() noreturn {
643 \\ asm volatile ("syscall"
644 \\ :
645 \\ : [number] "{rax}" (231),
646 \\ [arg1] "{rdi}" (0)
647 \\ : "rcx", "r11", "memory"
648 \\ );
649 \\ unreachable;
650 \\}
651 ,
652 "",
653 );
654 }
655
656 {
657 var case = ctx.exe("wasm function calls", wasi);
658
659 case.addCompareOutput(
660 \\export fn _start() u32 {
661 \\ foo();
662 \\ bar();
663 \\ return 42;
664 \\}
665 \\fn foo() void {
666 \\ bar();
667 \\ bar();
668 \\}
669 \\fn bar() void {}
670 ,
671 "42\n",
672 );
673
674 case.addCompareOutput(
675 \\export fn _start() i64 {
676 \\ bar();
677 \\ foo();
678 \\ foo();
679 \\ bar();
680 \\ foo();
681 \\ bar();
682 \\ return 42;
683 \\}
684 \\fn foo() void {
685 \\ bar();
686 \\}
687 \\fn bar() void {}
688 ,
689 "42\n",
690 );
691
692 case.addCompareOutput(
693 \\export fn _start() f32 {
694 \\ bar();
695 \\ foo();
696 \\ return 42.0;
697 \\}
698 \\fn foo() void {
699 \\ bar();
700 \\ bar();
701 \\ bar();
702 \\}
703 \\fn bar() void {}
704 ,
705 // This is what you get when you take the bits of the IEE-754
706 // representation of 42.0 and reinterpret them as an unsigned
707 // integer. Guess that's a bug in wasmtime.
708 "1109917696\n",
709 );
710 }
711
712 ctx.compileError("function redefinition", linux_x64,
713 \\fn entry() void {}
714 \\fn entry() void {}
715 , &[_][]const u8{":2:4: error: redefinition of 'entry'"});
716
717 ctx.compileError("extern variable has no type", linux_x64,
718 \\comptime {
719 \\ _ = foo;
720 \\}
721 \\extern var foo;
722 , &[_][]const u8{":4:1: error: unable to infer variable type"});
723}
test/stage2/test.zig+720-1
...@@ -1,7 +1,726 @@...@@ -1,7 +1,726 @@
1const std = @import("std");
1const TestContext = @import("../../src-self-hosted/test.zig").TestContext;2const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
23
4// self-hosted does not yet support PE executable files / COFF object files
5// or mach-o files. So we do these test cases cross compiling for x86_64-linux.
6const linux_x64 = std.zig.CrossTarget{
7 .cpu_arch = .x86_64,
8 .os_tag = .linux,
9};
10
11const linux_riscv64 = std.zig.CrossTarget{
12 .cpu_arch = .riscv64,
13 .os_tag = .linux,
14};
15
16const wasi = std.zig.CrossTarget{
17 .cpu_arch = .wasm32,
18 .os_tag = .wasi,
19};
20
3pub fn addCases(ctx: *TestContext) !void {21pub fn addCases(ctx: *TestContext) !void {
4 try @import("compare_output.zig").addCases(ctx);
5 try @import("zir.zig").addCases(ctx);22 try @import("zir.zig").addCases(ctx);
6 try @import("cbe.zig").addCases(ctx);23 try @import("cbe.zig").addCases(ctx);
24 {
25 var case = ctx.exe("hello world with updates", linux_x64);
26
27 case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
28
29 // Incorrect return type
30 case.addError(
31 \\export fn _start() noreturn {
32 \\}
33 , &[_][]const u8{":2:1: error: expected noreturn, found void"});
34
35 // Regular old hello world
36 case.addCompareOutput(
37 \\export fn _start() noreturn {
38 \\ print();
39 \\
40 \\ exit();
41 \\}
42 \\
43 \\fn print() void {
44 \\ asm volatile ("syscall"
45 \\ :
46 \\ : [number] "{rax}" (1),
47 \\ [arg1] "{rdi}" (1),
48 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
49 \\ [arg3] "{rdx}" (14)
50 \\ : "rcx", "r11", "memory"
51 \\ );
52 \\ return;
53 \\}
54 \\
55 \\fn exit() noreturn {
56 \\ asm volatile ("syscall"
57 \\ :
58 \\ : [number] "{rax}" (231),
59 \\ [arg1] "{rdi}" (0)
60 \\ : "rcx", "r11", "memory"
61 \\ );
62 \\ unreachable;
63 \\}
64 ,
65 "Hello, World!\n",
66 );
67 // Now change the message only
68 case.addCompareOutput(
69 \\export fn _start() noreturn {
70 \\ print();
71 \\
72 \\ exit();
73 \\}
74 \\
75 \\fn print() void {
76 \\ asm volatile ("syscall"
77 \\ :
78 \\ : [number] "{rax}" (1),
79 \\ [arg1] "{rdi}" (1),
80 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
81 \\ [arg3] "{rdx}" (104)
82 \\ : "rcx", "r11", "memory"
83 \\ );
84 \\ return;
85 \\}
86 \\
87 \\fn exit() noreturn {
88 \\ asm volatile ("syscall"
89 \\ :
90 \\ : [number] "{rax}" (231),
91 \\ [arg1] "{rdi}" (0)
92 \\ : "rcx", "r11", "memory"
93 \\ );
94 \\ unreachable;
95 \\}
96 ,
97 "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
98 );
99 // Now we print it twice.
100 case.addCompareOutput(
101 \\export fn _start() noreturn {
102 \\ print();
103 \\ print();
104 \\
105 \\ exit();
106 \\}
107 \\
108 \\fn print() void {
109 \\ asm volatile ("syscall"
110 \\ :
111 \\ : [number] "{rax}" (1),
112 \\ [arg1] "{rdi}" (1),
113 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
114 \\ [arg3] "{rdx}" (104)
115 \\ : "rcx", "r11", "memory"
116 \\ );
117 \\ return;
118 \\}
119 \\
120 \\fn exit() noreturn {
121 \\ asm volatile ("syscall"
122 \\ :
123 \\ : [number] "{rax}" (231),
124 \\ [arg1] "{rdi}" (0)
125 \\ : "rcx", "r11", "memory"
126 \\ );
127 \\ unreachable;
128 \\}
129 ,
130 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
131 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
132 \\
133 );
134 }
135
136 {
137 var case = ctx.exe("hello world", linux_riscv64);
138 // Regular old hello world
139 case.addCompareOutput(
140 \\export fn _start() noreturn {
141 \\ print();
142 \\
143 \\ exit();
144 \\}
145 \\
146 \\fn print() void {
147 \\ asm volatile ("ecall"
148 \\ :
149 \\ : [number] "{a7}" (64),
150 \\ [arg1] "{a0}" (1),
151 \\ [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
152 \\ [arg3] "{a2}" ("Hello, World!\n".len)
153 \\ : "rcx", "r11", "memory"
154 \\ );
155 \\ return;
156 \\}
157 \\
158 \\fn exit() noreturn {
159 \\ asm volatile ("ecall"
160 \\ :
161 \\ : [number] "{a7}" (94),
162 \\ [arg1] "{a0}" (0)
163 \\ : "rcx", "r11", "memory"
164 \\ );
165 \\ unreachable;
166 \\}
167 ,
168 "Hello, World!\n",
169 );
170 }
171
172 {
173 var case = ctx.exe("adding numbers at comptime", linux_x64);
174 case.addCompareOutput(
175 \\export fn _start() noreturn {
176 \\ asm volatile ("syscall"
177 \\ :
178 \\ : [number] "{rax}" (1),
179 \\ [arg1] "{rdi}" (1),
180 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
181 \\ [arg3] "{rdx}" (10 + 4)
182 \\ : "rcx", "r11", "memory"
183 \\ );
184 \\ asm volatile ("syscall"
185 \\ :
186 \\ : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)),
187 \\ [arg1] "{rdi}" (0)
188 \\ : "rcx", "r11", "memory"
189 \\ );
190 \\ unreachable;
191 \\}
192 ,
193 "Hello, World!\n",
194 );
195 }
196
197 {
198 var case = ctx.exe("adding numbers at runtime", linux_x64);
199 case.addCompareOutput(
200 \\export fn _start() noreturn {
201 \\ add(3, 4);
202 \\
203 \\ exit();
204 \\}
205 \\
206 \\fn add(a: u32, b: u32) void {
207 \\ if (a + b != 7) unreachable;
208 \\}
209 \\
210 \\fn exit() noreturn {
211 \\ asm volatile ("syscall"
212 \\ :
213 \\ : [number] "{rax}" (231),
214 \\ [arg1] "{rdi}" (0)
215 \\ : "rcx", "r11", "memory"
216 \\ );
217 \\ unreachable;
218 \\}
219 ,
220 "",
221 );
222 }
223
224 {
225 var case = ctx.exe("substracting numbers at runtime", linux_x64);
226 case.addCompareOutput(
227 \\export fn _start() noreturn {
228 \\ sub(7, 4);
229 \\
230 \\ exit();
231 \\}
232 \\
233 \\fn sub(a: u32, b: u32) void {
234 \\ if (a - b != 3) unreachable;
235 \\}
236 \\
237 \\fn exit() noreturn {
238 \\ asm volatile ("syscall"
239 \\ :
240 \\ : [number] "{rax}" (231),
241 \\ [arg1] "{rdi}" (0)
242 \\ : "rcx", "r11", "memory"
243 \\ );
244 \\ unreachable;
245 \\}
246 ,
247 "",
248 );
249 }
250
251 {
252 var case = ctx.exe("assert function", linux_x64);
253 case.addCompareOutput(
254 \\export fn _start() noreturn {
255 \\ add(3, 4);
256 \\
257 \\ exit();
258 \\}
259 \\
260 \\fn add(a: u32, b: u32) void {
261 \\ assert(a + b == 7);
262 \\}
263 \\
264 \\pub fn assert(ok: bool) void {
265 \\ if (!ok) unreachable; // assertion failure
266 \\}
267 \\
268 \\fn exit() noreturn {
269 \\ asm volatile ("syscall"
270 \\ :
271 \\ : [number] "{rax}" (231),
272 \\ [arg1] "{rdi}" (0)
273 \\ : "rcx", "r11", "memory"
274 \\ );
275 \\ unreachable;
276 \\}
277 ,
278 "",
279 );
280
281 // Tests copying a register. For the `c = a + b`, it has to
282 // preserve both a and b, because they are both used later.
283 case.addCompareOutput(
284 \\export fn _start() noreturn {
285 \\ add(3, 4);
286 \\
287 \\ exit();
288 \\}
289 \\
290 \\fn add(a: u32, b: u32) void {
291 \\ const c = a + b; // 7
292 \\ const d = a + c; // 10
293 \\ const e = d + b; // 14
294 \\ assert(e == 14);
295 \\}
296 \\
297 \\pub fn assert(ok: bool) void {
298 \\ if (!ok) unreachable; // assertion failure
299 \\}
300 \\
301 \\fn exit() noreturn {
302 \\ asm volatile ("syscall"
303 \\ :
304 \\ : [number] "{rax}" (231),
305 \\ [arg1] "{rdi}" (0)
306 \\ : "rcx", "r11", "memory"
307 \\ );
308 \\ unreachable;
309 \\}
310 ,
311 "",
312 );
313
314 // More stress on the liveness detection.
315 case.addCompareOutput(
316 \\export fn _start() noreturn {
317 \\ add(3, 4);
318 \\
319 \\ exit();
320 \\}
321 \\
322 \\fn add(a: u32, b: u32) void {
323 \\ const c = a + b; // 7
324 \\ const d = a + c; // 10
325 \\ const e = d + b; // 14
326 \\ const f = d + e; // 24
327 \\ const g = e + f; // 38
328 \\ const h = f + g; // 62
329 \\ const i = g + h; // 100
330 \\ assert(i == 100);
331 \\}
332 \\
333 \\pub fn assert(ok: bool) void {
334 \\ if (!ok) unreachable; // assertion failure
335 \\}
336 \\
337 \\fn exit() noreturn {
338 \\ asm volatile ("syscall"
339 \\ :
340 \\ : [number] "{rax}" (231),
341 \\ [arg1] "{rdi}" (0)
342 \\ : "rcx", "r11", "memory"
343 \\ );
344 \\ unreachable;
345 \\}
346 ,
347 "",
348 );
349
350 // Requires a second move. The register allocator should figure out to re-use rax.
351 case.addCompareOutput(
352 \\export fn _start() noreturn {
353 \\ add(3, 4);
354 \\
355 \\ exit();
356 \\}
357 \\
358 \\fn add(a: u32, b: u32) void {
359 \\ const c = a + b; // 7
360 \\ const d = a + c; // 10
361 \\ const e = d + b; // 14
362 \\ const f = d + e; // 24
363 \\ const g = e + f; // 38
364 \\ const h = f + g; // 62
365 \\ const i = g + h; // 100
366 \\ const j = i + d; // 110
367 \\ assert(j == 110);
368 \\}
369 \\
370 \\pub fn assert(ok: bool) void {
371 \\ if (!ok) unreachable; // assertion failure
372 \\}
373 \\
374 \\fn exit() noreturn {
375 \\ asm volatile ("syscall"
376 \\ :
377 \\ : [number] "{rax}" (231),
378 \\ [arg1] "{rdi}" (0)
379 \\ : "rcx", "r11", "memory"
380 \\ );
381 \\ unreachable;
382 \\}
383 ,
384 "",
385 );
386
387 // Now we test integer return values.
388 case.addCompareOutput(
389 \\export fn _start() noreturn {
390 \\ assert(add(3, 4) == 7);
391 \\ assert(add(20, 10) == 30);
392 \\
393 \\ exit();
394 \\}
395 \\
396 \\fn add(a: u32, b: u32) u32 {
397 \\ return a + b;
398 \\}
399 \\
400 \\pub fn assert(ok: bool) void {
401 \\ if (!ok) unreachable; // assertion failure
402 \\}
403 \\
404 \\fn exit() noreturn {
405 \\ asm volatile ("syscall"
406 \\ :
407 \\ : [number] "{rax}" (231),
408 \\ [arg1] "{rdi}" (0)
409 \\ : "rcx", "r11", "memory"
410 \\ );
411 \\ unreachable;
412 \\}
413 ,
414 "",
415 );
416
417 // Local mutable variables.
418 case.addCompareOutput(
419 \\export fn _start() noreturn {
420 \\ assert(add(3, 4) == 7);
421 \\ assert(add(20, 10) == 30);
422 \\
423 \\ exit();
424 \\}
425 \\
426 \\fn add(a: u32, b: u32) u32 {
427 \\ var x: u32 = undefined;
428 \\ x = 0;
429 \\ x += a;
430 \\ x += b;
431 \\ return x;
432 \\}
433 \\
434 \\pub fn assert(ok: bool) void {
435 \\ if (!ok) unreachable; // assertion failure
436 \\}
437 \\
438 \\fn exit() noreturn {
439 \\ asm volatile ("syscall"
440 \\ :
441 \\ : [number] "{rax}" (231),
442 \\ [arg1] "{rdi}" (0)
443 \\ : "rcx", "r11", "memory"
444 \\ );
445 \\ unreachable;
446 \\}
447 ,
448 "",
449 );
450
451 // Optionals
452 case.addCompareOutput(
453 \\export fn _start() noreturn {
454 \\ const a: u32 = 2;
455 \\ const b: ?u32 = a;
456 \\ const c = b.?;
457 \\ if (c != 2) unreachable;
458 \\
459 \\ exit();
460 \\}
461 \\
462 \\fn exit() noreturn {
463 \\ asm volatile ("syscall"
464 \\ :
465 \\ : [number] "{rax}" (231),
466 \\ [arg1] "{rdi}" (0)
467 \\ : "rcx", "r11", "memory"
468 \\ );
469 \\ unreachable;
470 \\}
471 ,
472 "",
473 );
474
475 // While loops
476 case.addCompareOutput(
477 \\export fn _start() noreturn {
478 \\ var i: u32 = 0;
479 \\ while (i < 4) : (i += 1) print();
480 \\ assert(i == 4);
481 \\
482 \\ exit();
483 \\}
484 \\
485 \\fn print() void {
486 \\ asm volatile ("syscall"
487 \\ :
488 \\ : [number] "{rax}" (1),
489 \\ [arg1] "{rdi}" (1),
490 \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
491 \\ [arg3] "{rdx}" (6)
492 \\ : "rcx", "r11", "memory"
493 \\ );
494 \\ return;
495 \\}
496 \\
497 \\pub fn assert(ok: bool) void {
498 \\ if (!ok) unreachable; // assertion failure
499 \\}
500 \\
501 \\fn exit() noreturn {
502 \\ asm volatile ("syscall"
503 \\ :
504 \\ : [number] "{rax}" (231),
505 \\ [arg1] "{rdi}" (0)
506 \\ : "rcx", "r11", "memory"
507 \\ );
508 \\ unreachable;
509 \\}
510 ,
511 "hello\nhello\nhello\nhello\n",
512 );
513
514 // Labeled blocks (no conditional branch)
515 case.addCompareOutput(
516 \\export fn _start() noreturn {
517 \\ assert(add(3, 4) == 20);
518 \\
519 \\ exit();
520 \\}
521 \\
522 \\fn add(a: u32, b: u32) u32 {
523 \\ const x: u32 = blk: {
524 \\ const c = a + b; // 7
525 \\ const d = a + c; // 10
526 \\ const e = d + b; // 14
527 \\ break :blk e;
528 \\ };
529 \\ const y = x + a; // 17
530 \\ const z = y + a; // 20
531 \\ return z;
532 \\}
533 \\
534 \\pub fn assert(ok: bool) void {
535 \\ if (!ok) unreachable; // assertion failure
536 \\}
537 \\
538 \\fn exit() noreturn {
539 \\ asm volatile ("syscall"
540 \\ :
541 \\ : [number] "{rax}" (231),
542 \\ [arg1] "{rdi}" (0)
543 \\ : "rcx", "r11", "memory"
544 \\ );
545 \\ unreachable;
546 \\}
547 ,
548 "",
549 );
550
551 // This catches a possible bug in the logic for re-using dying operands.
552 case.addCompareOutput(
553 \\export fn _start() noreturn {
554 \\ assert(add(3, 4) == 116);
555 \\
556 \\ exit();
557 \\}
558 \\
559 \\fn add(a: u32, b: u32) u32 {
560 \\ const x: u32 = blk: {
561 \\ const c = a + b; // 7
562 \\ const d = a + c; // 10
563 \\ const e = d + b; // 14
564 \\ const f = d + e; // 24
565 \\ const g = e + f; // 38
566 \\ const h = f + g; // 62
567 \\ const i = g + h; // 100
568 \\ const j = i + d; // 110
569 \\ break :blk j;
570 \\ };
571 \\ const y = x + a; // 113
572 \\ const z = y + a; // 116
573 \\ return z;
574 \\}
575 \\
576 \\pub fn assert(ok: bool) void {
577 \\ if (!ok) unreachable; // assertion failure
578 \\}
579 \\
580 \\fn exit() noreturn {
581 \\ asm volatile ("syscall"
582 \\ :
583 \\ : [number] "{rax}" (231),
584 \\ [arg1] "{rdi}" (0)
585 \\ : "rcx", "r11", "memory"
586 \\ );
587 \\ unreachable;
588 \\}
589 ,
590 "",
591 );
592
593 // Character literals and multiline strings.
594 case.addCompareOutput(
595 \\export fn _start() noreturn {
596 \\ const ignore =
597 \\ \\ cool thx
598 \\ \\
599 \\ ;
600 \\ add('ぁ', '\x03');
601 \\
602 \\ exit();
603 \\}
604 \\
605 \\fn add(a: u32, b: u32) void {
606 \\ assert(a + b == 12356);
607 \\}
608 \\
609 \\pub fn assert(ok: bool) void {
610 \\ if (!ok) unreachable; // assertion failure
611 \\}
612 \\
613 \\fn exit() noreturn {
614 \\ asm volatile ("syscall"
615 \\ :
616 \\ : [number] "{rax}" (231),
617 \\ [arg1] "{rdi}" (0)
618 \\ : "rcx", "r11", "memory"
619 \\ );
620 \\ unreachable;
621 \\}
622 ,
623 "",
624 );
625
626 // Global const.
627 case.addCompareOutput(
628 \\export fn _start() noreturn {
629 \\ add(aa, bb);
630 \\
631 \\ exit();
632 \\}
633 \\
634 \\const aa = 'ぁ';
635 \\const bb = '\x03';
636 \\
637 \\fn add(a: u32, b: u32) void {
638 \\ assert(a + b == 12356);
639 \\}
640 \\
641 \\pub fn assert(ok: bool) void {
642 \\ if (!ok) unreachable; // assertion failure
643 \\}
644 \\
645 \\fn exit() noreturn {
646 \\ asm volatile ("syscall"
647 \\ :
648 \\ : [number] "{rax}" (231),
649 \\ [arg1] "{rdi}" (0)
650 \\ : "rcx", "r11", "memory"
651 \\ );
652 \\ unreachable;
653 \\}
654 ,
655 "",
656 );
657 }
658
659 {
660 var case = ctx.exe("wasm function calls", wasi);
661
662 case.addCompareOutput(
663 \\export fn _start() u32 {
664 \\ foo();
665 \\ bar();
666 \\ return 42;
667 \\}
668 \\fn foo() void {
669 \\ bar();
670 \\ bar();
671 \\}
672 \\fn bar() void {}
673 ,
674 "42\n",
675 );
676
677 case.addCompareOutput(
678 \\export fn _start() i64 {
679 \\ bar();
680 \\ foo();
681 \\ foo();
682 \\ bar();
683 \\ foo();
684 \\ bar();
685 \\ return 42;
686 \\}
687 \\fn foo() void {
688 \\ bar();
689 \\}
690 \\fn bar() void {}
691 ,
692 "42\n",
693 );
694
695 case.addCompareOutput(
696 \\export fn _start() f32 {
697 \\ bar();
698 \\ foo();
699 \\ return 42.0;
700 \\}
701 \\fn foo() void {
702 \\ bar();
703 \\ bar();
704 \\ bar();
705 \\}
706 \\fn bar() void {}
707 ,
708 // This is what you get when you take the bits of the IEE-754
709 // representation of 42.0 and reinterpret them as an unsigned
710 // integer. Guess that's a bug in wasmtime.
711 "1109917696\n",
712 );
713 }
714
715 ctx.compileError("function redefinition", linux_x64,
716 \\fn entry() void {}
717 \\fn entry() void {}
718 , &[_][]const u8{":2:4: error: redefinition of 'entry'"});
719
720 ctx.compileError("extern variable has no type", linux_x64,
721 \\comptime {
722 \\ _ = foo;
723 \\}
724 \\extern var foo;
725 , &[_][]const u8{":4:1: error: unable to infer variable type"});
7}726}