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