| ... | @@ -16,2273 +16,44 @@ const all_targets: []const CrossTarget = &[_]CrossTarget{ | ... | @@ -16,2273 +16,44 @@ const all_targets: []const CrossTarget = &[_]CrossTarget{ |
| 16 | }; | 16 | }; |
| 17 | | 17 | |
| 18 | pub fn addCases(ctx: *TestContext) !void { | 18 | pub 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 | | | |
| 1922 | fn 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 | ); |
| 1990 | | 29 | switch (target.getOsTag()) { |
| 1991 | // Now change the message only | 30 | .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 | | | |
| 2174 | fn 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 | } |