authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-27 17:53:24+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-28 18:35:01+02:00
loge4a8a665040b22b52519b68433ed58b1e34f841d
tree1d97f9939ee1c6d37a6e9409f7a38730664a3a20
parent97b781955eca7c3fc6ee2713f8b5e355645fff58

test: remove incremental tests that were ported to the new harness


1 files changed, 32 insertions(+), 2261 deletions(-)

test/stage2/x86_64.zig+32-2261
...@@ -16,2273 +16,44 @@ const all_targets: []const CrossTarget = &[_]CrossTarget{...@@ -16,2273 +16,44 @@ const all_targets: []const CrossTarget = &[_]CrossTarget{
16};16};
1717
18pub fn addCases(ctx: *TestContext) !void {18pub fn addCases(ctx: *TestContext) !void {
19 try addLinuxTestCases(ctx);
20 try addMacOsTestCases(ctx);
21
22 // Common tests
23 for (all_targets) |target| {19 for (all_targets) |target| {
24 {20 // TODO port this to the new test harness
25 var case = ctx.exe("adding numbers at runtime and comptime", target);21 var case = ctx.exe("basic import", target);
26 case.addCompareOutput(
27 \\pub fn main() void {
28 \\ add(3, 4);
29 \\}
30 \\
31 \\fn add(a: u32, b: u32) void {
32 \\ if (a + b != 7) unreachable;
33 \\}
34 ,
35 "",
36 );
37 // comptime function call
38 case.addCompareOutput(
39 \\pub fn main() void {
40 \\ if (x - 7 != 0) unreachable;
41 \\}
42 \\
43 \\fn add(a: u32, b: u32) u32 {
44 \\ return a + b;
45 \\}
46 \\
47 \\const x = add(3, 4);
48 ,
49 "",
50 );
51 // Inline function call
52 case.addCompareOutput(
53 \\pub fn main() void {
54 \\ var x: usize = 3;
55 \\ const y = add(1, 2, x);
56 \\ if (y - 6 != 0) unreachable;
57 \\}
58 \\
59 \\fn add(a: usize, b: usize, c: usize) callconv(.Inline) usize {
60 \\ return a + b + c;
61 \\}
62 ,
63 "",
64 );
65 }
66
67 {
68 var case = ctx.exe("subtracting numbers at runtime", target);
69 case.addCompareOutput(
70 \\pub fn main() void {
71 \\ sub(7, 4);
72 \\}
73 \\
74 \\fn sub(a: u32, b: u32) void {
75 \\ if (a - b != 3) unreachable;
76 \\}
77 ,
78 "",
79 );
80 }
81
82 {
83 var case = ctx.exe("unused vars", target);
84 case.addError(
85 \\pub fn main() void {
86 \\ const x = 1;
87 \\}
88 , &.{":2:11: error: unused local constant"});
89 }
90
91 {
92 var case = ctx.exe("multiplying numbers at runtime and comptime", target);
93 case.addCompareOutput(
94 \\pub fn main() void {
95 \\ mul(3, 4);
96 \\}
97 \\
98 \\fn mul(a: u32, b: u32) void {
99 \\ if (a * b != 12) unreachable;
100 \\}
101 ,
102 "",
103 );
104 // comptime function call
105 case.addCompareOutput(
106 \\pub fn main() void {
107 \\ if (x - 12 != 0) unreachable;
108 \\}
109 \\
110 \\fn mul(a: u32, b: u32) u32 {
111 \\ return a * b;
112 \\}
113 \\
114 \\const x = mul(3, 4);
115 ,
116 "",
117 );
118 // Inline function call
119 case.addCompareOutput(
120 \\pub fn main() void {
121 \\ var x: usize = 5;
122 \\ const y = mul(2, 3, x);
123 \\ if (y - 30 != 0) unreachable;
124 \\}
125 \\
126 \\fn mul(a: usize, b: usize, c: usize) callconv(.Inline) usize {
127 \\ return a * b * c;
128 \\}
129 ,
130 "",
131 );
132 }
133
134 {
135 var case = ctx.exe("assert function", target);
136 case.addCompareOutput(
137 \\pub fn main() void {
138 \\ add(3, 4);
139 \\}
140 \\
141 \\fn add(a: u32, b: u32) void {
142 \\ assert(a + b == 7);
143 \\}
144 \\
145 \\pub fn assert(ok: bool) void {
146 \\ if (!ok) unreachable; // assertion failure
147 \\}
148 ,
149 "",
150 );
151
152 // Tests copying a register. For the `c = a + b`, it has to
153 // preserve both a and b, because they are both used later.
154 case.addCompareOutput(
155 \\pub fn main() void {
156 \\ add(3, 4);
157 \\}
158 \\
159 \\fn add(a: u32, b: u32) void {
160 \\ const c = a + b; // 7
161 \\ const d = a + c; // 10
162 \\ const e = d + b; // 14
163 \\ assert(e == 14);
164 \\}
165 \\
166 \\pub fn assert(ok: bool) void {
167 \\ if (!ok) unreachable; // assertion failure
168 \\}
169 ,
170 "",
171 );
172
173 // More stress on the liveness detection.
174 case.addCompareOutput(
175 \\pub fn main() void {
176 \\ add(3, 4);
177 \\}
178 \\
179 \\fn add(a: u32, b: u32) void {
180 \\ const c = a + b; // 7
181 \\ const d = a + c; // 10
182 \\ const e = d + b; // 14
183 \\ const f = d + e; // 24
184 \\ const g = e + f; // 38
185 \\ const h = f + g; // 62
186 \\ const i = g + h; // 100
187 \\ assert(i == 100);
188 \\}
189 \\
190 \\pub fn assert(ok: bool) void {
191 \\ if (!ok) unreachable; // assertion failure
192 \\}
193 ,
194 "",
195 );
196
197 // Requires a second move. The register allocator should figure out to re-use rax.
198 case.addCompareOutput(
199 \\pub fn main() void {
200 \\ add(3, 4);
201 \\}
202 \\
203 \\fn add(a: u32, b: u32) void {
204 \\ const c = a + b; // 7
205 \\ const d = a + c; // 10
206 \\ const e = d + b; // 14
207 \\ const f = d + e; // 24
208 \\ const g = e + f; // 38
209 \\ const h = f + g; // 62
210 \\ const i = g + h; // 100
211 \\ const j = i + d; // 110
212 \\ assert(j == 110);
213 \\}
214 \\
215 \\pub fn assert(ok: bool) void {
216 \\ if (!ok) unreachable; // assertion failure
217 \\}
218 ,
219 "",
220 );
221
222 // Now we test integer return values.
223 case.addCompareOutput(
224 \\pub fn main() void {
225 \\ assert(add(3, 4) == 7);
226 \\ assert(add(20, 10) == 30);
227 \\}
228 \\
229 \\fn add(a: u32, b: u32) u32 {
230 \\ return a + b;
231 \\}
232 \\
233 \\pub fn assert(ok: bool) void {
234 \\ if (!ok) unreachable; // assertion failure
235 \\}
236 ,
237 "",
238 );
239
240 // Local mutable variables.
241 case.addCompareOutput(
242 \\pub fn main() void {
243 \\ assert(add(3, 4) == 7);
244 \\ assert(add(20, 10) == 30);
245 \\}
246 \\
247 \\fn add(a: u32, b: u32) u32 {
248 \\ var x: u32 = undefined;
249 \\ x = 0;
250 \\ x += a;
251 \\ x += b;
252 \\ return x;
253 \\}
254 \\
255 \\pub fn assert(ok: bool) void {
256 \\ if (!ok) unreachable; // assertion failure
257 \\}
258 ,
259 "",
260 );
261
262 // Optionals
263 case.addCompareOutput(
264 \\pub fn main() void {
265 \\ const a: u32 = 2;
266 \\ const b: ?u32 = a;
267 \\ const c = b.?;
268 \\ if (c != 2) unreachable;
269 \\}
270 ,
271 "",
272 );
273
274 switch (target.getOsTag()) {
275 .linux => {
276 // While loops
277 case.addCompareOutput(
278 \\pub fn main() void {
279 \\ var i: u32 = 0;
280 \\ while (i < 4) : (i += 1) print();
281 \\ assert(i == 4);
282 \\}
283 \\
284 \\fn print() void {
285 \\ asm volatile ("syscall"
286 \\ :
287 \\ : [number] "{rax}" (1),
288 \\ [arg1] "{rdi}" (1),
289 \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
290 \\ [arg3] "{rdx}" (6)
291 \\ : "rcx", "r11", "memory"
292 \\ );
293 \\ return;
294 \\}
295 \\
296 \\pub fn assert(ok: bool) void {
297 \\ if (!ok) unreachable; // assertion failure
298 \\}
299 ,
300 "hello\nhello\nhello\nhello\n",
301 );
302
303 // inline while requires the condition to be comptime known.
304 case.addError(
305 \\pub fn main() void {
306 \\ var i: u32 = 0;
307 \\ inline while (i < 4) : (i += 1) print();
308 \\ assert(i == 4);
309 \\}
310 \\
311 \\fn print() void {
312 \\ asm volatile ("syscall"
313 \\ :
314 \\ : [number] "{rax}" (1),
315 \\ [arg1] "{rdi}" (1),
316 \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
317 \\ [arg3] "{rdx}" (6)
318 \\ : "rcx", "r11", "memory"
319 \\ );
320 \\ return;
321 \\}
322 \\
323 \\pub fn assert(ok: bool) void {
324 \\ if (!ok) unreachable; // assertion failure
325 \\}
326 , &[_][]const u8{":3:21: error: unable to resolve comptime value"});
327 },
328 .macos => {
329 // While loops
330 case.addCompareOutput(
331 \\extern "c" fn write(usize, usize, usize) usize;
332 \\
333 \\pub fn main() void {
334 \\ var i: u32 = 0;
335 \\ while (i < 4) : (i += 1) print();
336 \\ assert(i == 4);
337 \\}
338 \\
339 \\fn print() void {
340 \\ _ = write(1, @ptrToInt("hello\n"), 6);
341 \\}
342 \\
343 \\pub fn assert(ok: bool) void {
344 \\ if (!ok) unreachable; // assertion failure
345 \\}
346 ,
347 "hello\nhello\nhello\nhello\n",
348 );
349
350 // inline while requires the condition to be comptime known.
351 case.addError(
352 \\extern "c" fn write(usize, usize, usize) usize;
353 \\
354 \\pub fn main() void {
355 \\ var i: u32 = 0;
356 \\ inline while (i < 4) : (i += 1) print();
357 \\ assert(i == 4);
358 \\}
359 \\
360 \\fn print() void {
361 \\ _ = write(1, @ptrToInt("hello\n"), 6);
362 \\}
363 \\
364 \\pub fn assert(ok: bool) void {
365 \\ if (!ok) unreachable; // assertion failure
366 \\}
367 , &[_][]const u8{":5:21: error: unable to resolve comptime value"});
368 },
369 else => unreachable,
370 }
371
372 // Labeled blocks (no conditional branch)
373 case.addCompareOutput(
374 \\pub fn main() void {
375 \\ assert(add(3, 4) == 20);
376 \\}
377 \\
378 \\fn add(a: u32, b: u32) u32 {
379 \\ const x: u32 = blk: {
380 \\ const c = a + b; // 7
381 \\ const d = a + c; // 10
382 \\ const e = d + b; // 14
383 \\ break :blk e;
384 \\ };
385 \\ const y = x + a; // 17
386 \\ const z = y + a; // 20
387 \\ return z;
388 \\}
389 \\
390 \\pub fn assert(ok: bool) void {
391 \\ if (!ok) unreachable; // assertion failure
392 \\}
393 ,
394 "",
395 );
396
397 // This catches a possible bug in the logic for re-using dying operands.
398 case.addCompareOutput(
399 \\pub fn main() void {
400 \\ assert(add(3, 4) == 116);
401 \\}
402 \\
403 \\fn add(a: u32, b: u32) u32 {
404 \\ const x: u32 = blk: {
405 \\ const c = a + b; // 7
406 \\ const d = a + c; // 10
407 \\ const e = d + b; // 14
408 \\ const f = d + e; // 24
409 \\ const g = e + f; // 38
410 \\ const h = f + g; // 62
411 \\ const i = g + h; // 100
412 \\ const j = i + d; // 110
413 \\ break :blk j;
414 \\ };
415 \\ const y = x + a; // 113
416 \\ const z = y + a; // 116
417 \\ return z;
418 \\}
419 \\
420 \\pub fn assert(ok: bool) void {
421 \\ if (!ok) unreachable; // assertion failure
422 \\}
423 ,
424 "",
425 );
426
427 // Spilling registers to the stack.
428 case.addCompareOutput(
429 \\pub fn main() void {
430 \\ assert(add(3, 4) == 1221);
431 \\ assert(mul(3, 4) == 21609);
432 \\}
433 \\
434 \\fn add(a: u32, b: u32) u32 {
435 \\ const x: u32 = blk: {
436 \\ const c = a + b; // 7
437 \\ const d = a + c; // 10
438 \\ const e = d + b; // 14
439 \\ const f = d + e; // 24
440 \\ const g = e + f; // 38
441 \\ const h = f + g; // 62
442 \\ const i = g + h; // 100
443 \\ const j = i + d; // 110
444 \\ const k = i + j; // 210
445 \\ const l = j + k; // 320
446 \\ const m = l + c; // 327
447 \\ const n = m + d; // 337
448 \\ const o = n + e; // 351
449 \\ const p = o + f; // 375
450 \\ const q = p + g; // 413
451 \\ const r = q + h; // 475
452 \\ const s = r + i; // 575
453 \\ const t = s + j; // 685
454 \\ const u = t + k; // 895
455 \\ const v = u + l; // 1215
456 \\ break :blk v;
457 \\ };
458 \\ const y = x + a; // 1218
459 \\ const z = y + a; // 1221
460 \\ return z;
461 \\}
462 \\
463 \\fn mul(a: u32, b: u32) u32 {
464 \\ const x: u32 = blk: {
465 \\ const c = a * a * a * a; // 81
466 \\ const d = a * a * a * b; // 108
467 \\ const e = a * a * b * a; // 108
468 \\ const f = a * a * b * b; // 144
469 \\ const g = a * b * a * a; // 108
470 \\ const h = a * b * a * b; // 144
471 \\ const i = a * b * b * a; // 144
472 \\ const j = a * b * b * b; // 192
473 \\ const k = b * a * a * a; // 108
474 \\ const l = b * a * a * b; // 144
475 \\ const m = b * a * b * a; // 144
476 \\ const n = b * a * b * b; // 192
477 \\ const o = b * b * a * a; // 144
478 \\ const p = b * b * a * b; // 192
479 \\ const q = b * b * b * a; // 192
480 \\ const r = b * b * b * b; // 256
481 \\ const s = c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r; // 2401
482 \\ break :blk s;
483 \\ };
484 \\ const y = x * a; // 7203
485 \\ const z = y * a; // 21609
486 \\ return z;
487 \\}
488 \\
489 \\pub fn assert(ok: bool) void {
490 \\ if (!ok) unreachable; // assertion failure
491 \\}
492 ,
493 "",
494 );
495
496 // Reusing the registers of dead operands playing nicely with conditional branching.
497 case.addCompareOutput(
498 \\pub fn main() void {
499 \\ assert(add(3, 4) == 791);
500 \\ assert(add(4, 3) == 79);
501 \\}
502 \\
503 \\fn add(a: u32, b: u32) u32 {
504 \\ const x: u32 = if (a < b) blk: {
505 \\ const c = a + b; // 7
506 \\ const d = a + c; // 10
507 \\ const e = d + b; // 14
508 \\ const f = d + e; // 24
509 \\ const g = e + f; // 38
510 \\ const h = f + g; // 62
511 \\ const i = g + h; // 100
512 \\ const j = i + d; // 110
513 \\ const k = i + j; // 210
514 \\ const l = k + c; // 217
515 \\ const m = l + d; // 227
516 \\ const n = m + e; // 241
517 \\ const o = n + f; // 265
518 \\ const p = o + g; // 303
519 \\ const q = p + h; // 365
520 \\ const r = q + i; // 465
521 \\ const s = r + j; // 575
522 \\ const t = s + k; // 785
523 \\ break :blk t;
524 \\ } else blk: {
525 \\ const t = b + b + a; // 10
526 \\ const c = a + t; // 14
527 \\ const d = c + t; // 24
528 \\ const e = d + t; // 34
529 \\ const f = e + t; // 44
530 \\ const g = f + t; // 54
531 \\ const h = c + g; // 68
532 \\ break :blk h + b; // 71
533 \\ };
534 \\ const y = x + a; // 788, 75
535 \\ const z = y + a; // 791, 79
536 \\ return z;
537 \\}
538 \\
539 \\pub fn assert(ok: bool) void {
540 \\ if (!ok) unreachable; // assertion failure
541 \\}
542 ,
543 "",
544 );
545
546 // Character literals and multiline strings.
547 case.addCompareOutput(
548 \\pub fn main() void {
549 \\ const ignore =
550 \\ \\ cool thx
551 \\ \\
552 \\ ;
553 \\ _ = ignore;
554 \\ add('ぁ', '\x03');
555 \\}
556 \\
557 \\fn add(a: u32, b: u32) void {
558 \\ assert(a + b == 12356);
559 \\}
560 \\
561 \\pub fn assert(ok: bool) void {
562 \\ if (!ok) unreachable; // assertion failure
563 \\}
564 ,
565 "",
566 );
567
568 // Global const.
569 case.addCompareOutput(
570 \\pub fn main() void {
571 \\ add(aa, bb);
572 \\}
573 \\
574 \\const aa = 'ぁ';
575 \\const bb = '\x03';
576 \\
577 \\fn add(a: u32, b: u32) void {
578 \\ assert(a + b == 12356);
579 \\}
580 \\
581 \\pub fn assert(ok: bool) void {
582 \\ if (!ok) unreachable; // assertion failure
583 \\}
584 ,
585 "",
586 );
587
588 // Array access.
589 case.addCompareOutput(
590 \\pub fn main() void {
591 \\ assert("hello"[0] == 'h');
592 \\}
593 \\
594 \\pub fn assert(ok: bool) void {
595 \\ if (!ok) unreachable; // assertion failure
596 \\}
597 ,
598 "",
599 );
600
601 // Array access to a global array.
602 case.addCompareOutput(
603 \\const hello = "hello".*;
604 \\pub fn main() void {
605 \\ assert(hello[1] == 'e');
606 \\}
607 \\
608 \\pub fn assert(ok: bool) void {
609 \\ if (!ok) unreachable; // assertion failure
610 \\}
611 ,
612 "",
613 );
614
615 // 64bit set stack
616 case.addCompareOutput(
617 \\pub fn main() void {
618 \\ var i: u64 = 0xFFEEDDCCBBAA9988;
619 \\ assert(i == 0xFFEEDDCCBBAA9988);
620 \\}
621 \\
622 \\pub fn assert(ok: bool) void {
623 \\ if (!ok) unreachable; // assertion failure
624 \\}
625 ,
626 "",
627 );
628
629 switch (target.getOsTag()) {
630 .linux => {
631 // Basic for loop
632 case.addCompareOutput(
633 \\pub fn main() void {
634 \\ for ("hello") |_| print();
635 \\}
636 \\
637 \\fn print() void {
638 \\ asm volatile ("syscall"
639 \\ :
640 \\ : [number] "{rax}" (1),
641 \\ [arg1] "{rdi}" (1),
642 \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
643 \\ [arg3] "{rdx}" (6)
644 \\ : "rcx", "r11", "memory"
645 \\ );
646 \\ return;
647 \\}
648 ,
649 "hello\nhello\nhello\nhello\nhello\n",
650 );
651 },
652 .macos => {
653 // Basic for loop
654 case.addCompareOutput(
655 \\extern "c" fn write(usize, usize, usize) usize;
656 \\
657 \\pub fn main() void {
658 \\ for ("hello") |_| print();
659 \\}
660 \\
661 \\fn print() void {
662 \\ _ = write(1, @ptrToInt("hello\n"), 6);
663 \\}
664 ,
665 "hello\nhello\nhello\nhello\nhello\n",
666 );
667 },
668 else => unreachable,
669 }
670 }
671
672 {
673 var case = ctx.exe("@TypeOf", target);
674 case.addCompareOutput(
675 \\pub fn main() void {
676 \\ var x: usize = 0;
677 \\ _ = x;
678 \\ const z = @TypeOf(x, @as(u128, 5));
679 \\ assert(z == u128);
680 \\}
681 \\
682 \\pub fn assert(ok: bool) void {
683 \\ if (!ok) unreachable; // assertion failure
684 \\}
685 ,
686 "",
687 );
688 case.addCompareOutput(
689 \\pub fn main() void {
690 \\ const z = @TypeOf(true);
691 \\ assert(z == bool);
692 \\}
693 \\
694 \\pub fn assert(ok: bool) void {
695 \\ if (!ok) unreachable; // assertion failure
696 \\}
697 ,
698 "",
699 );
700 case.addError(
701 \\pub fn main() void {
702 \\ _ = @TypeOf(true, 1);
703 \\}
704 , &[_][]const u8{
705 ":2:9: error: incompatible types: 'bool' and 'comptime_int'",
706 ":2:17: note: type 'bool' here",
707 ":2:23: note: type 'comptime_int' here",
708 });
709 }
710
711 {
712 var case = ctx.exe("basic import", target);
713 case.addCompareOutput(
714 \\pub fn main() void {
715 \\ @import("print.zig").print();
716 \\}
717 ,
718 "Hello, World!\n",
719 );
720 switch (target.getOsTag()) {
721 .linux => try case.files.append(.{
722 .src =
723 \\pub fn print() void {
724 \\ asm volatile ("syscall"
725 \\ :
726 \\ : [number] "{rax}" (@as(usize, 1)),
727 \\ [arg1] "{rdi}" (@as(usize, 1)),
728 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
729 \\ [arg3] "{rdx}" (@as(usize, 14))
730 \\ : "rcx", "r11", "memory"
731 \\ );
732 \\ return;
733 \\}
734 ,
735 .path = "print.zig",
736 }),
737 .macos => try case.files.append(.{
738 .src =
739 \\extern "c" fn write(usize, usize, usize) usize;
740 \\
741 \\pub fn print() void {
742 \\ _ = write(1, @ptrToInt("Hello, World!\n"), 14);
743 \\}
744 ,
745 .path = "print.zig",
746 }),
747 else => unreachable,
748 }
749 }
750
751 {
752 var case = ctx.exe("redundant comptime", target);
753 case.addError(
754 \\pub fn main() void {
755 \\ var a: comptime u32 = 0;
756 \\}
757 ,
758 &.{":2:12: error: redundant comptime keyword in already comptime scope"},
759 );
760 case.addError(
761 \\pub fn main() void {
762 \\ comptime {
763 \\ var a: u32 = comptime 0;
764 \\ }
765 \\}
766 ,
767 &.{":3:22: error: redundant comptime keyword in already comptime scope"},
768 );
769 }
770 {
771 var case = ctx.exe("try in comptime in struct in test", target);
772 case.addError(
773 \\test "@unionInit on union w/ tag but no fields" {
774 \\ const S = struct {
775 \\ comptime {
776 \\ try expect(false);
777 \\ }
778 \\ };
779 \\ _ = S;
780 \\}
781 ,
782 &.{":4:13: error: 'try' outside function scope"},
783 );
784 }
785 {
786 var case = ctx.exe("import private", target);
787 case.addError(
788 \\pub fn main() void {
789 \\ @import("print.zig").print();
790 \\}
791 ,
792 &.{
793 ":2:25: error: 'print' is not marked 'pub'",
794 "print.zig:2:1: note: declared here",
795 },
796 );
797 switch (target.getOsTag()) {
798 .linux => try case.files.append(.{
799 .src =
800 \\// dummy comment to make print be on line 2
801 \\fn print() void {
802 \\ asm volatile ("syscall"
803 \\ :
804 \\ : [number] "{rax}" (@as(usize, 1)),
805 \\ [arg1] "{rdi}" (@as(usize, 1)),
806 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
807 \\ [arg3] "{rdx}" (@as(usize, 14))
808 \\ : "rcx", "r11", "memory"
809 \\ );
810 \\ return;
811 \\}
812 ,
813 .path = "print.zig",
814 }),
815 .macos => try case.files.append(.{
816 .src =
817 \\extern "c" fn write(usize, usize, usize) usize;
818 \\fn print() void {
819 \\ _ = write(1, @ptrToInt("Hello, World!\n"), 14);
820 \\}
821 ,
822 .path = "print.zig",
823 }),
824 else => unreachable,
825 }
826 }
827
828 ctx.compileError("function redeclaration", target,
829 \\// dummy comment
830 \\fn entry() void {}
831 \\fn entry() void {}
832 \\
833 \\fn foo() void {
834 \\ var foo = 1234;
835 \\}
836 , &[_][]const u8{
837 ":3:1: error: redeclaration of 'entry'",
838 ":2:1: note: other declaration here",
839 ":6:9: error: local shadows declaration of 'foo'",
840 ":5:1: note: declared here",
841 });
842
843 ctx.compileError("returns in try", target,
844 \\pub fn main() !void {
845 \\ try a();
846 \\ try b();
847 \\}
848 \\
849 \\pub fn a() !void {
850 \\ defer try b();
851 \\}
852 \\pub fn b() !void {
853 \\ defer return a();
854 \\}
855 , &[_][]const u8{
856 ":7:8: error: 'try' not allowed inside defer expression",
857 ":10:8: error: cannot return from defer expression",
858 });
859
860 ctx.compileError("ambiguous references", target,
861 \\const T = struct {
862 \\ const T = struct {
863 \\ fn f() void {
864 \\ _ = T;
865 \\ }
866 \\ };
867 \\};
868 , &.{
869 ":4:17: error: ambiguous reference",
870 ":2:5: note: declared here",
871 ":1:1: note: also declared here",
872 });
873
874 ctx.compileError("inner func accessing outer var", target,
875 \\pub fn f() void {
876 \\ var bar: bool = true;
877 \\ const S = struct {
878 \\ fn baz() bool {
879 \\ return bar;
880 \\ }
881 \\ };
882 \\ _ = S;
883 \\}
884 , &.{
885 ":5:20: error: mutable 'bar' not accessible from here",
886 ":2:9: note: declared mutable here",
887 ":3:15: note: crosses namespace boundary here",
888 });
889
890 ctx.compileError("global variable redeclaration", target,
891 \\// dummy comment
892 \\var foo = false;
893 \\var foo = true;
894 , &[_][]const u8{
895 ":3:1: error: redeclaration of 'foo'",
896 ":2:1: note: other declaration here",
897 });
898
899 ctx.compileError("compileError", target,
900 \\export fn foo() void {
901 \\ @compileError("this is an error");
902 \\}
903 , &[_][]const u8{":2:3: error: this is an error"});
904
905 {
906 var case = ctx.exe("intToPtr", target);
907 case.addError(
908 \\pub fn main() void {
909 \\ _ = @intToPtr(*u8, 0);
910 \\}
911 , &[_][]const u8{
912 ":2:24: error: pointer type '*u8' does not allow address zero",
913 });
914 case.addError(
915 \\pub fn main() void {
916 \\ _ = @intToPtr(*u32, 2);
917 \\}
918 , &[_][]const u8{
919 ":2:25: error: pointer type '*u32' requires aligned address",
920 });
921 }
922
923 {
924 var case = ctx.obj("variable shadowing", target);
925 case.addError(
926 \\pub fn main() void {
927 \\ var i: u32 = 10;
928 \\ var i: u32 = 10;
929 \\}
930 , &[_][]const u8{
931 ":3:9: error: redeclaration of local variable 'i'",
932 ":2:9: note: previous declaration here",
933 });
934 case.addError(
935 \\var testing: i64 = 10;
936 \\pub fn main() void {
937 \\ var testing: i64 = 20;
938 \\}
939 , &[_][]const u8{
940 ":3:9: error: local shadows declaration of 'testing'",
941 ":1:1: note: declared here",
942 });
943 case.addError(
944 \\fn a() type {
945 \\ return struct {
946 \\ pub fn b() void {
947 \\ const c = 6;
948 \\ const c = 69;
949 \\ }
950 \\ };
951 \\}
952 , &[_][]const u8{
953 ":5:19: error: redeclaration of local constant 'c'",
954 ":4:19: note: previous declaration here",
955 });
956 case.addError(
957 \\pub fn main() void {
958 \\ var i = 0;
959 \\ for ("n") |_, i| {
960 \\ }
961 \\}
962 , &[_][]const u8{
963 ":3:19: error: redeclaration of local variable 'i'",
964 ":2:9: note: previous declaration here",
965 });
966 case.addError(
967 \\pub fn main() void {
968 \\ var i = 0;
969 \\ for ("n") |i| {
970 \\ }
971 \\}
972 , &[_][]const u8{
973 ":3:16: error: redeclaration of local variable 'i'",
974 ":2:9: note: previous declaration here",
975 });
976 case.addError(
977 \\pub fn main() void {
978 \\ var i = 0;
979 \\ while ("n") |i| {
980 \\ }
981 \\}
982 , &[_][]const u8{
983 ":3:18: error: redeclaration of local variable 'i'",
984 ":2:9: note: previous declaration here",
985 });
986 case.addError(
987 \\pub fn main() void {
988 \\ var i = 0;
989 \\ while ("n") |bruh| {
990 \\ _ = bruh;
991 \\ } else |i| {
992 \\
993 \\ }
994 \\}
995 , &[_][]const u8{
996 ":5:13: error: redeclaration of local variable 'i'",
997 ":2:9: note: previous declaration here",
998 });
999 case.addError(
1000 \\pub fn main() void {
1001 \\ var i = 0;
1002 \\ if (true) |i| {}
1003 \\}
1004 , &[_][]const u8{
1005 ":3:16: error: redeclaration of local variable 'i'",
1006 ":2:9: note: previous declaration here",
1007 });
1008 case.addError(
1009 \\pub fn main() void {
1010 \\ var i = 0;
1011 \\ if (true) |i| {} else |e| {}
1012 \\}
1013 , &[_][]const u8{
1014 ":3:16: error: redeclaration of local variable 'i'",
1015 ":2:9: note: previous declaration here",
1016 });
1017 case.addError(
1018 \\pub fn main() void {
1019 \\ var i = 0;
1020 \\ if (true) |_| {} else |i| {}
1021 \\}
1022 , &[_][]const u8{
1023 ":3:28: error: redeclaration of local variable 'i'",
1024 ":2:9: note: previous declaration here",
1025 });
1026 }
1027
1028 {
1029 // TODO make the test harness support checking the compile log output too
1030 var case = ctx.obj("@compileLog", target);
1031 // The other compile error prevents emission of a "found compile log" statement.
1032 case.addError(
1033 \\export fn _start() noreturn {
1034 \\ const b = true;
1035 \\ var f: u32 = 1;
1036 \\ @compileLog(b, 20, f, x);
1037 \\ @compileLog(1000);
1038 \\ var bruh: usize = true;
1039 \\ _ = bruh;
1040 \\ unreachable;
1041 \\}
1042 \\export fn other() void {
1043 \\ @compileLog(1234);
1044 \\}
1045 \\fn x() void {}
1046 , &[_][]const u8{
1047 ":6:23: error: expected usize, found bool",
1048 });
1049
1050 // Now only compile log statements remain. One per Decl.
1051 case.addError(
1052 \\export fn _start() noreturn {
1053 \\ const b = true;
1054 \\ var f: u32 = 1;
1055 \\ @compileLog(b, 20, f, x);
1056 \\ @compileLog(1000);
1057 \\ unreachable;
1058 \\}
1059 \\export fn other() void {
1060 \\ @compileLog(1234);
1061 \\}
1062 \\fn x() void {}
1063 , &[_][]const u8{
1064 ":9:5: error: found compile log statement",
1065 ":4:5: note: also here",
1066 });
1067 }
1068
1069 {
1070 var case = ctx.obj("extern variable has no type", target);
1071 case.addError(
1072 \\comptime {
1073 \\ const x = foo + foo;
1074 \\ _ = x;
1075 \\}
1076 \\extern var foo: i32;
1077 , &[_][]const u8{":2:15: error: unable to resolve comptime value"});
1078 case.addError(
1079 \\export fn entry() void {
1080 \\ _ = foo;
1081 \\}
1082 \\extern var foo;
1083 , &[_][]const u8{":4:8: error: unable to infer variable type"});
1084 }
1085
1086 {
1087 var case = ctx.exe("break/continue", target);
1088
1089 // Break out of loop
1090 case.addCompareOutput(
1091 \\pub fn main() void {
1092 \\ while (true) {
1093 \\ break;
1094 \\ }
1095 \\}
1096 ,
1097 "",
1098 );
1099 case.addCompareOutput(
1100 \\pub fn main() void {
1101 \\ foo: while (true) {
1102 \\ break :foo;
1103 \\ }
1104 \\}
1105 ,
1106 "",
1107 );
1108
1109 // Continue in loop
1110 case.addCompareOutput(
1111 \\pub fn main() void {
1112 \\ var i: u64 = 0;
1113 \\ while (true) : (i+=1) {
1114 \\ if (i == 4) return;
1115 \\ continue;
1116 \\ }
1117 \\}
1118 ,
1119 "",
1120 );
1121 case.addCompareOutput(
1122 \\pub fn main() void {
1123 \\ var i: u64 = 0;
1124 \\ foo: while (true) : (i+=1) {
1125 \\ if (i == 4) return;
1126 \\ continue :foo;
1127 \\ }
1128 \\}
1129 ,
1130 "",
1131 );
1132 }
1133
1134 {
1135 var case = ctx.exe("unused labels", target);
1136 case.addError(
1137 \\comptime {
1138 \\ foo: {}
1139 \\}
1140 , &[_][]const u8{":2:5: error: unused block label"});
1141 case.addError(
1142 \\comptime {
1143 \\ foo: while (true) {}
1144 \\}
1145 , &[_][]const u8{":2:5: error: unused while loop label"});
1146 case.addError(
1147 \\comptime {
1148 \\ foo: for ("foo") |_| {}
1149 \\}
1150 , &[_][]const u8{":2:5: error: unused for loop label"});
1151 case.addError(
1152 \\comptime {
1153 \\ blk: {blk: {}}
1154 \\}
1155 , &[_][]const u8{
1156 ":2:11: error: redefinition of label 'blk'",
1157 ":2:5: note: previous definition here",
1158 });
1159 }
1160
1161 {
1162 var case = ctx.exe("bad inferred variable type", target);
1163 case.addError(
1164 \\pub fn main() void {
1165 \\ var x = null;
1166 \\ _ = x;
1167 \\}
1168 , &[_][]const u8{
1169 ":2:9: error: variable of type '@TypeOf(null)' must be const or comptime",
1170 });
1171 }
1172
1173 {
1174 var case = ctx.exe("compile error in inline fn call fixed", target);
1175 case.addError(
1176 \\pub fn main() void {
1177 \\ var x: usize = 3;
1178 \\ const y = add(10, 2, x);
1179 \\ if (y - 6 != 0) unreachable;
1180 \\}
1181 \\
1182 \\fn add(a: usize, b: usize, c: usize) callconv(.Inline) usize {
1183 \\ if (a == 10) @compileError("bad");
1184 \\ return a + b + c;
1185 \\}
1186 , &[_][]const u8{
1187 ":8:18: error: bad",
1188 ":3:18: note: called from here",
1189 });
1190
1191 case.addCompareOutput(
1192 \\pub fn main() void {
1193 \\ var x: usize = 3;
1194 \\ const y = add(1, 2, x);
1195 \\ if (y - 6 != 0) unreachable;
1196 \\}
1197 \\
1198 \\fn add(a: usize, b: usize, c: usize) callconv(.Inline) usize {
1199 \\ if (a == 10) @compileError("bad");
1200 \\ return a + b + c;
1201 \\}
1202 ,
1203 "",
1204 );
1205 }
1206 {
1207 var case = ctx.exe("recursive inline function", target);
1208 case.addCompareOutput(
1209 \\pub fn main() void {
1210 \\ const y = fibonacci(7);
1211 \\ if (y - 21 != 0) unreachable;
1212 \\}
1213 \\
1214 \\fn fibonacci(n: usize) callconv(.Inline) usize {
1215 \\ if (n <= 2) return n;
1216 \\ return fibonacci(n - 2) + fibonacci(n - 1);
1217 \\}
1218 ,
1219 "",
1220 );
1221 // This additionally tests that the compile error reports the correct source location.
1222 // Without storing source locations relative to the owner decl, the compile error
1223 // here would be off by 2 bytes (from the "7" -> "999").
1224 case.addError(
1225 \\pub fn main() void {
1226 \\ const y = fibonacci(999);
1227 \\ if (y - 21 != 0) unreachable;
1228 \\}
1229 \\
1230 \\fn fibonacci(n: usize) callconv(.Inline) usize {
1231 \\ if (n <= 2) return n;
1232 \\ return fibonacci(n - 2) + fibonacci(n - 1);
1233 \\}
1234 , &[_][]const u8{":8:21: error: evaluation exceeded 1000 backwards branches"});
1235 }
1236 {
1237 var case = ctx.exe("orelse at comptime", target);
1238 case.addCompareOutput(
1239 \\pub fn main() void {
1240 \\ const i: ?u64 = 0;
1241 \\ const result = i orelse 5;
1242 \\ assert(result == 0);
1243 \\}
1244 \\fn assert(b: bool) void {
1245 \\ if (!b) unreachable;
1246 \\}
1247 ,
1248 "",
1249 );
1250 case.addCompareOutput(
1251 \\pub fn main() void {
1252 \\ const i: ?u64 = null;
1253 \\ const result = i orelse 5;
1254 \\ assert(result == 5);
1255 \\}
1256 \\fn assert(b: bool) void {
1257 \\ if (!b) unreachable;
1258 \\}
1259 ,
1260 "",
1261 );
1262 }
1263
1264 {
1265 var case = ctx.exe("passing u0 to function", target);
1266 case.addCompareOutput(
1267 \\pub fn main() void {
1268 \\ doNothing(0);
1269 \\}
1270 \\fn doNothing(arg: u0) void {
1271 \\ _ = arg;
1272 \\}
1273 ,
1274 "",
1275 );
1276 }
1277
1278 {
1279 var case = ctx.exe("catch at comptime", target);
1280 case.addCompareOutput(
1281 \\pub fn main() void {
1282 \\ const i: anyerror!u64 = 0;
1283 \\ const caught = i catch 5;
1284 \\ assert(caught == 0);
1285 \\}
1286 \\fn assert(b: bool) void {
1287 \\ if (!b) unreachable;
1288 \\}
1289 ,
1290 "",
1291 );
1292
1293 case.addCompareOutput(
1294 \\pub fn main() void {
1295 \\ const i: anyerror!u64 = error.B;
1296 \\ const caught = i catch 5;
1297 \\ assert(caught == 5);
1298 \\}
1299 \\fn assert(b: bool) void {
1300 \\ if (!b) unreachable;
1301 \\}
1302 ,
1303 "",
1304 );
1305
1306 case.addCompareOutput(
1307 \\pub fn main() void {
1308 \\ const a: anyerror!comptime_int = 42;
1309 \\ const b: *const comptime_int = &(a catch unreachable);
1310 \\ assert(b.* == 42);
1311 \\}
1312 \\fn assert(b: bool) void {
1313 \\ if (!b) unreachable; // assertion failure
1314 \\}
1315 , "");
1316
1317 case.addCompareOutput(
1318 \\pub fn main() void {
1319 \\ const a: anyerror!u32 = error.B;
1320 \\ _ = &(a catch |err| assert(err == error.B));
1321 \\}
1322 \\fn assert(b: bool) void {
1323 \\ if (!b) unreachable;
1324 \\}
1325 , "");
1326
1327 case.addCompareOutput(
1328 \\pub fn main() void {
1329 \\ const a: anyerror!u32 = error.Bar;
1330 \\ a catch |err| assert(err == error.Bar);
1331 \\}
1332 \\fn assert(b: bool) void {
1333 \\ if (!b) unreachable;
1334 \\}
1335 , "");
1336 }
1337
1338 {
1339 var case = ctx.exe("runtime bitwise and", target);
1340
1341 case.addCompareOutput(
1342 \\pub fn main() void {
1343 \\ var i: u32 = 10;
1344 \\ var j: u32 = 11;
1345 \\ assert(i & 1 == 0);
1346 \\ assert(j & 1 == 1);
1347 \\ var m1: u32 = 0b1111;
1348 \\ var m2: u32 = 0b0000;
1349 \\ assert(m1 & 0b1010 == 0b1010);
1350 \\ assert(m2 & 0b1010 == 0b0000);
1351 \\}
1352 \\fn assert(b: bool) void {
1353 \\ if (!b) unreachable;
1354 \\}
1355 ,
1356 "",
1357 );
1358 }
1359
1360 {
1361 var case = ctx.exe("runtime bitwise or", target);
1362
1363 case.addCompareOutput(
1364 \\pub fn main() void {
1365 \\ var i: u32 = 10;
1366 \\ var j: u32 = 11;
1367 \\ assert(i | 1 == 11);
1368 \\ assert(j | 1 == 11);
1369 \\ var m1: u32 = 0b1111;
1370 \\ var m2: u32 = 0b0000;
1371 \\ assert(m1 | 0b1010 == 0b1111);
1372 \\ assert(m2 | 0b1010 == 0b1010);
1373 \\}
1374 \\fn assert(b: bool) void {
1375 \\ if (!b) unreachable;
1376 \\}
1377 ,
1378 "",
1379 );
1380 }
1381
1382 {
1383 var case = ctx.exe("merge error sets", target);
1384
1385 case.addCompareOutput(
1386 \\pub fn main() void {
1387 \\ const E = error{ A, B, D } || error { A, B, C };
1388 \\ E.A catch {};
1389 \\ E.B catch {};
1390 \\ E.C catch {};
1391 \\ E.D catch {};
1392 \\ const E2 = error { X, Y } || @TypeOf(error.Z);
1393 \\ E2.X catch {};
1394 \\ E2.Y catch {};
1395 \\ E2.Z catch {};
1396 \\ assert(anyerror || error { Z } == anyerror);
1397 \\}
1398 \\fn assert(b: bool) void {
1399 \\ if (!b) unreachable;
1400 \\}
1401 ,
1402 "",
1403 );
1404 case.addError(
1405 \\pub fn main() void {
1406 \\ const z = true || false;
1407 \\ _ = z;
1408 \\}
1409 , &.{
1410 ":2:15: error: expected error set type, found 'bool'",
1411 ":2:20: note: '||' merges error sets; 'or' performs boolean OR",
1412 });
1413 }
1414
1415 {
1416 var case = ctx.exe("comptime var", target);
1417
1418 case.addError(
1419 \\pub fn main() void {
1420 \\ var a: u32 = 0;
1421 \\ comptime var b: u32 = 0;
1422 \\ if (a == 0) b = 3;
1423 \\}
1424 , &.{
1425 ":4:21: error: store to comptime variable depends on runtime condition",
1426 ":4:11: note: runtime condition here",
1427 });
1428
1429 case.addError(
1430 \\pub fn main() void {
1431 \\ var a: u32 = 0;
1432 \\ comptime var b: u32 = 0;
1433 \\ switch (a) {
1434 \\ 0 => {},
1435 \\ else => b = 3,
1436 \\ }
1437 \\}
1438 , &.{
1439 ":6:21: error: store to comptime variable depends on runtime condition",
1440 ":4:13: note: runtime condition here",
1441 });
1442
1443 switch (target.getOsTag()) {
1444 .linux => case.addCompareOutput(
1445 \\pub fn main() void {
1446 \\ comptime var len: u32 = 5;
1447 \\ print(len);
1448 \\ len += 9;
1449 \\ print(len);
1450 \\}
1451 \\
1452 \\fn print(len: usize) void {
1453 \\ asm volatile ("syscall"
1454 \\ :
1455 \\ : [number] "{rax}" (1),
1456 \\ [arg1] "{rdi}" (1),
1457 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
1458 \\ [arg3] "{rdx}" (len)
1459 \\ : "rcx", "r11", "memory"
1460 \\ );
1461 \\ return;
1462 \\}
1463 , "HelloHello, World!\n"),
1464 .macos => case.addCompareOutput(
1465 \\extern "c" fn write(usize, usize, usize) usize;
1466 \\
1467 \\pub fn main() void {
1468 \\ comptime var len: u32 = 5;
1469 \\ print(len);
1470 \\ len += 9;
1471 \\ print(len);
1472 \\}
1473 \\
1474 \\fn print(len: usize) void {
1475 \\ _ = write(1, @ptrToInt("Hello, World!\n"), len);
1476 \\}
1477 , "HelloHello, World!\n"),
1478
1479 else => unreachable,
1480 }
1481
1482 case.addError(
1483 \\comptime {
1484 \\ var x: i32 = 1;
1485 \\ x += 1;
1486 \\ if (x != 1) unreachable;
1487 \\}
1488 \\pub fn main() void {}
1489 , &.{":4:17: error: unable to resolve comptime value"});
1490
1491 case.addError(
1492 \\pub fn main() void {
1493 \\ comptime var i: u64 = 0;
1494 \\ while (i < 5) : (i += 1) {}
1495 \\}
1496 , &.{
1497 ":3:24: error: cannot store to comptime variable in non-inline loop",
1498 ":3:5: note: non-inline loop here",
1499 });
1500
1501 case.addCompareOutput(
1502 \\pub fn main() void {
1503 \\ var a: u32 = 0;
1504 \\ if (a == 0) {
1505 \\ comptime var b: u32 = 0;
1506 \\ b = 1;
1507 \\ }
1508 \\}
1509 \\comptime {
1510 \\ var x: i32 = 1;
1511 \\ x += 1;
1512 \\ if (x != 2) unreachable;
1513 \\}
1514 , "");
1515
1516 switch (target.getOsTag()) {
1517 .linux => case.addCompareOutput(
1518 \\pub fn main() void {
1519 \\ comptime var i: u64 = 2;
1520 \\ inline while (i < 6) : (i+=1) {
1521 \\ print(i);
1522 \\ }
1523 \\}
1524 \\fn print(len: usize) void {
1525 \\ asm volatile ("syscall"
1526 \\ :
1527 \\ : [number] "{rax}" (1),
1528 \\ [arg1] "{rdi}" (1),
1529 \\ [arg2] "{rsi}" (@ptrToInt("Hello")),
1530 \\ [arg3] "{rdx}" (len)
1531 \\ : "rcx", "r11", "memory"
1532 \\ );
1533 \\ return;
1534 \\}
1535 , "HeHelHellHello"),
1536 .macos => case.addCompareOutput(
1537 \\extern "c" fn write(usize, usize, usize) usize;
1538 \\
1539 \\pub fn main() void {
1540 \\ comptime var i: u64 = 2;
1541 \\ inline while (i < 6) : (i+=1) {
1542 \\ print(i);
1543 \\ }
1544 \\}
1545 \\fn print(len: usize) void {
1546 \\ _ = write(1, @ptrToInt("Hello"), len);
1547 \\}
1548 , "HeHelHellHello"),
1549 else => unreachable,
1550 }
1551 }
1552
1553 {
1554 var case = ctx.exe("double ampersand", target);
1555
1556 case.addError(
1557 \\pub const a = if (true && false) 1 else 2;
1558 , &[_][]const u8{":1:24: error: ambiguous use of '&&'; use 'and' for logical AND, or change whitespace to ' & &' for bitwise AND"});
1559
1560 case.addError(
1561 \\pub fn main() void {
1562 \\ const a = true;
1563 \\ const b = false;
1564 \\ _ = a & &b;
1565 \\}
1566 , &[_][]const u8{
1567 ":4:11: error: incompatible types: 'bool' and '*const bool'",
1568 ":4:9: note: type 'bool' here",
1569 ":4:13: note: type '*const bool' here",
1570 });
1571
1572 case.addCompareOutput(
1573 \\pub fn main() void {
1574 \\ const b: u8 = 1;
1575 \\ _ = &&b;
1576 \\}
1577 , "");
1578 }
1579
1580 {
1581 var case = ctx.exe("setting an address space on a local variable", target);
1582 case.addError(
1583 \\export fn entry() i32 {
1584 \\ var foo: i32 addrspace(".general") = 1234;
1585 \\ return foo;
1586 \\}
1587 , &[_][]const u8{
1588 ":2:28: error: cannot set address space of local variable 'foo'",
1589 });
1590 }
1591
1592 {
1593 var case = ctx.exe("saving vars of different ABI size to stack", target);
1594
1595 case.addCompareOutput(
1596 \\pub fn main() void {
1597 \\ assert(callMe(2) == 24);
1598 \\}
1599 \\
1600 \\fn callMe(a: u8) u8 {
1601 \\ var b: u8 = a + 10;
1602 \\ const c = 2 * b;
1603 \\ return c;
1604 \\}
1605 \\
1606 \\pub fn assert(ok: bool) void {
1607 \\ if (!ok) unreachable; // assertion failure
1608 \\}
1609 ,
1610 "",
1611 );
1612
1613 case.addCompareOutput(
1614 \\pub fn main() void {
1615 \\ assert(callMe(2) == 24);
1616 \\}
1617 \\
1618 \\fn callMe(a: u16) u16 {
1619 \\ var b: u16 = a + 10;
1620 \\ const c = 2 * b;
1621 \\ return c;
1622 \\}
1623 \\
1624 \\pub fn assert(ok: bool) void {
1625 \\ if (!ok) unreachable; // assertion failure
1626 \\}
1627 ,
1628 "",
1629 );
1630
1631 case.addCompareOutput(
1632 \\pub fn main() void {
1633 \\ assert(callMe(2) == 24);
1634 \\}
1635 \\
1636 \\fn callMe(a: u32) u32 {
1637 \\ var b: u32 = a + 10;
1638 \\ const c = 2 * b;
1639 \\ return c;
1640 \\}
1641 \\
1642 \\pub fn assert(ok: bool) void {
1643 \\ if (!ok) unreachable; // assertion failure
1644 \\}
1645 ,
1646 "",
1647 );
1648 }
1649 {
1650 var case = ctx.exe("issue 7187: miscompilation with bool return type", target);
1651 case.addCompareOutput(
1652 \\pub fn main() void {
1653 \\ var x: usize = 1;
1654 \\ var y: bool = getFalse();
1655 \\ _ = y;
1656 \\
1657 \\ assert(x == 1);
1658 \\}
1659 \\
1660 \\fn getFalse() bool {
1661 \\ return false;
1662 \\}
1663 \\
1664 \\fn assert(ok: bool) void {
1665 \\ if (!ok) unreachable;
1666 \\}
1667 , "");
1668 }
1669
1670 {
1671 var case = ctx.exe("load-store via pointer deref", target);
1672 case.addCompareOutput(
1673 \\pub fn main() void {
1674 \\ var x: u32 = undefined;
1675 \\ set(&x);
1676 \\ assert(x == 123);
1677 \\}
1678 \\
1679 \\fn set(x: *u32) void {
1680 \\ x.* = 123;
1681 \\}
1682 \\
1683 \\fn assert(ok: bool) void {
1684 \\ if (!ok) unreachable;
1685 \\}
1686 , "");
1687 case.addCompareOutput(
1688 \\pub fn main() void {
1689 \\ var x: u16 = undefined;
1690 \\ set(&x);
1691 \\ assert(x == 123);
1692 \\}
1693 \\
1694 \\fn set(x: *u16) void {
1695 \\ x.* = 123;
1696 \\}
1697 \\
1698 \\fn assert(ok: bool) void {
1699 \\ if (!ok) unreachable;
1700 \\}
1701 , "");
1702 case.addCompareOutput(
1703 \\pub fn main() void {
1704 \\ var x: u8 = undefined;
1705 \\ set(&x);
1706 \\ assert(x == 123);
1707 \\}
1708 \\
1709 \\fn set(x: *u8) void {
1710 \\ x.* = 123;
1711 \\}
1712 \\
1713 \\fn assert(ok: bool) void {
1714 \\ if (!ok) unreachable;
1715 \\}
1716 , "");
1717 }
1718
1719 {
1720 var case = ctx.exe("optional payload", target);
1721 case.addCompareOutput(
1722 \\pub fn main() void {
1723 \\ var x: u32 = undefined;
1724 \\ const maybe_x = byPtr(&x);
1725 \\ assert(maybe_x != null);
1726 \\ maybe_x.?.* = 123;
1727 \\ assert(x == 123);
1728 \\}
1729 \\
1730 \\fn byPtr(x: *u32) ?*u32 {
1731 \\ return x;
1732 \\}
1733 \\
1734 \\fn assert(ok: bool) void {
1735 \\ if (!ok) unreachable;
1736 \\}
1737 , "");
1738 case.addCompareOutput(
1739 \\pub fn main() void {
1740 \\ var x: u32 = undefined;
1741 \\ const maybe_x = byPtr(&x);
1742 \\ assert(maybe_x == null);
1743 \\}
1744 \\
1745 \\fn byPtr(x: *u32) ?*u32 {
1746 \\ _ = x;
1747 \\ return null;
1748 \\}
1749 \\
1750 \\fn assert(ok: bool) void {
1751 \\ if (!ok) unreachable;
1752 \\}
1753 , "");
1754 case.addCompareOutput(
1755 \\pub fn main() void {
1756 \\ var x: u8 = undefined;
1757 \\ const maybe_x = byPtr(&x);
1758 \\ assert(maybe_x != null);
1759 \\ maybe_x.?.* = 255;
1760 \\ assert(x == 255);
1761 \\}
1762 \\
1763 \\fn byPtr(x: *u8) ?*u8 {
1764 \\ return x;
1765 \\}
1766 \\
1767 \\fn assert(ok: bool) void {
1768 \\ if (!ok) unreachable;
1769 \\}
1770 , "");
1771 case.addCompareOutput(
1772 \\pub fn main() void {
1773 \\ var x: i8 = undefined;
1774 \\ const maybe_x = byPtr(&x);
1775 \\ assert(maybe_x != null);
1776 \\ maybe_x.?.* = -1;
1777 \\ assert(x == -1);
1778 \\}
1779 \\
1780 \\fn byPtr(x: *i8) ?*i8 {
1781 \\ return x;
1782 \\}
1783 \\
1784 \\fn assert(ok: bool) void {
1785 \\ if (!ok) unreachable;
1786 \\}
1787 , "");
1788 }
1789
1790 {
1791 var case = ctx.exe("unwrap error union - simple errors", target);
1792 case.addCompareOutput(
1793 \\pub fn main() void {
1794 \\ maybeErr() catch unreachable;
1795 \\}
1796 \\
1797 \\fn maybeErr() !void {
1798 \\ return;
1799 \\}
1800 , "");
1801 case.addCompareOutput(
1802 \\pub fn main() void {
1803 \\ maybeErr() catch return;
1804 \\ unreachable;
1805 \\}
1806 \\
1807 \\fn maybeErr() !void {
1808 \\ return error.NoWay;
1809 \\}
1810 , "");
1811 }
1812
1813 {
1814 var case = ctx.exe("access slice element by index - slice_elem_val", target);
1815 case.addCompareOutput(
1816 \\var array = [_]usize{ 0, 42, 123, 34 };
1817 \\var slice: []const usize = &array;
1818 \\
1819 \\pub fn main() void {
1820 \\ assert(slice[0] == 0);
1821 \\ assert(slice[1] == 42);
1822 \\ assert(slice[2] == 123);
1823 \\ assert(slice[3] == 34);
1824 \\}
1825 \\
1826 \\fn assert(ok: bool) void {
1827 \\ if (!ok) unreachable;
1828 \\}
1829 , "");
1830 }
1831
1832 {
1833 var case = ctx.exe("lower unnamed constants - structs", target);
1834 case.addCompareOutput(
1835 \\const Foo = struct {
1836 \\ a: u8,
1837 \\ b: u32,
1838 \\
1839 \\ fn first(self: *Foo) u8 {
1840 \\ return self.a;
1841 \\ }
1842 \\
1843 \\ fn second(self: *Foo) u32 {
1844 \\ return self.b;
1845 \\ }
1846 \\};
1847 \\
1848 \\pub fn main() void {
1849 \\ var foo = Foo{ .a = 1, .b = 5 };
1850 \\ assert(foo.first() == 1);
1851 \\ assert(foo.second() == 5);
1852 \\}
1853 \\
1854 \\fn assert(ok: bool) void {
1855 \\ if (!ok) unreachable;
1856 \\}
1857 , "");
1858
1859 case.addCompareOutput(
1860 \\const Foo = struct {
1861 \\ a: u8,
1862 \\ b: u32,
1863 \\
1864 \\ fn first(self: *Foo) u8 {
1865 \\ return self.a;
1866 \\ }
1867 \\
1868 \\ fn second(self: *Foo) u32 {
1869 \\ return self.b;
1870 \\ }
1871 \\};
1872 \\
1873 \\pub fn main() void {
1874 \\ var foo = Foo{ .a = 1, .b = 5 };
1875 \\ assert(foo.first() == 1);
1876 \\ assert(foo.second() == 5);
1877 \\
1878 \\ foo.a = 10;
1879 \\ foo.b = 255;
1880 \\
1881 \\ assert(foo.first() == 10);
1882 \\ assert(foo.second() == 255);
1883 \\
1884 \\ var foo2 = Foo{ .a = 15, .b = 255 };
1885 \\ assert(foo2.first() == 15);
1886 \\ assert(foo2.second() == 255);
1887 \\}
1888 \\
1889 \\fn assert(ok: bool) void {
1890 \\ if (!ok) unreachable;
1891 \\}
1892 , "");
1893
1894 case.addCompareOutput(
1895 \\const Foo = struct {
1896 \\ a: u8,
1897 \\ b: u32,
1898 \\
1899 \\ fn first(self: *Foo) u8 {
1900 \\ return self.a;
1901 \\ }
1902 \\
1903 \\ fn second(self: *Foo) u32 {
1904 \\ return self.b;
1905 \\ }
1906 \\};
1907 \\
1908 \\pub fn main() void {
1909 \\ var foo2 = Foo{ .a = 15, .b = 255 };
1910 \\ assert(foo2.first() == 15);
1911 \\ assert(foo2.second() == 255);
1912 \\}
1913 \\
1914 \\fn assert(ok: bool) void {
1915 \\ if (!ok) unreachable;
1916 \\}
1917 , "");
1918 }
1919 }
1920}
1921
1922fn addLinuxTestCases(ctx: *TestContext) !void {
1923 // Linux tests
1924 {
1925 var case = ctx.exe("hello world with updates", linux_x64);
1926
1927 case.addError("", &[_][]const u8{
1928 ":109:9: error: struct 'tmp.tmp' has no member named 'main'",
1929 });
1930
1931 // Incorrect return type
1932 case.addError(
1933 \\pub export fn _start() noreturn {
1934 \\}
1935 , &[_][]const u8{":2:1: error: expected noreturn, found void"});
1936
1937 // Regular old hello world
1938 case.addCompareOutput(
1939 \\pub export fn _start() noreturn {
1940 \\ print();
1941 \\
1942 \\ exit();
1943 \\}
1944 \\
1945 \\fn print() void {
1946 \\ asm volatile ("syscall"
1947 \\ :
1948 \\ : [number] "{rax}" (1),
1949 \\ [arg1] "{rdi}" (1),
1950 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
1951 \\ [arg3] "{rdx}" (14)
1952 \\ : "rcx", "r11", "memory"
1953 \\ );
1954 \\ return;
1955 \\}
1956 \\
1957 \\fn exit() noreturn {
1958 \\ asm volatile ("syscall"
1959 \\ :
1960 \\ : [number] "{rax}" (231),
1961 \\ [arg1] "{rdi}" (0)
1962 \\ : "rcx", "r11", "memory"
1963 \\ );
1964 \\ unreachable;
1965 \\}
1966 ,
1967 "Hello, World!\n",
1968 );
1969
1970 // Convert to pub fn main
1971 case.addCompareOutput(22 case.addCompareOutput(
1972 \\pub fn main() void {23 \\pub fn main() void {
1973 \\ print();24 \\ @import("print.zig").print();
1974 \\}
1975 \\
1976 \\fn print() void {
1977 \\ asm volatile ("syscall"
1978 \\ :
1979 \\ : [number] "{rax}" (1),
1980 \\ [arg1] "{rdi}" (1),
1981 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
1982 \\ [arg3] "{rdx}" (14)
1983 \\ : "rcx", "r11", "memory"
1984 \\ );
1985 \\ return;
1986 \\}25 \\}
1987 ,26 ,
1988 "Hello, World!\n",27 "Hello, World!\n",
1989 );28 );
199029 switch (target.getOsTag()) {
1991 // Now change the message only30 .linux => try case.files.append(.{
1992 case.addCompareOutput(31 .src =
1993 \\pub fn main() void {32 \\pub fn print() void {
1994 \\ print();33 \\ asm volatile ("syscall"
1995 \\}34 \\ :
1996 \\35 \\ : [number] "{rax}" (@as(usize, 1)),
1997 \\fn print() void {36 \\ [arg1] "{rdi}" (@as(usize, 1)),
1998 \\ asm volatile ("syscall"37 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
1999 \\ :38 \\ [arg3] "{rdx}" (@as(usize, 14))
2000 \\ : [number] "{rax}" (1),39 \\ : "rcx", "r11", "memory"
2001 \\ [arg1] "{rdi}" (1),40 \\ );
2002 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),41 \\ return;
2003 \\ [arg3] "{rdx}" (104)42 \\}
2004 \\ : "rcx", "r11", "memory"43 ,
2005 \\ );44 .path = "print.zig",
2006 \\ return;45 }),
2007 \\}46 .macos => try case.files.append(.{
2008 ,47 .src =
2009 "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",48 \\extern "c" fn write(usize, usize, usize) usize;
2010 );49 \\
2011 // Now we print it twice.50 \\pub fn print() void {
2012 case.addCompareOutput(51 \\ _ = write(1, @ptrToInt("Hello, World!\n"), 14);
2013 \\pub fn main() void {52 \\}
2014 \\ print();53 ,
2015 \\ print();54 .path = "print.zig",
2016 \\}55 }),
2017 \\56 else => unreachable,
2018 \\fn print() void {57 }
2019 \\ asm volatile ("syscall"
2020 \\ :
2021 \\ : [number] "{rax}" (1),
2022 \\ [arg1] "{rdi}" (1),
2023 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
2024 \\ [arg3] "{rdx}" (104)
2025 \\ : "rcx", "r11", "memory"
2026 \\ );
2027 \\ return;
2028 \\}
2029 ,
2030 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
2031 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
2032 \\
2033 );
2034 }
2035
2036 {
2037 var case = ctx.exe("adding numbers at comptime", linux_x64);
2038 case.addCompareOutput(
2039 \\pub export fn _start() noreturn {
2040 \\ asm volatile ("syscall"
2041 \\ :
2042 \\ : [number] "{rax}" (1),
2043 \\ [arg1] "{rdi}" (1),
2044 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
2045 \\ [arg3] "{rdx}" (10 + 4)
2046 \\ : "rcx", "r11", "memory"
2047 \\ );
2048 \\ asm volatile ("syscall"
2049 \\ :
2050 \\ : [number] "{rax}" (@as(usize, 230) + @as(usize, 1)),
2051 \\ [arg1] "{rdi}" (0)
2052 \\ : "rcx", "r11", "memory"
2053 \\ );
2054 \\ unreachable;
2055 \\}
2056 ,
2057 "Hello, World!\n",
2058 );
2059 }
2060
2061 {
2062 var case = ctx.exe("only 1 function and it gets updated", linux_x64);
2063 case.addCompareOutput(
2064 \\pub export fn _start() noreturn {
2065 \\ asm volatile ("syscall"
2066 \\ :
2067 \\ : [number] "{rax}" (60), // exit
2068 \\ [arg1] "{rdi}" (0)
2069 \\ : "rcx", "r11", "memory"
2070 \\ );
2071 \\ unreachable;
2072 \\}
2073 ,
2074 "",
2075 );
2076 case.addCompareOutput(
2077 \\pub export fn _start() noreturn {
2078 \\ asm volatile ("syscall"
2079 \\ :
2080 \\ : [number] "{rax}" (231), // exit_group
2081 \\ [arg1] "{rdi}" (0)
2082 \\ : "rcx", "r11", "memory"
2083 \\ );
2084 \\ unreachable;
2085 \\}
2086 ,
2087 "",
2088 );
2089 }
2090 {
2091 var case = ctx.exe("inline assembly", linux_x64);
2092
2093 case.addError(
2094 \\pub fn main() void {
2095 \\ const number = 1234;
2096 \\ const x = asm volatile ("syscall"
2097 \\ : [o] "{rax}" (-> number)
2098 \\ : [number] "{rax}" (231),
2099 \\ [arg1] "{rdi}" (60)
2100 \\ : "rcx", "r11", "memory"
2101 \\ );
2102 \\ _ = x;
2103 \\}
2104 , &[_][]const u8{":4:27: error: expected type, found comptime_int"});
2105 case.addError(
2106 \\const S = struct {
2107 \\ comptime {
2108 \\ asm volatile (
2109 \\ \\zig_moment:
2110 \\ \\syscall
2111 \\ );
2112 \\ }
2113 \\};
2114 \\pub fn main() void {
2115 \\ _ = S;
2116 \\}
2117 , &.{":3:13: error: volatile is meaningless on global assembly"});
2118 case.addError(
2119 \\pub fn main() void {
2120 \\ var bruh: u32 = 1;
2121 \\ asm (""
2122 \\ :
2123 \\ : [bruh] "{rax}" (4)
2124 \\ : "memory"
2125 \\ );
2126 \\}
2127 , &.{":3:5: error: assembly expression with no output must be marked volatile"});
2128 case.addError(
2129 \\pub fn main() void {}
2130 \\comptime {
2131 \\ asm (""
2132 \\ :
2133 \\ : [bruh] "{rax}" (4)
2134 \\ : "memory"
2135 \\ );
2136 \\}
2137 , &.{":3:5: error: global assembly cannot have inputs, outputs, or clobbers"});
2138 }
2139
2140 {
2141 var case = ctx.exe("issue 10138: callee preserved regs working", linux_x64);
2142 case.addCompareOutput(
2143 \\pub fn main() void {
2144 \\ const fd = open();
2145 \\ _ = write(fd, "a", 1);
2146 \\ _ = close(fd);
2147 \\}
2148 \\
2149 \\fn open() usize {
2150 \\ return 42;
2151 \\}
2152 \\
2153 \\fn write(fd: usize, a: [*]const u8, len: usize) usize {
2154 \\ return syscall4(.WRITE, fd, @ptrToInt(a), len);
2155 \\}
2156 \\
2157 \\fn syscall4(n: enum { WRITE }, a: usize, b: usize, c: usize) usize {
2158 \\ _ = n;
2159 \\ _ = a;
2160 \\ _ = b;
2161 \\ _ = c;
2162 \\ return 23;
2163 \\}
2164 \\
2165 \\fn close(fd: usize) usize {
2166 \\ if (fd != 42)
2167 \\ unreachable;
2168 \\ return 0;
2169 \\}
2170 , "");
2171 }
2172}
2173
2174fn addMacOsTestCases(ctx: *TestContext) !void {
2175 // macOS tests
2176 {
2177 var case = ctx.exe("darwin hello world with updates", macos_x64);
2178 case.addError("", &[_][]const u8{
2179 ":109:9: error: struct 'tmp.tmp' has no member named 'main'",
2180 });
2181
2182 // Incorrect return type
2183 case.addError(
2184 \\pub export fn main() noreturn {
2185 \\}
2186 , &[_][]const u8{
2187 ":2:1: error: expected noreturn, found void",
2188 });
2189
2190 // Regular old hello world
2191 case.addCompareOutput(
2192 \\extern "c" fn write(usize, usize, usize) usize;
2193 \\extern "c" fn exit(usize) noreturn;
2194 \\
2195 \\pub export fn main() noreturn {
2196 \\ print();
2197 \\
2198 \\ exit(0);
2199 \\}
2200 \\
2201 \\fn print() void {
2202 \\ const msg = @ptrToInt("Hello, World!\n");
2203 \\ const len = 14;
2204 \\ _ = write(1, msg, len);
2205 \\}
2206 ,
2207 "Hello, World!\n",
2208 );
2209
2210 // Now using start.zig without an explicit extern exit fn
2211 case.addCompareOutput(
2212 \\extern "c" fn write(usize, usize, usize) usize;
2213 \\
2214 \\pub fn main() void {
2215 \\ print();
2216 \\}
2217 \\
2218 \\fn print() void {
2219 \\ const msg = @ptrToInt("Hello, World!\n");
2220 \\ const len = 14;
2221 \\ _ = write(1, msg, len);
2222 \\}
2223 ,
2224 "Hello, World!\n",
2225 );
2226
2227 // Print it 4 times and force growth and realloc.
2228 case.addCompareOutput(
2229 \\extern "c" fn write(usize, usize, usize) usize;
2230 \\
2231 \\pub fn main() void {
2232 \\ print();
2233 \\ print();
2234 \\ print();
2235 \\ print();
2236 \\}
2237 \\
2238 \\fn print() void {
2239 \\ const msg = @ptrToInt("Hello, World!\n");
2240 \\ const len = 14;
2241 \\ _ = write(1, msg, len);
2242 \\}
2243 ,
2244 \\Hello, World!
2245 \\Hello, World!
2246 \\Hello, World!
2247 \\Hello, World!
2248 \\
2249 );
2250
2251 // Print it once, and change the message.
2252 case.addCompareOutput(
2253 \\extern "c" fn write(usize, usize, usize) usize;
2254 \\
2255 \\pub fn main() void {
2256 \\ print();
2257 \\}
2258 \\
2259 \\fn print() void {
2260 \\ const msg = @ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n");
2261 \\ const len = 104;
2262 \\ _ = write(1, msg, len);
2263 \\}
2264 ,
2265 "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
2266 );
2267
2268 // Now we print it twice.
2269 case.addCompareOutput(
2270 \\extern "c" fn write(usize, usize, usize) usize;
2271 \\
2272 \\pub fn main() void {
2273 \\ print();
2274 \\ print();
2275 \\}
2276 \\
2277 \\fn print() void {
2278 \\ const msg = @ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n");
2279 \\ const len = 104;
2280 \\ _ = write(1, msg, len);
2281 \\}
2282 ,
2283 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
2284 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
2285 \\
2286 );
2287 }58 }
2288}59}