1 /// Copyright: Copyright (c) 2017-2020 Andrey Penechko. 2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 3 /// Authors: Andrey Penechko. 4 module tests.passing; 5 6 import core.stdc.stdlib : malloc, free; 7 import std.stdio; 8 import tester; 9 10 Test[] passingTests() { return collectTests!(tests.passing)(); } 11 12 /// Used to force correct type of float literal, like `42.54f.force` 13 /// Without it, 42.54f will be store as dobule by the compiler 14 T force(T)(T t) { return t; } 15 16 extern(C) void external_print_i32_func(int par1) { 17 formattedWrite(testSink, "%s ", par1); 18 } 19 extern(C) void external_print_i64_func(long par1) { 20 formattedWrite(testSink, "%s ", par1); 21 } 22 extern(C) void external_print_string(Slice!char param) { 23 char[] slice = *cast(char[]*)¶m; 24 testSink.put(slice); 25 } 26 27 @TestInfo(&tester7) 28 immutable test7 = q{--- test7 29 i32 fib(i32 number) { 30 if (number < 1) return 0; 31 if (number < 3) return 1; 32 return fib(number-1) + fib(number-2); 33 } 34 }; 35 void tester7(ref TestContext ctx) { 36 auto fib = ctx.getFunctionPtr!(int, int)("fib"); 37 immutable int[] results = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 38 377, 610, 987, 1597, 2584, 4181, 6765]; 39 foreach(size_t i, int expected; results) 40 { 41 int res = fib(cast(int)i+1); 42 assert(res == expected, format("%s != %s", res, expected)); 43 } 44 } 45 46 47 @TestInfo() 48 immutable test9 = q{--- test9 49 i32 test(i32 number) { 50 i32 result; 51 if (1 == 1) 52 { 53 result = 1; 54 } 55 else 56 { 57 result = 0; 58 } 59 return result; 60 } 61 }; 62 63 64 @TestInfo(&tester8) 65 immutable test8 = q{--- test8 66 i32 sign(i32 number) { 67 i32 result; 68 if (number < 0) result = 0-1; 69 else if (number > 0) result = 1; 70 else result = 0; 71 return result; 72 } 73 }; 74 75 76 @TestInfo(&tester8) 77 immutable test8_1 = q{--- test8_1 78 i32 sign(i32 number) { 79 if (number < 0) return 0-1; 80 else if (number > 0) return 1; 81 else return 0; 82 } 83 }; 84 85 void tester8(ref TestContext ctx) { 86 auto sign = ctx.getFunctionPtr!(int, int)("sign"); 87 int res1 = sign(10); 88 int res2 = sign(0); 89 int res3 = sign(-10); 90 //writefln("sign(10) -> %s", res1); 91 //writefln("sign(0) -> %s", res2); 92 //writefln("sign(-10) -> %s", res3); 93 assert(res1 == 1); 94 assert(res2 == 0); 95 assert(res3 == -1); 96 } 97 98 99 @TestInfo(&tester10) 100 immutable test10 = q{--- test10 101 // Test reading pointer at zero index 102 i32 run(i32* array) { 103 return array[0]; 104 } 105 }; 106 void tester10(ref TestContext ctx) { 107 auto run = ctx.getFunctionPtr!(int, int*)("run"); 108 int val = 42; 109 int res = run(&val); 110 //writefln("test(&42) -> %s", res); 111 assert(res == 42); 112 } 113 114 115 @TestInfo(&tester11) 116 immutable test11 = q{--- test11 117 // Test reading pointer at constant non-zero index 118 i32 run(i32* array) { 119 return array[1]; 120 } 121 }; 122 void tester11(ref TestContext ctx) { 123 auto run = ctx.getFunctionPtr!(int, int*)("run"); 124 int[2] val = [42, 56]; 125 int res = run(val.ptr); 126 //writefln("test([42, 56].ptr) -> %s", res); 127 assert(res == 56); 128 } 129 130 131 @TestInfo(&tester12) 132 immutable test12 = q{--- test12 133 // Test reading pointer at variable index 134 i32 run(i32* array, i32 index) { 135 return array[index]; 136 } 137 }; 138 void tester12(ref TestContext ctx) { 139 auto run = ctx.getFunctionPtr!(int, int*, int)("run"); 140 int[2] val = [42, 56]; 141 int res0 = run(val.ptr, 0); 142 int res1 = run(val.ptr, 1); 143 //writefln("test([42, 56].ptr, 1) -> %s", res); 144 assert(res0 == 42); 145 assert(res1 == 56); 146 } 147 148 149 @TestInfo(&tester13) 150 immutable test13 = q{--- test13 151 // Test pointer index assign 152 void run(i32* array, i32 index, i32 value) { 153 array[index] = value; 154 } 155 }; 156 void tester13(ref TestContext ctx) { 157 auto run = ctx.getFunctionPtr!(void, int*, int, int)("run"); 158 int[4] val = [42, 56, 96, 102]; 159 int[4] expected = [42, 20, 96, 102]; 160 run(val.ptr, 1, 20); 161 //writefln("test([42, 56].ptr, 1, 20) -> %s", val); 162 assert(val == expected, format("%s != %s", val, expected)); 163 } 164 165 166 @TestInfo(&tester14) 167 immutable test14 = q{--- test14 168 // Test pointer index assign 169 void run(i32* array, i32 index, i32 value, i32 value2, i32 value3) { 170 array[index] = value + value2 + value3; 171 } 172 }; 173 void tester14(ref TestContext ctx) { 174 auto run = ctx.getFunctionPtr!(void, int*, int, int, int, int)("run"); 175 int[2] val = [42, 56]; 176 run(val.ptr, 1, 10, 6, 4); 177 //writefln("test([42, 56].ptr, 1, 10, 6, 4) -> %s", val); 178 assert(val[1] == 20); 179 } 180 181 182 @TestInfo(&tester15, [HostSymbol("external", cast(void*)&test15_external_func)]) 183 immutable test15 = q{--- test15 184 // Test 3 inputs no parameters pushed to the stack 185 i32 run(i32 par) { 186 return external(par, 10, 20); 187 } 188 @extern(module, "host") 189 i32 external(i32, i32, i32); 190 }; 191 extern(C) int test15_external_func(int par1, int par2, int par3) { 192 return par1 + par2 + par3; 193 } 194 void tester15(ref TestContext ctx) { 195 auto run = ctx.getFunctionPtr!(int, int)("run"); 196 int result = run(10); 197 //writefln("fun(10) -> %s", result); 198 assert(result == 40); 199 } 200 201 202 @TestInfo(&tester16, [HostSymbol("external", cast(void*)&test16_external_func)]) 203 immutable test16 = q{--- test16 204 // Test more than 4 inputs (5-th parameter pushed to the stack, extra alignment needed) 205 i32 run(i32 par) { 206 return external(par, 10, 20, 30, 40); 207 } 208 @extern(module, "host") 209 i32 external(i32, i32, i32, i32, i32); 210 }; 211 extern(C) int test16_external_func(int par1, int par2, int par3, int par4, int par5) { 212 return par1 + par2 + par3 + par4 + par5; 213 } 214 void tester16(ref TestContext ctx) { 215 auto run = ctx.getFunctionPtr!(int, int)("run"); 216 int result = run(10); 217 //writefln("fun(10) -> %s", result); 218 assert(result == 110); 219 } 220 221 222 @TestInfo(&tester17, [HostSymbol("external", cast(void*)&test17_external_func)]) 223 immutable test17 = q{--- test17 224 // Test 6 inputs (5-th and 6-th parameters pushed to the stack, no extra alignment needed) 225 i32 run(i32 par) { 226 return external(par, 10, 20, 30, 40, 50); 227 } 228 @extern(module, "host") 229 i32 external(i32, i32, i32, i32, i32, i32); 230 }; 231 extern(C) int test17_external_func(int par1, int par2, int par3, int par4, int par5, int par6) { 232 return par1 + par2 + par3 + par4 + par5 + par6; 233 } 234 void tester17(ref TestContext ctx) { 235 auto run = ctx.getFunctionPtr!(int, int)("run"); 236 int result = run(10); 237 //writefln("fun(10) -> %s", result); 238 assert(result == 160); 239 } 240 241 void testerRunVoid(ref TestContext ctx) { 242 auto run = ctx.getFunctionPtr!(void)("run"); 243 run(); 244 } 245 246 247 @TestInfo(&testerRunVoid) 248 immutable test18 = q{--- test18 249 // test empty void function 250 void run() {} 251 }; 252 253 254 @TestInfo(&testerRunVoid) 255 immutable test19 = q{--- test19 256 // test empty void function with return 257 void run() { return; } 258 }; 259 260 261 @TestInfo(&tester20) 262 immutable test20 = q{--- test20 263 // test empty i32 function without return and with control flow 264 void run(i32 i) { if(i){}else{} } 265 }; 266 void tester20(ref TestContext ctx) { 267 auto run = ctx.getFunctionPtr!(void, int)("run"); 268 run(1); 269 } 270 271 272 void tester21(ref TestContext ctx) { 273 auto fibonacci = ctx.getFunctionPtr!(void)("fibonacci"); 274 fibonacci(); 275 assert(testSink.text == "1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765"); 276 } 277 278 279 @TestInfo(&tester21, [HostSymbol("print", cast(void*)&external_print_i32_func)]) 280 immutable test21 = q{--- test21 281 // test fibonacci. while loop. func call 282 @extern(module, "host") 283 void print(i32); // external 284 void fibonacci() { 285 i32 lo = 0; 286 i32 hi = 1; 287 while (hi < 10000) { 288 hi = hi + lo; 289 lo = hi - lo; 290 print(lo); 291 } 292 } 293 }; 294 295 296 @TestInfo(&tester21, [HostSymbol("print", cast(void*)&external_print_i32_func)]) 297 immutable test21_2 = q{--- test21_2 298 // Causes other order of phi functions, which requires correct move sequence to resolve 299 // Tests phi resolution after register allocation 300 @extern(module, "host") 301 void print(i32); // external 302 void fibonacci() { 303 i32 lo = 0; 304 i32 hi = 1; 305 while (hi < 10000) { 306 i32 tmp = hi; 307 hi = hi + lo; 308 lo = tmp; 309 print(lo); 310 } 311 } 312 }; 313 314 315 @TestInfo(&tester22) 316 immutable test22 = q{--- test22 317 // test phi resolution with critical edge and test break; 318 i32 run() { 319 i32 counter = 10; 320 i32 counter2 = 0; 321 while (counter > 0) 322 { 323 counter = counter - 1; 324 counter2 = counter2 + 1; 325 if (counter2 == 5) break; 326 } 327 return counter; 328 } 329 }; 330 void tester22(ref TestContext ctx) { 331 auto run = ctx.getFunctionPtr!(int)("run"); 332 int res = run(); 333 assert(res == 5); 334 } 335 336 337 @TestInfo(&tester23) 338 immutable test23 = q{--- test23 339 // test continue 340 i32 run() { 341 i32 counter = 10; 342 i32 counter2 = 2; 343 while (counter > 0) { 344 counter = counter - 1; 345 if (counter < 5) continue; 346 counter2 = counter2 + 1; 347 } 348 return counter2; 349 } 350 }; 351 void tester23(ref TestContext ctx) { 352 auto run = ctx.getFunctionPtr!(int)("run"); 353 int res = run(); 354 assert(res == 7); 355 } 356 357 358 @TestInfo(&tester24, [HostSymbol("print", cast(void*)&test24_external_print)]) 359 immutable test24 = q{--- test24 360 // test string literal as u8* param 361 @extern(module, "host") 362 void print(u8*); 363 void run(){ print("Hello"); } 364 }; 365 extern(C) void test24_external_print(ubyte* param) { 366 testSink.put(cast(char[])param[0..5]); // Hello 367 } 368 void tester24(ref TestContext ctx) { 369 auto run = ctx.getFunctionPtr!(void)("run"); 370 run(); 371 assert(testSink.text == "Hello"); 372 } 373 374 375 @TestInfo(&tester25, [HostSymbol("print", cast(void*)&external_print_string)]) 376 immutable test25 = q{--- test25 377 // test struct creation, member set, stack struct as func argument 378 struct string { u64 length; u8* ptr; } 379 @extern(module, "host") 380 void print(string); 381 void run(){ 382 string str; 383 str.ptr = "Hello"; 384 str.length = 5; 385 print(str); 386 } 387 }; 388 void tester25(ref TestContext ctx) { 389 auto run = ctx.getFunctionPtr!(void)("run"); 390 run(); 391 //writefln("run() == '%s'", testSink.text); 392 assert(testSink.text == "Hello"); 393 } 394 395 396 @TestInfo(&tester25, [HostSymbol("print", cast(void*)&external_print_string)]) 397 immutable test26 = q{--- test26 398 // test global parameter, assignment 399 struct string { u64 length; u8* ptr; } 400 @extern(module, "host") 401 void print(string); 402 string str; 403 void run(){ 404 str.ptr = "Hello"; 405 str.length = 5; 406 print(str); 407 } 408 }; 409 410 411 @TestInfo(&tester27, [HostSymbol("print", cast(void*)&external_print_string)]) 412 immutable test27 = q{--- test27 413 // test slices 414 @extern(module, "host") 415 void print(u8[]); 416 void run() { 417 u8[] array; 418 array.length = 9; 419 // Assign string literal to ptr 420 array.ptr = "AssignPtr"; 421 print(array); 422 423 // Assign string literal to slice 424 array = "AssignSlice"; 425 print(array); 426 } 427 }; 428 void tester27(ref TestContext ctx) { 429 auto run = ctx.getFunctionPtr!(void)("run"); 430 run(); 431 //writefln("run() == '%s'", testSink.text); 432 assert(testSink.text == "AssignPtrAssignSlice"); 433 } 434 435 436 @TestInfo(&tester31, [HostSymbol("print_num", cast(void*)&test31_external_print_num)]) 437 immutable test31 = q{--- test31 438 // test enums 439 //enum i32 e2; // manifest constant, invalid, need initializer 440 enum e3 = 3; // manifest constant 441 enum i32 e4 = 4; // manifest constant 442 443 enum { e5 = 5 } // anon type 444 enum : i32 { e6 = 6 } // anon type 445 446 enum e1; // type 447 enum e7 : i32 { e7 = 7 } // type 448 enum e8 : i32; // type, body omitted 449 enum e9 { e9 = 9 } // type 450 451 @extern(module, "host") 452 void print_num(i64 val); 453 e9 ret_enum(){ return e9.e9; } 454 void accept_enum(e9 e){print_num(e);} 455 void run() { 456 print_num(e3); 457 print_num(e4); 458 print_num(e5); 459 print_num(e6); 460 // enum implicitly casts to base 461 print_num(e7.e7); 462 print_num(e9.e9); 463 accept_enum(e9.e9); 464 // explicit cast of int to enum 465 accept_enum(cast(e9)42); 466 // makes sure that e9.e9 is of type e9 and that e9 is implicitly castable to i32 467 print_num(ret_enum()); 468 } 469 }; 470 extern(C) void test31_external_print_num(long param) { 471 testSink.putf("%s", param); 472 } 473 void tester31(ref TestContext ctx) { 474 auto run = ctx.getFunctionPtr!(void)("run"); 475 run(); 476 //writefln("run() == '%s'", testSink.text); 477 assert(testSink.text == "3456799429"); 478 } 479 480 481 @TestInfo(&tester21, [HostSymbol("print", cast(void*)&external_print_i32_func)]) 482 immutable test32 = q{--- test32 483 // Test reg alloc xchg generation 484 @extern(module, "host") 485 void print(i32); // external 486 void fibonacci() { 487 i32 lo = 0; 488 i32 hi = 1; 489 while (hi < 10000) { 490 i32 tmp = hi; 491 hi = hi + lo; 492 lo = tmp; 493 print(lo); 494 } 495 while (hi < 10000) { 496 i32 tmp = hi; 497 hi = hi + lo; 498 lo = tmp; 499 print(lo); 500 } 501 while (hi < 10000) { 502 i32 tmp = hi; 503 hi = hi + lo; 504 lo = tmp; 505 print(lo); 506 } 507 while (hi < 10000) { 508 i32 tmp = hi; 509 hi = hi + lo; 510 lo = tmp; 511 print(lo); 512 } 513 } 514 }; 515 516 517 @TestInfo(&tester21, [HostSymbol("print", cast(void*)&external_print_i32_func)]) 518 immutable test33 = q{ 519 --- test33_1 520 // test multifile compilation 521 @extern(module, "host") 522 void print(i32); // external 523 --- test33_2 524 import test33_1; 525 void fibonacci() { 526 i32 lo = 0; 527 i32 hi = 1; 528 while (hi < 10000) { 529 hi = hi + lo; 530 lo = hi - lo; 531 print(lo); 532 } 533 } 534 }; 535 536 @TestInfo(&tester34) 537 immutable test34 = q{--- test34 538 i32 getElement(i32[] items, i32 index) { return items[index]; } 539 }; 540 void tester34(ref TestContext ctx) { 541 auto getElement = ctx.getFunctionPtr!(int, Slice!int, int)("getElement"); 542 int[2] val = [42, 56]; 543 Slice!int slice = Slice!int(val); 544 int res0 = getElement(slice, 0); 545 int res1 = getElement(slice, 1); 546 assert(res0 == 42); 547 assert(res1 == 56); 548 } 549 550 551 @TestInfo(&tester35) 552 immutable test35 = q{--- test35 553 void setElement(i32[] items, i32 index, i32 value) { items[index] = value; } 554 }; 555 void tester35(ref TestContext ctx) { 556 auto setElement = ctx.getFunctionPtr!(void, Slice!int, int, int)("setElement"); 557 int[2] val = [42, 56]; 558 Slice!int slice = Slice!int(val); 559 setElement(slice, 0, 88); 560 assert(val == [88, 56]); 561 setElement(slice, 1, 96); 562 assert(val == [88, 96]); 563 } 564 565 566 @TestInfo() 567 immutable test36 = q{--- test36 568 // Test null literal implicit conversion to pointer types 569 void test() { 570 callee1(null); 571 callee2(null); 572 } 573 void callee1(void*) {} 574 void callee2(u8*) {} 575 }; 576 577 578 @TestInfo() 579 immutable test37 = q{--- test37 580 // Test negative int literal 581 void test() { 582 callee1(-1); 583 } 584 void callee1(i32) {} 585 }; 586 587 588 @TestInfo() 589 immutable test38 = q{--- test38 590 // Test empty struct 591 struct A {} 592 }; 593 594 595 @TestInfo(&tester39) 596 immutable test39 = q{--- test39 597 // Test shifts 598 i32 shl(i32 a, i32 b) { 599 return a << b; 600 } 601 i32 shr(i32 a, i32 b) { 602 return a >> b; 603 } 604 i32 sar(i32 a, i32 b) { 605 return a >>> b; 606 } 607 }; 608 void tester39(ref TestContext ctx) { 609 auto shl = ctx.getFunctionPtr!(int, int, int)("shl"); 610 auto shr = ctx.getFunctionPtr!(int, int, int)("shr"); 611 auto sar = ctx.getFunctionPtr!(int, int, int)("sar"); 612 foreach(i; 0..33) { 613 int res = shl(1, i); 614 assert(res == 1 << i); 615 //writefln("1 << %s == %b", i, res); 616 617 enum HIGH_BIT = 1 << 31; 618 int res2 = shr(HIGH_BIT, i); 619 //writefln("%032b >> %s == %032b", HIGH_BIT, i, res2); 620 assert(res2 == HIGH_BIT >> i); 621 622 int res3 = sar(HIGH_BIT, i); 623 assert(res3 == HIGH_BIT >>> i); 624 //writefln("%032b >>> %s == %032b", HIGH_BIT, i, res3); 625 } 626 } 627 628 629 @TestInfo(&tester40) 630 immutable test40 = q{--- test40 631 // Test left shift by a constant 632 i32 shl(i32 a) { 633 i32 res1 = a << 1; 634 i32 res2 = 4 << a; 635 i32 res3 = a << 3; 636 i32 res4 = a << 31; 637 i32 res5 = 1 << 31; 638 return res1 + res2 + res3 + res4 + res5; 639 } 640 }; 641 void tester40(ref TestContext ctx) { 642 auto shl = ctx.getFunctionPtr!(int, int)("shl"); 643 int res = shl(1); 644 //writefln("%b", res); 645 assert(res == (1 << 1) + (4 << 1) + (1 << 3) + (1 << 31) + (1 << 31)); 646 } 647 648 649 @TestInfo(&tester41) 650 immutable test41 = q{--- test41 651 // Test division, multiplication, remainder 652 i32 idiv(i32 a, i32 b) { 653 return a / b; 654 } 655 u32 div(u32 a, u32 b) { 656 return a / b; 657 } 658 i32 imul(i32 a, i32 b) { 659 return a * b; 660 } 661 u32 mul(u32 a, u32 b) { 662 return a * b; 663 } 664 i32 irem(i32 a, i32 b) { 665 return a % b; 666 } 667 u32 rem(u32 a, u32 b) { 668 return a % b; 669 } 670 }; 671 void tester41(ref TestContext ctx) { 672 auto div = ctx.getFunctionPtr!(int, int, int)("div"); 673 auto idiv = ctx.getFunctionPtr!(int, int, int)("idiv"); 674 auto rem = ctx.getFunctionPtr!(int, int, int)("rem"); 675 auto irem = ctx.getFunctionPtr!(int, int, int)("irem"); 676 auto mul = ctx.getFunctionPtr!(int, int, int)("mul"); 677 auto imul = ctx.getFunctionPtr!(int, int, int)("imul"); 678 int resDiv = div(10, 5); 679 //writefln("10 / 5 == %s", resDiv); 680 assert(resDiv == 10 / 5); 681 int resIdiv = idiv(-10, 5); 682 //writefln("-10 / 5 == %s %s", resIdiv, -10 / 5); 683 assert(resIdiv == -10 / 5); 684 int resRem = rem(10, 4); 685 //writefln("10 %% 4 == %s", resRem); 686 assert(resRem == 10 % 4); 687 int resIrem = irem(-10, 4); 688 //writefln("-10 %% 4 == %s %s", resIrem, -10 % 4); 689 assert(resIrem == -10 % 4); 690 int resMul = mul(-10, 4); 691 //writefln("-10 * 4 == %s %s", resMul, -10 * 4); 692 assert(resMul == -10 * 4); 693 int resImul = imul(-10, 4); 694 //writefln("-10 * 4 == %s %s", resImul, -10 * 4); 695 assert(resImul == -10 * 4); 696 } 697 698 699 @TestInfo(&tester42) 700 immutable test42 = q{--- test42 701 // Test bit-wise negation, unary minus, xor, or, and operators 702 i32 not(i32 a) { 703 return ~a; 704 } 705 i32 neg(i32 a) { 706 return -a; 707 } 708 i32 xor(i32 a, i32 b) { 709 return a ^ b; 710 } 711 i32 or(i32 a, i32 b) { 712 return a | b; 713 } 714 i32 and(i32 a, i32 b) { 715 return a & b; 716 } 717 }; 718 void tester42(ref TestContext ctx) { 719 auto not = ctx.getFunctionPtr!(int, int)("not"); 720 auto neg = ctx.getFunctionPtr!(int, int)("neg"); 721 auto xor = ctx.getFunctionPtr!(int, int, int)("xor"); 722 auto or = ctx.getFunctionPtr!(int, int, int)("or"); 723 auto and = ctx.getFunctionPtr!(int, int, int)("and"); 724 725 int res_not = not(0b01); 726 //writefln("~0b01 == %02b", res_not); 727 assert(res_not == ~0b01); 728 729 int res_neg = neg(1); 730 //writefln("-1 == %s", res_neg); 731 assert(res_neg == -1); 732 733 int res_xor = xor(0b0011, 0b0101); 734 //writefln("0b0011 ^ 0b0101 == %04b", res_xor); 735 assert(res_xor == (0b0011 ^ 0b0101)); 736 737 int res_or = or(0b0011, 0b0101); 738 //writefln("0b0011 | 0b0101 == %04b", res_or); 739 assert(res_or == (0b0011 | 0b0101)); 740 741 int res_and = and(0b0011, 0b0101); 742 //writefln("0b0011 & 0b0101 == %04b", res_and); 743 assert(res_and == (0b0011 & 0b0101)); 744 } 745 746 747 @TestInfo(&tester43) 748 immutable test43 = q{--- test43 749 // Test op= 750 i32 add(i32 a, i32 b) { a += b; return a; } 751 i32 sub(i32 a, i32 b) { a -= b; return a; } 752 i32 mul(i32 a, i32 b) { a *= b; return a; } 753 i32 div(i32 a, i32 b) { a /= b; return a; } 754 i32 rem(i32 a, i32 b) { a %= b; return a; } 755 i32 shl(i32 a, i32 b) { a <<= b; return a; } 756 i32 shr(i32 a, i32 b) { a >>>= b; return a; } 757 i32 sar(i32 a, i32 b) { a >>= b; return a; } 758 i32 or (i32 a, i32 b) { a |= b; return a; } 759 i32 xor(i32 a, i32 b) { a ^= b; return a; } 760 i32 and(i32 a, i32 b) { a &= b; return a; } 761 }; 762 void tester43(ref TestContext ctx) { 763 auto add = ctx.getFunctionPtr!(int, int, int)("add"); 764 auto sub = ctx.getFunctionPtr!(int, int, int)("sub"); 765 auto mul = ctx.getFunctionPtr!(int, int, int)("mul"); 766 auto div = ctx.getFunctionPtr!(int, int, int)("div"); 767 auto rem = ctx.getFunctionPtr!(int, int, int)("rem"); 768 auto shl = ctx.getFunctionPtr!(int, int, int)("shl"); 769 auto shr = ctx.getFunctionPtr!(int, int, int)("shr"); 770 auto sar = ctx.getFunctionPtr!(int, int, int)("sar"); 771 auto or = ctx.getFunctionPtr!(int, int, int)("or"); 772 auto xor = ctx.getFunctionPtr!(int, int, int)("xor"); 773 auto and = ctx.getFunctionPtr!(int, int, int)("and"); 774 775 assert(add(1, 3) == 4); 776 assert(sub(3, 1) == 2); 777 assert(mul(3, 2) == 6); 778 assert(div(7, 2) == 3); 779 assert(rem(7, 2) == 1); 780 assert(shl(1, 2) == 4); 781 assert(shr(int.min, 2) == (int.min >>> 2)); 782 assert(sar(int.min, 2) == (int.min >> 2)); 783 assert(or(0b0011, 0b0101) == 0b0111); 784 assert(xor(0b0011, 0b0101) == 0b0110); 785 assert(and(0b0011, 0b0101) == 0b0001); 786 } 787 788 789 @TestInfo(&tester44) 790 immutable test44 = q{--- test44 791 // Test --a, ++a 792 i32 preInc(i32 a) { return ++a + ++a; } 793 i32 postInc(i32 a) { return a++ + a++; } 794 i32 preDec(i32 a) { return --a + --a; } 795 i32 postDec(i32 a) { return a-- + a--; } 796 797 i32* preIncPtr(i32* a) { return ++a; } 798 i32* postIncPtr(i32* a) { return a++; } 799 i32* preDecPtr(i32* a) { return --a; } 800 i32* postDecPtr(i32* a) { return a--; } 801 }; 802 void tester44(ref TestContext ctx) { 803 auto preInc = ctx.getFunctionPtr!(int, int)("preInc"); 804 auto postInc = ctx.getFunctionPtr!(int, int)("postInc"); 805 auto preDec = ctx.getFunctionPtr!(int, int)("preDec"); 806 auto postDec = ctx.getFunctionPtr!(int, int)("postDec"); 807 808 assert(preInc(10) == 23); 809 assert(postInc(10) == 21); 810 assert(preDec(3) == 3); 811 assert(postDec(3) == 5); 812 813 auto preIncPtr = ctx.getFunctionPtr!(int*, int*)("preIncPtr"); 814 auto postIncPtr = ctx.getFunctionPtr!(int*, int*)("postIncPtr"); 815 auto preDecPtr = ctx.getFunctionPtr!(int*, int*)("preDecPtr"); 816 auto postDecPtr = ctx.getFunctionPtr!(int*, int*)("postDecPtr"); 817 818 int[4] arr; 819 assert(preIncPtr(&arr[1]) == &arr[2]); 820 assert(postIncPtr(&arr[1]) == &arr[1]); 821 assert(preDecPtr(&arr[1]) == &arr[0]); 822 assert(postDecPtr(&arr[1]) == &arr[1]); 823 } 824 825 826 @TestInfo(&tester45) 827 immutable test45 = q{--- test45 828 void incArray(i32* arr, i32 length) { 829 i32 i = 0; 830 while(i < length) { 831 ++arr[i++]; 832 } 833 } 834 }; 835 void tester45(ref TestContext ctx) { 836 int[4] arr = [1, 2, 3, 4]; 837 auto incArray = ctx.getFunctionPtr!(void, int*, int)("incArray"); 838 incArray(arr.ptr, arr.length); 839 assert(arr == [2, 3, 4, 5]); 840 } 841 842 843 @TestInfo(&tester46) 844 immutable test46 = q{--- test46 845 void incArray(i32* begin, i32* end) { 846 while(begin < end) { 847 ++(*begin++); 848 } 849 } 850 }; 851 void tester46(ref TestContext ctx) { 852 int[4] arr = [1, 2, 3, 4]; 853 auto incArray = ctx.getFunctionPtr!(void, int*, int*)("incArray"); 854 incArray(arr.ptr, arr.ptr + arr.length); 855 assert(arr == [2, 3, 4, 5]); 856 } 857 858 859 @TestInfo(&tester47) 860 immutable test47 = q{--- test47 861 // test logical not, or, and 862 i32 selectNot(i32 selector, i32 a, i32 b) { 863 if (!selector) 864 return a; 865 else return b; 866 } 867 i32 selectOr(i32 selectorA, i32 selectorB, i32 a, i32 b) { 868 if (selectorA || selectorB) 869 return a; 870 else return b; 871 } 872 i32 selectAnd(i32 selectorA, i32 selectorB, i32 a, i32 b) { 873 if (selectorA && selectorB) 874 return a; 875 else return b; 876 } 877 }; 878 void tester47(ref TestContext ctx) { 879 auto selectNot = ctx.getFunctionPtr!(int, int, int, int)("selectNot"); 880 assert(selectNot(0, 1, 2) == 1); 881 assert(selectNot(1, 1, 2) == 2); 882 auto selectOr = ctx.getFunctionPtr!(int, int, int, int, int)("selectOr"); 883 assert(selectOr(0, 0, 1, 0) == 0); 884 assert(selectOr(0, 1, 1, 0) == 1); 885 assert(selectOr(1, 0, 1, 0) == 1); 886 assert(selectOr(1, 1, 1, 0) == 1); 887 auto selectAnd = ctx.getFunctionPtr!(int, int, int, int, int)("selectAnd"); 888 assert(selectAnd(0, 0, 1, 0) == 0); 889 assert(selectAnd(0, 1, 1, 0) == 0); 890 assert(selectAnd(1, 0, 1, 0) == 0); 891 assert(selectAnd(1, 1, 1, 0) == 1); 892 } 893 894 895 @TestInfo(&tester48) 896 immutable test48 = q{--- test48 897 // bool values 898 bool getFalse() { return false; } 899 bool getTrue() { return true; } 900 bool getBool(i32 selectorA) { 901 return selectorA; 902 } 903 bool getNot(i32 selectorA) { 904 return !selectorA; 905 } 906 bool getOr(i32 selectorA, i32 selectorB) { 907 return selectorA || selectorB; 908 } 909 bool getAnd(i32 selectorA, i32 selectorB) { 910 return selectorA && selectorB; 911 } 912 }; 913 void tester48(ref TestContext ctx) { 914 auto getFalse = ctx.getFunctionPtr!(bool)("getFalse"); 915 assert(getFalse() == false); 916 auto getTrue = ctx.getFunctionPtr!(bool)("getTrue"); 917 assert(getTrue() == true); 918 auto getBool = ctx.getFunctionPtr!(bool, int)("getBool"); 919 assert(getBool(0) == false); 920 assert(getBool(1) == true); 921 auto getNot = ctx.getFunctionPtr!(bool, int)("getNot"); 922 assert(getNot(0) == true); 923 assert(getNot(1) == false); 924 auto getOr = ctx.getFunctionPtr!(bool, int, int)("getOr"); 925 assert(getOr(0, 0) == false); 926 assert(getOr(0, 1) == true); 927 assert(getOr(1, 0) == true); 928 assert(getOr(1, 1) == true); 929 auto getAnd = ctx.getFunctionPtr!(bool, int, int)("getAnd"); 930 assert(getAnd(0, 0) == false); 931 assert(getAnd(0, 1) == false); 932 assert(getAnd(1, 0) == false); 933 assert(getAnd(1, 1) == true); 934 } 935 936 937 @TestInfo(&tester49) 938 immutable test49 = q{--- test49 939 // Test full suite of pointer arithmetic operations 940 void preIncrement(i32* arr, i32 length) { 941 (++arr)[-1] = 10; // arr[0] = 10, negative index 942 *arr = 15; // arr[1] = 15, deref pointer 943 } 944 void preDecrement(i32* arr, i32 length) { 945 (--arr)[1] = 20; // arr[0] = 20 946 arr[2] = 25; // arr[1] = 25 947 } 948 void postIncrement(i32* arr, i32 length) { 949 (arr++)[0] = 30; // arr[0] = 30 950 arr[0] = 35; // arr[1] = 35 951 } 952 void postDecrement(i32* arr, i32 length) { 953 (arr--)[0] = 40; // arr[0] = 40 954 arr[2] = 45; // arr[1] = 45 955 } 956 void addInt(i32* arr, i32 length) { 957 *(arr + 3) = 50; // arr[3] = 50 958 } 959 void subInt(i32* arr, i32 length) { 960 *(arr - 3) = 60; // arr[-4] = 60 961 } 962 void diff(i32* arr, i32 length) { 963 i32* last = arr + length; // last = &arr[4]; 964 // sub two pointers 965 i64 diff = last - arr; 966 arr[length - 3] = cast(i32)diff; // ar[1] = 4 967 } 968 void plusEqual(i32* arr, i32 length) { 969 arr += 3; 970 arr[0] = 90; // arr[3] = 90 971 } 972 void minusEqual(i32* arr, i32 length) { 973 arr -= 3; 974 arr[3] = 100; // arr[0] = 100 975 } 976 }; 977 void tester49(ref TestContext ctx) { 978 int[2] arr; 979 auto preIncrement = ctx.getFunctionPtr!(void, int*, int)("preIncrement"); 980 preIncrement(arr.ptr, arr.length); 981 assert(arr == [10, 15]); 982 983 auto preDecrement = ctx.getFunctionPtr!(void, int*, int)("preDecrement"); 984 preDecrement(arr.ptr, arr.length); 985 assert(arr == [20, 25]); 986 987 auto postIncrement = ctx.getFunctionPtr!(void, int*, int)("postIncrement"); 988 postIncrement(arr.ptr, arr.length); 989 assert(arr == [30, 35]); 990 991 auto postDecrement = ctx.getFunctionPtr!(void, int*, int)("postDecrement"); 992 postDecrement(arr.ptr, arr.length); 993 assert(arr == [40, 45]); 994 995 int[4] arr2; 996 997 auto addInt = ctx.getFunctionPtr!(void, int*, int)("addInt"); 998 addInt(arr2.ptr, arr2.length); 999 assert(arr2 == [0, 0, 0, 50]); 1000 1001 auto subInt = ctx.getFunctionPtr!(void, int*, int)("subInt"); 1002 subInt(arr2.ptr+3, arr2.length); 1003 assert(arr2 == [60, 0, 0, 50]); 1004 1005 auto diff = ctx.getFunctionPtr!(void, int*, int)("diff"); 1006 diff(arr2.ptr, arr2.length); 1007 assert(arr2 == [60, 4, 0, 50]); 1008 1009 auto plusEqual = ctx.getFunctionPtr!(void, int*, int)("plusEqual"); 1010 plusEqual(arr2.ptr, arr2.length); 1011 assert(arr2 == [60, 4, 0, 90]); 1012 1013 auto minusEqual = ctx.getFunctionPtr!(void, int*, int)("minusEqual"); 1014 minusEqual(arr2.ptr, arr2.length); 1015 assert(arr2 == [100, 4, 0, 90]); 1016 } 1017 1018 @TestInfo(&tester50) 1019 immutable test50 = q{--- test50 1020 // test ptr cmp with null 1021 // test unary branch on byte value 1022 u64 cstrlen(u8* str) { 1023 if (str == null) return 0; 1024 1025 u8* start = str; 1026 while(*str) 1027 { 1028 ++str; 1029 } 1030 return cast(u64)(str - start); 1031 } 1032 }; 1033 void tester50(ref TestContext ctx) { 1034 auto cstrlen = ctx.getFunctionPtr!(ulong, const(char)*)("cstrlen"); 1035 string str = "test"; 1036 ulong length = cstrlen(str.ptr); 1037 assert(length == str.length); 1038 } 1039 1040 @TestInfo(&tester51) 1041 immutable test51 = q{--- test51 1042 // test null assign, compare 1043 u8* assignNull() { 1044 u8* ptr = null; 1045 return ptr; 1046 } 1047 bool testNull(u8* ptr) { 1048 return ptr == null; 1049 } 1050 }; 1051 void tester51(ref TestContext ctx) { 1052 auto assignNull = ctx.getFunctionPtr!(ubyte*)("assignNull"); 1053 ubyte* val = assignNull(); 1054 assert(val == null); 1055 1056 auto testNull = ctx.getFunctionPtr!(bool, ubyte*)("testNull"); 1057 bool resNull = testNull(val); 1058 assert(resNull == true); 1059 1060 ubyte value; 1061 bool resNotNull = testNull(&value); 1062 assert(resNotNull == false); 1063 } 1064 1065 @TestInfo(&tester52) 1066 immutable test52 = q{--- test52 1067 // test integer comparison 1068 bool cmp8(i8 a, i8 b) { return a == b; } 1069 bool cmp16(i16 a, i16 b) { return a == b; } 1070 bool cmp32(i32 a, i32 b) { return a == b; } 1071 bool cmp64(i64 a, i64 b) { return a == b; } 1072 1073 bool br8(i8 a, i8 b) { bool result; if (a == b) result = true; else result = false; return result; } 1074 bool br16(i16 a, i16 b) { bool result; if (a == b) result = true; else result = false; return result; } 1075 bool br32(i32 a, i32 b) { bool result; if (a == b) result = true; else result = false; return result; } 1076 bool br64(i64 a, i64 b) { bool result; if (a == b) result = true; else result = false; return result; } 1077 }; 1078 void tester52(ref TestContext ctx) { 1079 // pass 64bit values, to check that only lower bits are compared 1080 void test(string funcName, ulong a, ulong b) 1081 { 1082 auto cmp = ctx.getFunctionPtr!(bool, ulong, ulong)(funcName); 1083 bool res = cmp(a, b); 1084 assert(res == true); 1085 } 1086 test("cmp8", 0xF0_F0_F0_F0_F0_F0_F0_FF, 0x0F_0F_0F_0F_0F_0F_0F_FF); 1087 test("br8", 0xF0_F0_F0_F0_F0_F0_F0_FF, 0x0F_0F_0F_0F_0F_0F_0F_FF); 1088 1089 test("cmp16", 0xF0_F0_F0_F0_F0_F0_FF_FF, 0x0F_0F_0F_0F_0F_0F_FF_FF); 1090 test("br16", 0xF0_F0_F0_F0_F0_F0_FF_FF, 0x0F_0F_0F_0F_0F_0F_FF_FF); 1091 1092 test("cmp32", 0xF0_F0_F0_F0_FF_FF_FF_FF, 0x0F_0F_0F_0F_FF_FF_FF_FF); 1093 test("br32", 0xF0_F0_F0_F0_FF_FF_FF_FF, 0x0F_0F_0F_0F_FF_FF_FF_FF); 1094 1095 test("cmp64", 0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); 1096 test("br64", 0xFF_FF_FF_FF_FF_FF_FF_FF, 0xFF_FF_FF_FF_FF_FF_FF_FF); 1097 } 1098 1099 @TestInfo(&tester53) 1100 immutable test53 = q{--- test53 1101 // Test constant folding 1102 i32 add() { return 1 + 3; } 1103 i32 sub() { return 3 - 1; } 1104 i32 mul() { return 3 * 2; } 1105 i32 div() { return 7 / 2; } 1106 i32 rem() { return 7 % 2; } 1107 i32 shl() { return 1 << 2; } 1108 i32 shr() { return i32.min >>> 2; } 1109 i32 sar() { return i32.min >> 2; } 1110 i32 or () { return 0b0011 | 0b0101; } 1111 i32 xor() { return 0b0011 ^ 0b0101; } 1112 i32 and() { return 0b0011 & 0b0101; } 1113 }; 1114 void tester53(ref TestContext ctx) { 1115 auto add = ctx.getFunctionPtr!(int)("add"); 1116 auto sub = ctx.getFunctionPtr!(int)("sub"); 1117 auto mul = ctx.getFunctionPtr!(int)("mul"); 1118 auto div = ctx.getFunctionPtr!(int)("div"); 1119 auto rem = ctx.getFunctionPtr!(int)("rem"); 1120 auto shl = ctx.getFunctionPtr!(int)("shl"); 1121 auto shr = ctx.getFunctionPtr!(int)("shr"); 1122 auto sar = ctx.getFunctionPtr!(int)("sar"); 1123 auto or = ctx.getFunctionPtr!(int)("or"); 1124 auto xor = ctx.getFunctionPtr!(int)("xor"); 1125 auto and = ctx.getFunctionPtr!(int)("and"); 1126 1127 assert(add() == 4); 1128 assert(sub() == 2); 1129 assert(mul() == 6); 1130 assert(div() == 3); 1131 assert(rem() == 1); 1132 assert(shl() == 4); 1133 assert(shr() == (int.min >>> 2)); 1134 assert(sar() == (int.min >> 2)); 1135 assert(or() == 0b0111); 1136 assert(xor() == 0b0110); 1137 assert(and() == 0b0001); 1138 } 1139 1140 @TestInfo() 1141 immutable test54 = q{--- test54 1142 // Test bool literal branching 1143 void run() { 1144 while(true) { 1145 break; 1146 } 1147 while(false) { 1148 1149 } 1150 while(true) { 1151 1152 } 1153 if (true){} 1154 if (false){} 1155 } 1156 }; 1157 1158 1159 @TestInfo(&tester55, [HostSymbol("print", cast(void*)&external_print_string)]) 1160 immutable test55 = q{--- test55 1161 // test slice forwarding 1162 @extern(module, "host") 1163 void print(u8[] str); 1164 void forward(u8[] str) { 1165 print(str); 1166 } 1167 }; 1168 void tester55(ref TestContext ctx) { 1169 auto forward = ctx.getFunctionPtr!(void, Slice!(immutable(char)))("forward"); 1170 forward(Slice!(immutable(char))("testString")); 1171 assert(testSink.text == "testString"); 1172 } 1173 1174 1175 @TestInfo() 1176 immutable test56 = q{--- test56 1177 // test using bool variable for branching 1178 void branch() { 1179 bool run = true; 1180 while (run) {} 1181 } 1182 }; 1183 1184 @TestInfo() 1185 immutable test57 = q{--- test57 1186 // test using bool variable for branching 1187 void use(bool){} 1188 void branch() { 1189 bool run = true; 1190 while (run) {} 1191 use(run); 1192 } 1193 }; 1194 1195 @TestInfo() 1196 immutable test58 = q{--- test58 1197 // Test declaration statement that declares pointer var 1198 struct SDL_Event { 1199 u32 type; 1200 } 1201 void run() { 1202 SDL_Event* key; 1203 } 1204 }; 1205 1206 @TestInfo() 1207 immutable test59 = q{--- test59 1208 // Test dot operator on dereference and member expressions 1209 struct SDL_KeyboardEvent { 1210 u32 type; 1211 u32 timestamp; 1212 SDL_Keysym keysym; 1213 } 1214 struct SDL_Keysym { 1215 u32 scancode; 1216 u32 sym; 1217 } 1218 void run(SDL_KeyboardEvent* key) { 1219 if ((*key).keysym.scancode == 1) { 1220 (*key).keysym.sym = 42; 1221 } 1222 } 1223 }; 1224 1225 @TestInfo() 1226 immutable test60 = q{--- test60 1227 // Test dot operator on pointer type 1228 struct SDL_KeyboardEvent { 1229 u32 type; 1230 u32 timestamp; 1231 SDL_Keysym keysym; 1232 } 1233 struct SDL_Keysym { 1234 u32 scancode; 1235 u32 sym; 1236 } 1237 void run(SDL_KeyboardEvent* key) { 1238 if (key.keysym.scancode == 1) { 1239 key.keysym.sym = 42; 1240 } 1241 } 1242 }; 1243 1244 @TestInfo() 1245 immutable test61 = q{--- test61 1246 // Test pointer to pointer cast 1247 struct SDL_Event { 1248 u32 type; 1249 u8[52] padding; 1250 } 1251 struct SDL_KeyboardEvent { 1252 u32 type; 1253 u32 timestamp; 1254 SDL_Keysym keysym; 1255 } 1256 struct SDL_Keysym { 1257 u32 scancode; 1258 u32 sym; 1259 } 1260 void run(SDL_KeyboardEvent* key) { 1261 SDL_Event e; 1262 SDL_KeyboardEvent* key = cast(SDL_KeyboardEvent*)&e; 1263 } 1264 }; 1265 1266 @TestInfo() 1267 immutable test62 = q{--- test62 1268 // Bug. Infinite loop in trivial phi removal 1269 struct SDL_Event { 1270 u32 type; 1271 u8[52] padding; 1272 } 1273 struct SDL_KeyboardEvent { 1274 u32 type; 1275 u32 timestamp; 1276 u32 keysym; 1277 } 1278 i32 SDL_PollEvent(SDL_Event*){return 0;} 1279 i32 player_x; 1280 void run(SDL_KeyboardEvent* key) { 1281 bool run = true; 1282 SDL_Event e; 1283 1284 while (run) 1285 { 1286 if (e.type == 1) 1287 { 1288 SDL_KeyboardEvent* key = cast(SDL_KeyboardEvent*)&e; 1289 if ((*key).keysym == 1) 1290 { 1291 ++player_x; 1292 } 1293 } 1294 } 1295 } 1296 }; 1297 1298 @TestInfo() 1299 immutable test63 = q{--- test63 1300 // Store const into stack 1301 void usePtru8(u8*){} 1302 void usePtru16(u16*){} 1303 void usePtru32(u32*){} 1304 void usePtru64(u64*){} 1305 void run() { 1306 u8 num8 = 10; 1307 u16 num16 = 10; 1308 u32 num32 = 10; 1309 u64 num64 = 10; 1310 usePtru8(&num8); 1311 usePtru16(&num16); 1312 usePtru32(&num32); 1313 usePtru64(&num64); 1314 } 1315 }; 1316 1317 1318 @TestInfo(&tester65, [HostSymbol("print", cast(void*)&external_print_string)]) 1319 immutable test65 = q{--- test65 1320 // Test string literals 1321 @extern(module, "host") 1322 void print(u8[]); // external 1323 u8[] returnStringLiteral() { 1324 return "testString"; 1325 } 1326 void passStringLiteralArgument() { 1327 print("testString"); 1328 } 1329 }; 1330 void tester65(ref TestContext ctx) { 1331 auto returnStringLiteral = ctx.getFunctionPtr!(Slice!char)("returnStringLiteral"); 1332 assert(returnStringLiteral() == "testString"); 1333 1334 auto passStringLiteralArgument = ctx.getFunctionPtr!(void)("passStringLiteralArgument"); 1335 passStringLiteralArgument(); 1336 assert(testSink.text == "testString"); 1337 } 1338 1339 @TestInfo(&tester66) 1340 immutable test66 = q{--- test66 1341 // Test char literals 1342 u8 getChar() { return '\n'; } 1343 }; 1344 void tester66(ref TestContext ctx) { 1345 auto getChar = ctx.getFunctionPtr!(char)("getChar"); 1346 assert(getChar() == '\n'); 1347 } 1348 1349 @TestInfo(&tester67) 1350 immutable test67 = q{--- test67 1351 // Test static arrays 1352 u8* getPtr(u8[21]* arrPtr) { return (*arrPtr).ptr; } 1353 u64 getLength(u8[21]* arrPtr) { return (*arrPtr).length; } 1354 u8 getElement(u8[21]* arrPtr, i64 index) { return (*arrPtr)[index]; } 1355 void arrayToSlice(u8[21]* arrPtr) { receiveSlice(*arrPtr); } 1356 void receiveSlice(u8[] arr) {} 1357 struct Color { 1358 u8 r; 1359 u8 g; 1360 u8 b; 1361 u8 a; 1362 } 1363 Color[2] colors; 1364 void fun() { 1365 Color[2] colors_static_local; 1366 Color[] colors_local; 1367 } 1368 }; 1369 void tester67(ref TestContext ctx) { 1370 ubyte[21] array; 1371 foreach(i, ref elem; array) elem = cast(ubyte)i; 1372 1373 auto getPtr = ctx.getFunctionPtr!(ubyte*, ubyte[21]*)("getPtr"); 1374 assert(getPtr(&array) == array.ptr); 1375 1376 auto getLength = ctx.getFunctionPtr!(ulong, ubyte[21]*)("getLength"); 1377 assert(getLength(&array) == array.length); 1378 1379 auto getElement = ctx.getFunctionPtr!(ubyte, ubyte[21]*, ulong)("getElement"); 1380 foreach(i, elem; array) 1381 assert(getElement(&array, i) == elem); 1382 1383 auto arrayToSlice = ctx.getFunctionPtr!(void, ubyte[21]*)("arrayToSlice"); 1384 arrayToSlice(&array); 1385 } 1386 1387 @TestInfo() 1388 immutable test68 = q{--- test68 1389 // Test enum inside struct 1390 struct Struct { 1391 u8 a; 1392 enum someVal = 42; 1393 } 1394 void run() { 1395 i64 var = Struct.someVal; 1396 Struct s; 1397 i64 var2 = s.someVal; 1398 } 1399 }; 1400 1401 @TestInfo() 1402 immutable test69 = q{--- test69 1403 // Bug. Multiple users of trivial phis do not get 1404 // all users added when replacing phi result by singular phi argument 1405 struct GameMap { 1406 bool blocked; 1407 bool block_sight; 1408 } 1409 void initialize_tiles(GameMap* map) 1410 { 1411 i32 x = 0; 1412 while(x < 20) { 1413 map.blocked = false; 1414 map.block_sight = false; 1415 } 1416 } 1417 }; 1418 1419 @TestInfo() 1420 immutable test70 = q{--- test70 1421 // usage of member expr in condition 1422 struct GameMap { 1423 bool blocked; 1424 bool block_sight; 1425 } 1426 void initialize_tiles(GameMap* map) 1427 { 1428 if (map.blocked) { 1429 map.block_sight = true; 1430 } 1431 } 1432 }; 1433 1434 @TestInfo() 1435 immutable test71 = q{--- test71 1436 // Take address of array index 1437 u8* getFirst(u8[2]* array) 1438 { 1439 return &(*array)[0]; 1440 } 1441 }; 1442 1443 @TestInfo() 1444 immutable test72 = q{--- test72 1445 // Use call result as condition 1446 i32 run() 1447 { 1448 i32 val; 1449 if (getBool()) { 1450 val = 42; 1451 } else { 1452 val = 21; 1453 } 1454 return val; 1455 } 1456 bool getBool() { return true; } 1457 }; 1458 1459 @TestInfo() 1460 immutable test73 = q{--- test73 1461 // General instruction const handling 1462 void run() 1463 { 1464 i8 val8; 1465 i16 val16; 1466 i32 val32; 1467 i64 val64; 1468 val8 += 8; 1469 val16 += 8; 1470 val16 += 500; 1471 val32 += 8; 1472 val32 += 500; 1473 val32 += 70000; 1474 val64 += 8; 1475 val64 += 500; 1476 val64 += 70000; 1477 val64 += 0x8_0000_0000; 1478 } 1479 }; 1480 1481 1482 @TestInfo(&tester74) 1483 immutable test74 = q{--- test74 1484 // Test nested call expression 1485 struct GameMap; 1486 GameMap* pass_ptr_and_struct(GameMap* map) { 1487 return create_room(map, Rect(1,1,5,5)); 1488 } 1489 1490 struct Rect { 1491 i32 x1; 1492 i32 y1; 1493 i32 x2; 1494 i32 y2; 1495 } 1496 1497 GameMap* create_room(GameMap* map, Rect room) { 1498 return map; 1499 } 1500 }; 1501 void tester74(ref TestContext ctx) { 1502 ubyte b; 1503 auto pass_ptr_and_struct = ctx.getFunctionPtr!(ubyte*, ubyte*)("pass_ptr_and_struct"); 1504 assert(pass_ptr_and_struct(&b) == &b); 1505 } 1506 1507 1508 @TestInfo(&tester75) 1509 immutable test75 = q{--- test75 1510 // Test for loop 1511 i32 sum(i32[] numbers) { 1512 i32 sum = 0; 1513 for (u32 i = 0; i < numbers.length; ++i) 1514 { 1515 sum += numbers[i]; 1516 } 1517 return sum; 1518 } 1519 void loops1() { 1520 i32 outer1; 1521 i32 outer2; 1522 for (;;) break; 1523 for (i32 i;;) break; 1524 for (i32 i, i32 j, i32 k = 8;;) break; 1525 for (;outer1 == 0;) break; 1526 for (;;outer1 = 0, outer2 = 10) break; 1527 } 1528 }; 1529 void tester75(ref TestContext ctx) { 1530 int[10] nums = [1,2,3,4,5,6,7,8,9,10]; 1531 auto sum = ctx.getFunctionPtr!(int, Slice!int)("sum"); 1532 assert(sum(Slice!int(nums[])) == 55); 1533 } 1534 1535 1536 @TestInfo(&tester76) 1537 immutable test76 = q{--- test76 1538 // Test for loop break avoiding increments block 1539 i32 test_for() { 1540 i32 outer; 1541 for (;;outer = 10) break; 1542 return outer; // must return 0, not 10 1543 } 1544 }; 1545 void tester76(ref TestContext ctx) { 1546 auto test_for = ctx.getFunctionPtr!(int)("test_for"); 1547 assert(test_for() == 0); 1548 } 1549 1550 @TestInfo() 1551 immutable test77 = q{--- test77 1552 // 1553 struct Tile { 1554 bool blocked; 1555 bool block_sight; 1556 } 1557 1558 struct GameMap { 1559 enum map_width = 40; 1560 enum map_height = 40; 1561 Tile[40][40] tiles; 1562 } 1563 1564 void initialize_tiles(GameMap* map) { 1565 for (i32 y = 0; y < map.map_height; ++y) { 1566 for (i32 x = 0; x < map.map_width; ++x) { 1567 map.tiles[y][x].blocked = true; 1568 map.tiles[y][x].block_sight = true; 1569 } 1570 } 1571 } 1572 }; 1573 1574 @TestInfo(&tester78) 1575 immutable test78 = q{--- test78 1576 // Bug: division by small constant generated BYTE idiv, instead of DWORD 1577 i64 test_div(i64 i, u8[] res) { 1578 res[0] = cast(u8)(i % 10); 1579 i /= 10; 1580 res[1] = cast(u8)(i % 10); 1581 return i; 1582 } 1583 }; 1584 void tester78(ref TestContext ctx) { 1585 auto test_div = ctx.getFunctionPtr!(long, long, Slice!ubyte)("test_div"); 1586 ubyte[2] buf; 1587 assert(test_div(97, Slice!ubyte(buf[])) == 9); 1588 assert(buf[] == [7, 9]); 1589 } 1590 1591 @TestInfo(&tester79) 1592 immutable test79 = q{--- test79 1593 // test null to slice conversion 1594 void receive(u8[]) {} 1595 u8[] make() { 1596 receive(null); 1597 return null; 1598 } 1599 }; 1600 void tester79(ref TestContext ctx) { 1601 auto make = ctx.getFunctionPtr!(Slice!ubyte)("make"); 1602 assert(make() == null); 1603 } 1604 1605 @TestInfo(&tester80) 1606 immutable test80 = q{--- test80 1607 // integer types .min, .max properties 1608 u8 u8min() { return u8.min; } 1609 u16 u16min() { return u16.min; } 1610 u32 u32min() { return u32.min; } 1611 u64 u64min() { return u64.min; } 1612 u8 u8max() { return u8.max; } 1613 u16 u16max() { return u16.max; } 1614 u32 u32max() { return u32.max; } 1615 u64 u64max() { return u64.max; } 1616 i8 i8min() { return i8.min; } 1617 i16 i16min() { return i16.min; } 1618 i32 i32min() { return i32.min; } 1619 i64 i64min() { return i64.min; } 1620 i8 i8max() { return i8.max; } 1621 i16 i16max() { return i16.max; } 1622 i32 i32max() { return i32.max; } 1623 i64 i64max() { return i64.max; } 1624 }; 1625 void tester80(ref TestContext ctx) { 1626 assert(ctx.getFunctionPtr!(ubyte)("u8min")() == ubyte.min); 1627 assert(ctx.getFunctionPtr!(ushort)("u16min")() == ushort.min); 1628 assert(ctx.getFunctionPtr!(uint)("u32min")() == uint.min); 1629 assert(ctx.getFunctionPtr!(ulong)("u64min")() == ulong.min); 1630 assert(ctx.getFunctionPtr!(ubyte)("u8max")() == ubyte.max); 1631 assert(ctx.getFunctionPtr!(ushort)("u16max")() == ushort.max); 1632 assert(ctx.getFunctionPtr!(uint)("u32max")() == uint.max); 1633 assert(ctx.getFunctionPtr!(ulong)("u64max")() == ulong.max); 1634 assert(ctx.getFunctionPtr!(byte)("i8min")() == byte.min); 1635 assert(ctx.getFunctionPtr!(short)("i16min")() == short.min); 1636 assert(ctx.getFunctionPtr!(int)("i32min")() == int.min); 1637 assert(ctx.getFunctionPtr!(long)("i64min")() == long.min); 1638 assert(ctx.getFunctionPtr!(byte)("i8max")() == byte.max); 1639 assert(ctx.getFunctionPtr!(short)("i16max")() == short.max); 1640 assert(ctx.getFunctionPtr!(int)("i32max")() == int.max); 1641 assert(ctx.getFunctionPtr!(long)("i64max")() == long.max); 1642 } 1643 1644 1645 @TestInfo(&tester81) 1646 immutable test81 = q{--- test81 1647 // Test mov of 64bit constant into memory 1648 void run(i64* ptr) { *ptr = i64.max; } 1649 }; 1650 void tester81(ref TestContext ctx) { 1651 long val = 0; 1652 ctx.getFunctionPtr!(void, long*)("run")(&val); 1653 assert(val == long.max); 1654 } 1655 1656 1657 @TestInfo() 1658 immutable test82 = q{--- test82 1659 // Bug 1660 void test() 1661 { 1662 for (u32 roomIndex = 0; roomIndex < 20; ++roomIndex) 1663 { 1664 for (u32 otherRoom = 0; otherRoom < roomIndex; ++otherRoom) 1665 { 1666 if (otherRoom < roomIndex) { 1667 break; 1668 } 1669 } 1670 } 1671 } 1672 }; 1673 1674 @TestInfo(&tester83) 1675 immutable test83 = q{--- test83 1676 // using enum as array size 1677 // constant folding in static expressions 1678 // test forward references too 1679 1680 // use static array length in constant folded expression 1681 enum combined_enums = cast(u64)arr_size3 + arrBackref.length; 1682 i32[combined_enums] arrBackrefX; 1683 u64 combinedEnums() { return arrBackrefX.length; } // 16 1684 1685 enum arr_size = 4; 1686 i32[arr_size] arrBackref; 1687 u64 getSize1() { return arrBackref.length; } // 4 1688 1689 u64 testBackref() { 1690 i32[arr_size] local_arr; 1691 return local_arr.length; // 4 1692 } 1693 1694 i32[arr_size2] arrForwardref; 1695 u64 getSize2() { return arrForwardref.length; } // 7 1696 1697 u64 testForwardref() { 1698 i32[arr_size2] local_arr; 1699 return local_arr.length; // 7 1700 } 1701 1702 enum arr_size2 = 7; 1703 1704 i32[arr_size3 + 4] arrForwardref2; 1705 u64 getSize3() { return arrForwardref2.length; } // 16 1706 1707 u64 testForwardref2() { 1708 i32[arr_size3 + 10] local_arr; 1709 return local_arr.length; // 22 1710 } 1711 1712 enum arr_size3 = 12; 1713 }; 1714 void tester83(ref TestContext ctx) { 1715 assert(ctx.getFunctionPtr!ulong("combinedEnums")() == 16); 1716 assert(ctx.getFunctionPtr!ulong("getSize1")() == 4); 1717 assert(ctx.getFunctionPtr!ulong("testBackref")() == 4); 1718 assert(ctx.getFunctionPtr!ulong("getSize2")() == 7); 1719 assert(ctx.getFunctionPtr!ulong("testForwardref")() == 7); 1720 assert(ctx.getFunctionPtr!ulong("getSize3")() == 16); 1721 assert(ctx.getFunctionPtr!ulong("testForwardref2")() == 22); 1722 } 1723 1724 @TestInfo(&tester84) 1725 immutable test84 = q{--- test84 1726 // check nested array length is set correctly 1727 i32[40][30] arr; 1728 u64 nestedArrLen() { return arr[0].length; } // 40 1729 }; 1730 void tester84(ref TestContext ctx) { 1731 assert(ctx.getFunctionPtr!ulong("nestedArrLen")() == 40); 1732 } 1733 1734 @TestInfo(&tester85) 1735 immutable test85 = q{--- test85 1736 // UFCS without parenthesis 1737 i32 static_func0() { return 42; } 1738 void static_func_void() {} 1739 i32 static_func1(i32 num) { return num; } 1740 i32 static_func2(i32 num, i32 num2) { return num + num2; } 1741 i32 test0() { 1742 static_func_void; 1743 return static_func0; 1744 } 1745 i32 test1(i32 num) { 1746 return num.static_func1; 1747 } 1748 i32 test2(i32 num, i32 num2) { 1749 return num.static_func2(num2); 1750 } 1751 }; 1752 void tester85(ref TestContext ctx) { 1753 assert(ctx.getFunctionPtr!(int)("test0")() == 42); 1754 assert(ctx.getFunctionPtr!(int, int)("test1")(42) == 42); 1755 assert(ctx.getFunctionPtr!(int, int, int)("test2")(42, 24) == 66); 1756 } 1757 1758 @TestInfo() 1759 immutable test86 = q{--- test86 1760 // alias type 1761 alias T = i32; 1762 T num = 2; 1763 T test(T t) { return t; } 1764 1765 struct S { i32 member; } 1766 alias U = S; 1767 void test2() { 1768 U s; 1769 s.member = 10; 1770 } 1771 1772 alias funcAlias = test; // function alias 1773 T test3() { return funcAlias(30); } 1774 1775 alias varAlias = num; // variable alias 1776 T test4() { return varAlias; } 1777 1778 alias aliasOfAlias = varAlias; // alias of alias 1779 T test5() { return aliasOfAlias; } 1780 1781 enum enumVal = 42; 1782 alias enumAlias = enumVal; // enum alias 1783 T test6() { return enumAlias; } 1784 1785 alias Ptr = i32*; 1786 alias HANDLE = void*; 1787 alias alias_bool = bool; 1788 enum ptrsize = i32*.sizeof; 1789 enum u8min = u8.max; 1790 u8[u8min] arr; 1791 u8[ptrsize] arr2; 1792 }; 1793 1794 @TestInfo(&tester87) 1795 immutable test87 = q{--- test87 1796 // pointer type expr parsing 1797 enum ptrsize = i32*.sizeof; 1798 enum ptrsize2 = i32**.sizeof; 1799 enum arrsize = i32[4].sizeof; 1800 struct S { i64 var; } // 8 1801 enum S_ptrsize = S*.sizeof; 1802 enum S_ptrsize2 = S**.sizeof; 1803 enum S_arrsize = S[4].sizeof; // 32 1804 S[S_arrsize] arr; // 256 1805 u64 S_sizeof() { return S.sizeof; } // 8 1806 u64 arr_sizeof() { return arr.sizeof; } // 256 1807 }; 1808 1809 void tester87(ref TestContext ctx) { 1810 assert(ctx.getFunctionPtr!(ulong)("S_sizeof")() == 8); 1811 assert(ctx.getFunctionPtr!(ulong)("arr_sizeof")() == 256); 1812 } 1813 1814 @TestInfo(&tester88) 1815 immutable test88 = q{--- test88 1816 // function pointer 1817 alias i32_funType = i32 function(); 1818 alias i32ptr_funType = i32* function(); 1819 enum i32_funType funPtrEnum = &i32Fun; 1820 enum i32 function() inlinefunPtrEnum = &i32Fun; 1821 // i32_funType funPtrGlobal = &i32Fun; // TODO: globals are uninitialized now 1822 // i32 function() inlinefunPtrGlobal = &i32Fun; // TODO: globals are uninitialized now 1823 i32 i32Fun() { 1824 return 42; 1825 } 1826 i32_funType retFuncPtr() { 1827 return &i32Fun; 1828 } 1829 i32 test() { 1830 i32_funType funPtr = retFuncPtr(); // call by ptr (may be optimized to direct call later) 1831 i32 function() inlinefunPtr = &i32Fun; // direct call 1832 return funPtr() + inlinefunPtr(); 1833 } 1834 i32 test2() { 1835 return funPtrEnum() + inlinefunPtrEnum(); // direct call is performed 1836 } 1837 i32 sum(i32 a, i32 b) { return a + b; } 1838 // pass ptr to function with parameters 1839 i32 callFunc(i32 function(i32, i32) func, i32 a, i32 b) { 1840 return func(a, b); 1841 } 1842 i32 test3() { 1843 return callFunc(&sum, 10, 40); 1844 } 1845 i32 callFunc2(i32 a1, i32 a2, i32 a3, i32 a4, i32 a5, i32 a6, i32 function(i32, i32) func) { 1846 return func(a1, a2); 1847 } 1848 // test push function address 1849 i32 test4() { 1850 return callFunc2(1, 2, 3, 4, 5, 6, &sum); 1851 } 1852 }; 1853 void tester88(ref TestContext ctx) { 1854 assert(ctx.getFunctionPtr!(int)("test")() == 84); 1855 assert(ctx.getFunctionPtr!(int)("test2")() == 84); 1856 assert(ctx.getFunctionPtr!(int)("test3")() == 50); 1857 assert(ctx.getFunctionPtr!(int)("test4")() == 3); 1858 } 1859 1860 @TestInfo() 1861 immutable test89 = q{--- test89 1862 // function pointer as parameter 1863 void tran_thong(i32 xstart, i32 ystart, i32 xend, i32 yend, void function(void*, i32, i32) callback) 1864 {} 1865 }; 1866 1867 @TestInfo(&tester90) 1868 immutable test90 = q{--- test90 1869 void setRangeu8(u8* slice, u64 from, u64 to, u8 value) { 1870 while(from < to) { 1871 slice[from] = value; 1872 ++from; 1873 } 1874 } 1875 void formatInt(i64 i, u8[21]* output, u32 minSize, u8[]* result) 1876 { 1877 u32 numDigits = 0; 1878 if (i == 0) 1879 { 1880 if (minSize == 0) 1881 minSize = 1; 1882 setRangeu8((*output).ptr, 21 - minSize, 21, '0'); 1883 (*output)[20] = '0'; 1884 numDigits = minSize; 1885 } 1886 else 1887 { 1888 bool neg = i < 0; 1889 if (neg) { 1890 i = -i; 1891 } 1892 bool overflow = i < 0; 1893 if (overflow) 1894 i = i64.max; 1895 1896 while (i) 1897 { 1898 u8 c = cast(u8)('0' + i % 10); 1899 (*output)[21 - ++numDigits] = c; 1900 i /= 10; 1901 } 1902 1903 while (numDigits < minSize) { 1904 (*output)[21 - ++numDigits] = '0'; 1905 } 1906 1907 if (neg) { 1908 (*output)[21 - ++numDigits] = '-'; 1909 } 1910 if (overflow) { 1911 ++(*output)[20]; 1912 } 1913 } 1914 (*result).ptr = (*output).ptr + (21 - numDigits); 1915 (*result).length = numDigits; 1916 } 1917 }; 1918 void tester90(ref TestContext ctx) { 1919 auto setRangeu8 = ctx.getFunctionPtr!(void, char*, ulong, ulong, char)("setRangeu8"); 1920 1921 char[23] buf; 1922 buf[] = 'z'; 1923 1924 setRangeu8(&buf[1], 0, 21, 'x'); 1925 setRangeu8(&buf[1], 0, 1, '0'); 1926 setRangeu8(&buf[1], 20, 21, '1'); 1927 assert(buf == "z0xxxxxxxxxxxxxxxxxxx1z"); 1928 1929 auto formatInt = ctx.getFunctionPtr!(void, long, char*, uint, Slice!char*)("formatInt"); 1930 1931 void testFormatInt(long num, string expectedBuf, string expectedResult) { 1932 buf[] = 'x'; 1933 Slice!char result; 1934 formatInt(num, &buf[1], 0, &result); 1935 //writefln("buf ptr %s len %s ptr %s %s", buf.ptr, result.length, result.ptr, buf); 1936 assert(buf == expectedBuf); 1937 assert(result.slice == expectedResult); 1938 } 1939 1940 testFormatInt( 0, "xxxxxxxxxxxxxxxxxxxxx0x", "0"); 1941 testFormatInt( 1, "xxxxxxxxxxxxxxxxxxxxx1x", "1"); 1942 testFormatInt( 10, "xxxxxxxxxxxxxxxxxxxx10x", "10"); 1943 testFormatInt(-10, "xxxxxxxxxxxxxxxxxxx-10x", "-10"); 1944 testFormatInt(long.min, "xx-9223372036854775808x", "-9223372036854775808"); 1945 testFormatInt(long.max, "xxx9223372036854775807x", "9223372036854775807"); 1946 } 1947 1948 1949 @TestInfo(&tester91) 1950 immutable test91 = q{--- test91 1951 // splitting and spilling 1952 void tran_thong(i32 xstart, i32 ystart, i32 xend, i32 yend, void function(void*, i32, i32) callback, void* userData) 1953 { 1954 i32 x = xstart; 1955 i32 y = ystart; 1956 1957 i32 deltax; 1958 i32 signdx; 1959 if (xend >= xstart) { 1960 deltax = xend - xstart; 1961 signdx = 1; 1962 } else { 1963 deltax = xstart - xend; 1964 signdx = -1; 1965 } 1966 1967 i32 deltay; 1968 i32 signdy; 1969 if (yend >= ystart) { 1970 deltay = yend - ystart; 1971 signdy = 1; 1972 } else { 1973 deltay = ystart - yend; 1974 signdy = -1; 1975 } 1976 1977 callback(userData, x, y); 1978 1979 i32 test; 1980 if (signdy == -1) 1981 test = -1; 1982 else 1983 test = 0; 1984 1985 if (deltax >= deltay) { 1986 test = (deltax + test) >> 1; 1987 for (i32 i = 1; i < deltax; ++i) { 1988 test -= deltay; 1989 x += signdx; 1990 if (test < 0) { 1991 y += signdy; 1992 test += deltax; 1993 } 1994 callback(userData, x, y); 1995 } 1996 } else { 1997 test = (deltay + test) >> 1; 1998 for (i32 i = 1; i < deltay; ++i) { 1999 test -= deltax; 2000 y += signdy; 2001 if (test < 0) { 2002 x += signdx; 2003 test += deltay; 2004 } 2005 callback(userData, x, y); 2006 } 2007 } 2008 callback(userData, xend, yend); 2009 } 2010 }; 2011 void tester91(ref TestContext ctx) { 2012 static struct test91_user_data { 2013 string text; 2014 size_t i; 2015 } 2016 static extern(C) void external_print_coords_func(void* userData, int x, int y) { 2017 auto data = cast(test91_user_data*)userData; 2018 if (data.i > 0) testSink.put(", "); 2019 formattedWrite(testSink, "(%s %s %s)", data.text, x, y); 2020 ++data.i; 2021 } 2022 alias func_T = extern(C) void function(void*, int, int); 2023 auto tran_thong = ctx.getFunctionPtr!(void, int, int, int, int, func_T, void*)("tran_thong"); 2024 2025 test91_user_data data = { 2026 text : "hi" 2027 }; 2028 2029 tran_thong(0, 0, 2, 2, &external_print_coords_func, &data); 2030 2031 //writefln("%s", testSink.text); 2032 assert(testSink.text == "(hi 0 0), (hi 1 1), (hi 2 2)"); 2033 } 2034 2035 @TestInfo(&tester92) 2036 immutable test92 = q{--- test92 2037 // struct methods 2038 struct Struct { 2039 i32 member; 2040 void set42() { 2041 this.member += 42; 2042 member = 42; 2043 } 2044 void set(i32 par) { 2045 member = par; 2046 this.member = par; 2047 } 2048 void set2() { 2049 set42(); // pass this 2050 } 2051 void set3() { 2052 set42; // pass this 2053 } 2054 void set4() { 2055 this.set42; // explicit this 2056 } 2057 void set5() { 2058 this.set42(); // explicit this 2059 } 2060 void set6() { 2061 set(42); // pass this 2062 } 2063 } 2064 i32 testMethod1() { 2065 Struct s; 2066 s.set42(); // take address 2067 return s.member; 2068 } 2069 i32 testMethod2(i32 val) { 2070 Struct s; 2071 s.set(val); // take address 2072 return s.member; 2073 } 2074 i32 testMethod3() { 2075 Struct s; 2076 s.set42; // take address 2077 return s.member; 2078 } 2079 i32 testMethod4() { 2080 Struct s; 2081 Struct* sptr = &s; 2082 sptr.set42; // call method on pointer 2083 return sptr.member; 2084 } 2085 i32 testMethod5() { 2086 Struct[1] s; 2087 s[0].set42; // call method on index expr 2088 s[0].set42(); 2089 s[0].set(42); 2090 return s[0].member; 2091 } 2092 i32 testMethodToMethod2() { 2093 Struct s = Struct(10); // reset stack value for future tests 2094 s.set2; 2095 return s.member; 2096 } 2097 i32 testMethodToMethod3() { 2098 Struct s = Struct(10); // reset stack value for future tests 2099 s.set3; 2100 return s.member; 2101 } 2102 i32 testMethodToMethod4() { 2103 Struct s = Struct(10); // reset stack value for future tests 2104 s.set4; 2105 return s.member; 2106 } 2107 i32 testMethodToMethod5() { 2108 Struct s = Struct(10); // reset stack value for future tests 2109 s.set5; 2110 return s.member; 2111 } 2112 i32 testMethodToMethod6() { 2113 Struct s = Struct(10); // reset stack value for future tests 2114 s.set6; 2115 return s.member; 2116 } 2117 }; 2118 void tester92(ref TestContext ctx) { 2119 assert(ctx.getFunctionPtr!(int)("testMethod1")() == 42); 2120 assert(ctx.getFunctionPtr!(int, int)("testMethod2")(60) == 60); 2121 assert(ctx.getFunctionPtr!(int)("testMethod3")() == 42); 2122 assert(ctx.getFunctionPtr!(int)("testMethod4")() == 42); 2123 assert(ctx.getFunctionPtr!(int)("testMethod5")() == 42); 2124 assert(ctx.getFunctionPtr!(int)("testMethodToMethod2")() == 42); 2125 assert(ctx.getFunctionPtr!(int)("testMethodToMethod3")() == 42); 2126 assert(ctx.getFunctionPtr!(int)("testMethodToMethod4")() == 42); 2127 assert(ctx.getFunctionPtr!(int)("testMethodToMethod5")() == 42); 2128 assert(ctx.getFunctionPtr!(int)("testMethodToMethod6")() == 42); 2129 } 2130 2131 @TestInfo() 2132 immutable test93 = q{--- test93 2133 // empty string literal 2134 void print(u8[]){} 2135 void run(){ 2136 print(""); 2137 } 2138 }; 2139 2140 @TestInfo(&tester94) 2141 immutable test94 = q{--- test94 2142 // return small struct 2143 struct Small { 2144 i32 a; 2145 i32 b; 2146 } 2147 Small glue(i32 a, i32 b) 2148 { 2149 return Small(a, b); 2150 } 2151 }; 2152 void tester94(ref TestContext ctx) { 2153 static struct Small { 2154 int a; 2155 int b; 2156 } 2157 assert(ctx.getFunctionPtr!(Small, int, int)("glue")(42, 100) == Small(42, 100)); 2158 } 2159 2160 2161 @TestInfo(&tester95) 2162 immutable test95 = q{--- test95 2163 // if callback returns true the traversal stops 2164 void tran_thong(i32 xstart, i32 ystart, i32 xend, i32 yend, bool function(void*, i32, i32) callback, void* userData) 2165 { 2166 i32 x = xstart; 2167 i32 y = ystart; 2168 2169 if (callback(userData, x, y)) return; 2170 2171 i32 deltax; 2172 i32 signdx; 2173 if (xend >= xstart) { 2174 deltax = xend - xstart; 2175 signdx = 1; 2176 } else { 2177 deltax = xstart - xend; 2178 signdx = -1; 2179 } 2180 2181 i32 deltay; 2182 i32 signdy; 2183 if (yend >= ystart) { 2184 deltay = yend - ystart; 2185 signdy = 1; 2186 } else { 2187 deltay = ystart - yend; 2188 signdy = -1; 2189 } 2190 2191 i32 test; 2192 if (signdy == -1) 2193 test = -1; 2194 else 2195 test = 0; 2196 2197 if (deltax >= deltay) { 2198 test = (deltax + test) >> 1; 2199 for (i32 i = 1; i < deltax; ++i) { 2200 test -= deltay; 2201 x += signdx; 2202 if (test < 0) { 2203 y += signdy; 2204 test += deltax; 2205 } 2206 if (callback(userData, x, y)) return; 2207 } 2208 } else { 2209 test = (deltay + test) >> 1; 2210 for (i32 i = 1; i < deltay; ++i) { 2211 test -= deltax; 2212 y += signdy; 2213 if (test < 0) { 2214 x += signdx; 2215 test += deltay; 2216 } 2217 if (callback(userData, x, y)) return; 2218 } 2219 } 2220 if (callback(userData, xend, yend)) return; 2221 } 2222 }; 2223 void tester95(ref TestContext ctx) { 2224 static struct test95_user_data { 2225 string text; 2226 size_t i; 2227 size_t breakIndex; 2228 } 2229 static extern(C) bool external_print_coords_func(void* userData, int x, int y) { 2230 auto data = cast(test95_user_data*)userData; 2231 if (data.i > 0) testSink.put(", "); 2232 formattedWrite(testSink, "(%s %s %s)", data.text, x, y); 2233 if (data.breakIndex == data.i) return true; 2234 ++data.i; 2235 return false; 2236 } 2237 2238 alias func_T = extern(C) bool function(void*, int, int); 2239 auto tran_thong = ctx.getFunctionPtr!(void, int, int, int, int, func_T, void*)("tran_thong"); 2240 2241 void runTest(size_t breakIndex, string expectedString) 2242 { 2243 test95_user_data data; 2244 data = test95_user_data("hi", 0, breakIndex); 2245 tran_thong(0, 0, 3, 3, &external_print_coords_func, &data); 2246 //writefln("%s", testSink.text); 2247 assert(testSink.text == expectedString); 2248 testSink.clear; 2249 } 2250 2251 runTest(0, "(hi 0 0)"); 2252 runTest(1, "(hi 0 0), (hi 1 1)"); 2253 runTest(2, "(hi 0 0), (hi 1 1), (hi 2 2)"); 2254 runTest(3, "(hi 0 0), (hi 1 1), (hi 2 2), (hi 3 3)"); 2255 runTest(4, "(hi 0 0), (hi 1 1), (hi 2 2), (hi 3 3)"); 2256 } 2257 2258 @TestInfo(&tester96) 2259 immutable test96 = q{--- test96 2260 // splitting and spilling 2261 void tran_thong(i32 xstart, i32 ystart, i32 xend, i32 yend, void function(void*, i32, i32) callback, void* userData) 2262 { 2263 i32 x = xstart; 2264 i32 y = ystart; 2265 2266 i32 deltax; 2267 i32 signdx; 2268 if (xend >= xstart) { 2269 deltax = xend - xstart; 2270 signdx = 1; 2271 } else { 2272 deltax = xstart - xend; 2273 signdx = -1; 2274 } 2275 2276 i32 deltay; 2277 i32 signdy; 2278 if (yend >= ystart) { 2279 deltay = yend - ystart; 2280 signdy = 1; 2281 } else { 2282 deltay = ystart - yend; 2283 signdy = -1; 2284 } 2285 2286 i32 test; 2287 if (signdy == -1) 2288 test = -1; 2289 else 2290 test = 0; 2291 2292 if (deltax >= deltay) { 2293 test = (deltax + test) >> 1; 2294 for (i32 i = 1; i < deltax; ++i) { 2295 test -= deltay; 2296 x += signdx; 2297 if (test < 0) { 2298 y += signdy; 2299 test += deltax; 2300 } 2301 callback(userData, x, y); 2302 } 2303 } else { 2304 test = (deltay + test) >> 1; 2305 for (i32 i = 1; i < deltay; ++i) { 2306 test -= deltax; 2307 y += signdy; 2308 if (test < 0) { 2309 x += signdx; 2310 test += deltay; 2311 } 2312 callback(userData, x, y); 2313 } 2314 } 2315 } 2316 }; 2317 void tester96(ref TestContext ctx) { 2318 static struct test96_user_data { 2319 string text; 2320 size_t i; 2321 } 2322 static extern(C) void external_print_coords_func(void* userData, int x, int y) { 2323 auto data = cast(test96_user_data*)userData; 2324 if (data.i > 0) testSink.put(", "); 2325 formattedWrite(testSink, "(%s %s %s)", data.text, x, y); 2326 ++data.i; 2327 } 2328 alias func_T = extern(C) void function(void*, int, int); 2329 auto tran_thong = ctx.getFunctionPtr!(void, int, int, int, int, func_T, void*)("tran_thong"); 2330 2331 test96_user_data data = { 2332 text : "hi" 2333 }; 2334 2335 tran_thong(0, 0, 2, 2, &external_print_coords_func, &data); 2336 2337 //writefln("%s", testSink.text); 2338 assert(testSink.text == "(hi 1 1)"); 2339 } 2340 2341 @TestInfo(&tester97) 2342 immutable test97 = q{--- test97 2343 // test proper GEP lowering for stack allocated data 2344 // stack argument of add instruction should be detected and lea instruction must be produced 2345 i32 index_array(i32 index) 2346 { 2347 i32[10] array; 2348 array[index] = 42; 2349 return array[index]; 2350 } 2351 }; 2352 void tester97(ref TestContext ctx) { 2353 auto index_array = ctx.getFunctionPtr!(int, int)("index_array"); 2354 2355 assert(index_array(0) == 42); 2356 assert(index_array(9) == 42); 2357 } 2358 2359 @TestInfo() 2360 immutable test98 = q{--- folder/test98.vx 2361 import dep98; 2362 // test module name creation. Folders must be stripped 2363 void test() 2364 { 2365 libfunc(); 2366 } 2367 --- folder/dep98.vx 2368 void libfunc(){} 2369 }; 2370 2371 @TestInfo(&tester99) 2372 immutable test99 = `--- test99 2373 // test #if 2374 enum valTrue = true; 2375 enum valFalse = false; 2376 2377 // global scope 2378 #if(valTrue) 2379 i32 foo() { return 42; } // no else 2380 2381 #if(valFalse) 2382 i32 foo() { return 42; } // no items to insert 2383 2384 #if(valTrue){} // empty 2385 2386 // curly braces 2387 #if(valFalse) 2388 { 2389 i32 bar() { return 42; } 2390 } 2391 else // insert more than 1 item 2392 { 2393 i32 bar() { return 100; } 2394 i32 bar2() { return 200; } 2395 } 2396 2397 // function scope 2398 i32 funcTrue() { 2399 #if(valTrue) 2400 return 42; 2401 else 2402 return 100; 2403 } 2404 2405 i32 funcFalse() { 2406 #if(valFalse) 2407 return 42; 2408 else 2409 return 100; 2410 } 2411 `; 2412 void tester99(ref TestContext ctx) { 2413 auto foo = ctx.getFunctionPtr!(int)("foo"); 2414 auto bar = ctx.getFunctionPtr!(int)("bar"); 2415 auto bar2 = ctx.getFunctionPtr!(int)("bar2"); 2416 auto funcTrue = ctx.getFunctionPtr!(int)("funcTrue"); 2417 auto funcFalse = ctx.getFunctionPtr!(int)("funcFalse"); 2418 2419 assert(foo() == 42); 2420 assert(bar() == 100); 2421 assert(bar2() == 200); 2422 assert(funcTrue() == 42); 2423 assert(funcFalse() == 100); 2424 } 2425 2426 @TestInfo() 2427 immutable test100 = `--- test100 2428 enum a = true; 2429 #if (a) 2430 enum b = true; 2431 2432 void main() 2433 { 2434 #if (b) enum c = 42; // requires #if (a) to be evalauated first 2435 } 2436 `; 2437 2438 @TestInfo() 2439 immutable test101 = `--- test101 2440 enum a = true; 2441 enum b = true; 2442 #if (a) 2443 { 2444 #if (b) enum c = true; 2445 } 2446 2447 void main() 2448 { 2449 #if (c) enum d = 42; // requires #if (b) to be evalauated first 2450 } 2451 `; 2452 2453 @TestInfo() 2454 immutable test102 = q{--- test102 2455 // test taking address of members 2456 struct S { 2457 u64 member; 2458 void method() { 2459 func(&member); 2460 } 2461 } 2462 void func(u64* ptr) {} 2463 }; 2464 2465 @TestInfo() 2466 immutable test103 = q{--- test103 2467 // test loading of pointers in member chains 2468 struct A { 2469 u64 member; 2470 } 2471 struct S { 2472 A* a; 2473 } 2474 void func() { 2475 S s; 2476 s.a.member = 42; 2477 } 2478 }; 2479 2480 @TestInfo(&tester104) 2481 immutable test104 = q{--- test104 2482 // cast int to int 2483 i16 fold__i8_to_i16_sext() { return cast(i16)cast( i8)-1; } // sext i8 -> i16 2484 i32 fold__i8_to_i32_sext() { return cast(i32)cast( i8)-1; } // sext i8 -> i32 2485 i32 fold_i16_to_i32_sext() { return cast(i32)cast(i16)-1; } // sext i16 -> i32 2486 i64 fold__i8_to_i64_sext() { return cast(i64)cast( i8)-1; } // sext i8 -> i64 2487 i64 fold_i16_to_i64_sext() { return cast(i64)cast(i16)-1; } // sext i16 -> i64 2488 i64 fold_i32_to_i64_sext() { return cast(i64)cast(i32)-1; } // sext i32 -> i64 2489 2490 i16 fold__u8_to_i16_zext() { return cast(i16)cast( u8)u8.max; } // zext u8 -> i16 2491 i32 fold__u8_to_i32_zext() { return cast(i32)cast( u8)u8.max; } // zext u8 -> i32 2492 i32 fold_u16_to_i32_zext() { return cast(i32)cast(u16)u16.max; } // zext u16 -> i32 2493 i64 fold__u8_to_i64_zext() { return cast(i64)cast( u8)u8.max; } // zext u8 -> i64 2494 i64 fold_u16_to_i64_zext() { return cast(i64)cast(u16)u16.max; } // zext u16 -> i64 2495 i64 fold_u32_to_i64_zext() { return cast(i64)cast(u32)u32.max; } // zext u32 -> i64 2496 2497 u16 fold__u8_to_u16_zext() { return cast(u16)cast( u8)u8.max; } // zext u8 -> u16 2498 u32 fold__u8_to_u32_zext() { return cast(u32)cast( u8)u8.max; } // zext u8 -> u32 2499 u32 fold_u16_to_u32_zext() { return cast(u32)cast(u16)u16.max; } // zext u16 -> u32 2500 u64 fold__u8_to_u64_zext() { return cast(u64)cast( u8)u8.max; } // zext u8 -> u64 2501 u64 fold_u16_to_u64_zext() { return cast(u64)cast(u16)u16.max; } // zext u16 -> u64 2502 u64 fold_u32_to_u64_zext() { return cast(u64)cast(u32)u32.max; } // zext u32 -> u64 2503 2504 u16 fold__i8_to_u16_zext() { return cast(u16)i8.min; } // zext i8 -> u16 TODO: these should error without cast 2505 u32 fold__i8_to_u32_zext() { return cast(u32)i8.min; } // zext i8 -> u32 TODO: these should error without cast 2506 u32 fold_i16_to_u32_zext() { return cast(u32)i16.min; } // zext i16 -> u32 TODO: these should error without cast 2507 u64 fold__i8_to_u64_zext() { return cast(u64)i8.min; } // zext i8 -> u64 TODO: these should error without cast 2508 u64 fold_i16_to_u64_zext() { return cast(u64)i16.min; } // zext i16 -> u64 TODO: these should error without cast 2509 u64 fold_i32_to_u64_zext() { return cast(u64)i32.min; } // zext i32 -> u64 TODO: these should error without cast 2510 2511 2512 i16 func__i8_to_i16( i8 a) { return a; } // sext i8 -> i16 2513 i32 func__i8_to_i32( i8 a) { return a; } // sext i8 -> i32 2514 i32 func_i16_to_i32(i16 a) { return a; } // sext i16 -> i32 2515 i64 func__i8_to_i64( i8 a) { return a; } // sext i8 -> i64 2516 i64 func_i16_to_i64(i16 a) { return a; } // sext i16 -> i64 2517 i64 func_i32_to_i64(i32 a) { return a; } // sext i32 -> i64 2518 2519 i16 func__u8_to_i16( u8 a) { return a; } // zext u8 -> i16 2520 i32 func__u8_to_i32( u8 a) { return a; } // zext u8 -> i32 2521 i32 func_u16_to_i32(u16 a) { return a; } // zext u16 -> i32 2522 i64 func__u8_to_i64( u8 a) { return a; } // zext u8 -> i64 2523 i64 func_u16_to_i64(u16 a) { return a; } // zext u16 -> i64 2524 i64 func_u32_to_i64(u32 a) { return a; } // zext u32 -> i64 2525 2526 u16 func__u8_to_u16( u8 a) { return a; } // zext u8 -> u16 2527 u32 func__u8_to_u32( u8 a) { return a; } // zext u8 -> u32 2528 u32 func_u16_to_u32(u16 a) { return a; } // zext u16 -> u32 2529 u64 func__u8_to_u64( u8 a) { return a; } // zext u8 -> u64 2530 u64 func_u16_to_u64(u16 a) { return a; } // zext u16 -> u64 2531 u64 func_u32_to_u64(u32 a) { return a; } // zext u32 -> u64 2532 2533 u16 func__i8_to_u16( i8 a) { return cast(u16)a; } // zext i8 -> u16 TODO: these should error without cast 2534 u32 func__i8_to_u32( i8 a) { return cast(u32)a; } // zext i8 -> u32 TODO: these should error without cast 2535 u32 func_i16_to_u32(i16 a) { return cast(u32)a; } // zext i16 -> u32 TODO: these should error without cast 2536 u64 func__i8_to_u64( i8 a) { return cast(u64)a; } // zext i8 -> u64 TODO: these should error without cast 2537 u64 func_i16_to_u64(i16 a) { return cast(u64)a; } // zext i16 -> u64 TODO: these should error without cast 2538 u64 func_i32_to_u64(i32 a) { return cast(u64)a; } // zext i32 -> u64 TODO: these should error without cast 2539 }; 2540 void tester104(ref TestContext ctx) { 2541 assert(ctx.getFunctionPtr!(short)("fold__i8_to_i16_sext")() == short(-1)); 2542 assert(ctx.getFunctionPtr!( int)("fold__i8_to_i32_sext")() == int(-1)); 2543 assert(ctx.getFunctionPtr!( int)("fold_i16_to_i32_sext")() == int(-1)); 2544 assert(ctx.getFunctionPtr!( long)("fold__i8_to_i64_sext")() == long(-1)); 2545 assert(ctx.getFunctionPtr!( long)("fold_i16_to_i64_sext")() == long(-1)); 2546 assert(ctx.getFunctionPtr!( long)("fold_i32_to_i64_sext")() == long(-1)); 2547 2548 assert(ctx.getFunctionPtr!(short)("fold__u8_to_i16_zext")() == ubyte.max); 2549 assert(ctx.getFunctionPtr!( int)("fold__u8_to_i32_zext")() == ubyte.max); 2550 assert(ctx.getFunctionPtr!( int)("fold_u16_to_i32_zext")() == ushort.max); 2551 assert(ctx.getFunctionPtr!( long)("fold__u8_to_i64_zext")() == ubyte.max); 2552 assert(ctx.getFunctionPtr!( long)("fold_u16_to_i64_zext")() == ushort.max); 2553 assert(ctx.getFunctionPtr!( long)("fold_u32_to_i64_zext")() == uint.max); 2554 2555 assert(ctx.getFunctionPtr!(ushort)("fold__u8_to_u16_zext")() == ubyte.max); 2556 assert(ctx.getFunctionPtr!( uint)("fold__u8_to_u32_zext")() == ubyte.max); 2557 assert(ctx.getFunctionPtr!( uint)("fold_u16_to_u32_zext")() == ushort.max); 2558 assert(ctx.getFunctionPtr!( ulong)("fold__u8_to_u64_zext")() == ubyte.max); 2559 assert(ctx.getFunctionPtr!( ulong)("fold_u16_to_u64_zext")() == ushort.max); 2560 assert(ctx.getFunctionPtr!( ulong)("fold_u32_to_u64_zext")() == uint.max); 2561 2562 //writefln("%08X", ctx.getFunctionPtr!(ushort)("fold__i8_to_u16_zext")()); 2563 assert(ctx.getFunctionPtr!(ushort)("fold__i8_to_u16_zext")() == ubyte(0x0000_0080)); 2564 assert(ctx.getFunctionPtr!( uint)("fold__i8_to_u32_zext")() == ubyte(0x0000_0080)); 2565 assert(ctx.getFunctionPtr!( uint)("fold_i16_to_u32_zext")() == ushort(0x0000_8000)); 2566 assert(ctx.getFunctionPtr!( ulong)("fold__i8_to_u64_zext")() == ubyte(0x0000_0080)); 2567 assert(ctx.getFunctionPtr!( ulong)("fold_i16_to_u64_zext")() == ushort(0x0000_8000)); 2568 assert(ctx.getFunctionPtr!( ulong)("fold_i32_to_u64_zext")() == uint(0x8000_0000)); 2569 2570 2571 assert(ctx.getFunctionPtr!(short, byte)("func__i8_to_i16")( byte(-1)) == short(-1)); 2572 assert(ctx.getFunctionPtr!( int, byte)("func__i8_to_i32")( byte(-1)) == int(-1)); 2573 assert(ctx.getFunctionPtr!( int, short)("func_i16_to_i32")( short(-1)) == int(-1)); 2574 assert(ctx.getFunctionPtr!( long, byte)("func__i8_to_i64")( byte(-1)) == long(-1)); 2575 assert(ctx.getFunctionPtr!( long, short)("func_i16_to_i64")( short(-1)) == long(-1)); 2576 assert(ctx.getFunctionPtr!( long, int)("func_i32_to_i64")( int(-1)) == long(-1)); 2577 2578 assert(ctx.getFunctionPtr!(short, ubyte)("func__u8_to_i16")( ubyte.max) == ubyte.max); 2579 assert(ctx.getFunctionPtr!( int, ubyte)("func__u8_to_i32")( ubyte.max) == ubyte.max); 2580 assert(ctx.getFunctionPtr!( int, ushort)("func_u16_to_i32")(ushort.max) == ushort.max); 2581 assert(ctx.getFunctionPtr!( long, ubyte)("func__u8_to_i64")( ubyte.max) == ubyte.max); 2582 assert(ctx.getFunctionPtr!( long, ushort)("func_u16_to_i64")(ushort.max) == ushort.max); 2583 assert(ctx.getFunctionPtr!( long, uint)("func_u32_to_i64")( uint.max) == uint.max); 2584 2585 assert(ctx.getFunctionPtr!(ushort, ubyte)("func__u8_to_u16")( ubyte.max) == ubyte.max); 2586 assert(ctx.getFunctionPtr!( uint, ubyte)("func__u8_to_u32")( ubyte.max) == ubyte.max); 2587 assert(ctx.getFunctionPtr!( uint, ushort)("func_u16_to_u32")(ushort.max) == ushort.max); 2588 assert(ctx.getFunctionPtr!( ulong, ubyte)("func__u8_to_u64")( ubyte.max) == ubyte.max); 2589 assert(ctx.getFunctionPtr!( ulong, ushort)("func_u16_to_u64")(ushort.max) == ushort.max); 2590 assert(ctx.getFunctionPtr!( ulong, uint)("func_u32_to_u64")( uint.max) == uint.max); 2591 2592 //writefln("%08X", ctx.getFunctionPtr!(ushort, byte)("func__i8_to_u16")( byte.min)); 2593 assert(ctx.getFunctionPtr!(ushort, byte)("func__i8_to_u16")( byte.min) == ubyte(0x0000_0080)); 2594 assert(ctx.getFunctionPtr!( uint, byte)("func__i8_to_u32")( byte.min) == ubyte(0x0000_0080)); 2595 assert(ctx.getFunctionPtr!( uint, short)("func_i16_to_u32")( short.min) == ushort(0x0000_8000)); 2596 assert(ctx.getFunctionPtr!( ulong, byte)("func__i8_to_u64")( byte.min) == ubyte(0x0000_0080)); 2597 assert(ctx.getFunctionPtr!( ulong, short)("func_i16_to_u64")( short.min) == ushort(0x0000_8000)); 2598 assert(ctx.getFunctionPtr!( ulong, int)("func_i32_to_u64")( int.min) == uint(0x8000_0000)); 2599 } 2600 2601 @TestInfo(&tester105) 2602 immutable test105 = q{--- test105 2603 // test struct constructor with default initialization 2604 struct Struct 2605 { 2606 i32 var = 42; 2607 void fun(){} 2608 i32 var2; 2609 } 2610 Struct get_struct() 2611 { 2612 Struct s = Struct(); 2613 return s; 2614 } 2615 // test struct constructor with nested struct initialization 2616 struct Struct2 2617 { 2618 u8[] str; 2619 } 2620 Struct2 get_struct2(u8[] str) 2621 { 2622 return Struct2(str); 2623 } 2624 }; 2625 void tester105(ref TestContext ctx) { 2626 struct Struct { int a; int b; } 2627 auto get_struct = ctx.getFunctionPtr!(Struct)("get_struct"); 2628 assert(get_struct() == Struct(42, 0)); 2629 2630 struct Struct2 { const(char)[] str; } 2631 auto get_struct2 = ctx.getFunctionPtr!(Struct2, SliceString)("get_struct2"); 2632 assert(get_struct2(SliceString("test")) == Struct2("test")); 2633 } 2634 2635 2636 @TestInfo(&tester106, [HostSymbol("fun2", cast(void*)&external_tester106)]) 2637 immutable test106 = q{--- test106 2638 // Test structs passed as pointer on the stack (win64 abi) (name parameter) 2639 // big struct on stack (sysv64) 2640 void fun(i32, i32, i32, u8, u8, u8, u8[] name, bool){ 2641 fun2(name); 2642 } 2643 @extern(module, "host") 2644 void fun2(u8[]); 2645 void run() 2646 { 2647 fun(50, 50, 32, 0, 255, 0, "Player", true); 2648 } 2649 }; 2650 extern(C) void external_tester106(Slice!char str) { 2651 assert(str == "Player"); 2652 } 2653 void tester106(ref TestContext ctx) { 2654 auto run = ctx.getFunctionPtr!(void)("run"); 2655 run(); 2656 } 2657 2658 2659 @TestInfo(&tester107) 2660 immutable test107 = q{--- test107 2661 // Test slicing 2662 i32[] slice_ptr1(i32* ptr) 2663 { 2664 return ptr[0..10]; 2665 } 2666 i32[] slice_ptr2(i32* ptr, u64 from, u64 to) 2667 { 2668 return ptr[from..to]; 2669 } 2670 i32[] slice_array1(i32[10]* ptr) 2671 { 2672 return (*ptr)[0..10]; 2673 } 2674 i32[] slice_array2(i32[10]* ptr, u64 from, u64 to) 2675 { 2676 return (*ptr)[from..to]; 2677 } 2678 i32[] slice_slice1(i32[] ptr) 2679 { 2680 return ptr[0..10]; 2681 } 2682 i32[] slice_slice2(i32[] ptr, u64 from, u64 to) 2683 { 2684 return ptr[from..to]; 2685 } 2686 void test() 2687 { 2688 u8[2] array; 2689 u8[] slice = array[0..1]; 2690 u8_user(array[0..1]); 2691 } 2692 void u8_user(u8[]){} 2693 }; 2694 void tester107(ref TestContext ctx) { 2695 int[10] array = [0,1,2,3,4,5,6,7,8,9]; 2696 2697 auto slice_ptr1 = ctx.getFunctionPtr!(Slice!int, int*)("slice_ptr1"); 2698 assert(slice_ptr1(array.ptr) == array[]); 2699 auto slice_ptr2 = ctx.getFunctionPtr!(Slice!int, int*, ulong, ulong)("slice_ptr2"); 2700 assert(slice_ptr2(array.ptr, 0, 10) == array[]); 2701 assert(slice_ptr2(array.ptr, 5, 7) == array[5..7]); 2702 2703 auto slice_array1 = ctx.getFunctionPtr!(Slice!int, int[10]*)("slice_array1"); 2704 assert(slice_array1(&array) == array[]); 2705 auto slice_array2 = ctx.getFunctionPtr!(Slice!int, int[10]*, ulong, ulong)("slice_array2"); 2706 assert(slice_array2(&array, 0, 10) == array[]); 2707 assert(slice_array2(&array, 5, 7) == array[5..7]); 2708 2709 auto slice_slice1 = ctx.getFunctionPtr!(Slice!int, Slice!int)("slice_slice1"); 2710 assert(slice_slice1(Slice!int(array[])) == array[]); 2711 auto slice_slice2 = ctx.getFunctionPtr!(Slice!int, Slice!int, ulong, ulong)("slice_slice2"); 2712 assert(slice_slice2(Slice!int(array[]), 0, 10) == array[]); 2713 assert(slice_slice2(Slice!int(array[]), 5, 7) == array[5..7]); 2714 } 2715 2716 2717 @TestInfo(&tester108) 2718 immutable test108 = q{--- test108 2719 // Test function templates 2720 T min[T](T a, T b) { 2721 if (a < b) return a; 2722 return b; 2723 } 2724 i8 test_i8(i8 a, i8 b) { 2725 return min[i8](a, b) + min[i8](a, b); // test double instantiation 2726 } 2727 i16 test_i16(i16 a, i16 b) { 2728 return min[i16](a, b) + min[i16](a, b); // test multiple instances 2729 } 2730 i32 test_i32(i32 a, i32 b) { 2731 return min[i32](a, b) + min[i32](a, b); 2732 } 2733 i64 test_i64(i64 a, i64 b) { 2734 return min[i64](a, b) + min[i64](a, b); 2735 } 2736 }; 2737 void tester108(ref TestContext ctx) { 2738 auto test_i8 = ctx.getFunctionPtr!(byte, byte, byte)("test_i8"); 2739 auto test_i16 = ctx.getFunctionPtr!(short, short, short)("test_i16"); 2740 auto test_i32 = ctx.getFunctionPtr!(int, int, int)("test_i32"); 2741 auto test_i64 = ctx.getFunctionPtr!(long, long, long)("test_i64"); 2742 assert(test_i8(42, 120) == 42 * 2); 2743 assert(test_i16(420, 1200) == 420 * 2); 2744 assert(test_i32(-10_000, 10_000) == -10_000 * 2); 2745 assert(test_i64(-10_000, 10_000) == -10_000 * 2); 2746 } 2747 2748 @TestInfo() 2749 immutable test109 = q{--- test109 2750 // Test all type kinds 2751 struct S { 2752 i32 n; 2753 } 2754 T pass[T](T a) { 2755 return a; 2756 } 2757 i8 test_basic(i8 a) { 2758 return pass[i8](a); 2759 } 2760 u8* test_ptr(u8* ptr) { 2761 return pass[u8*](ptr); 2762 } 2763 S test_struct(S s) { 2764 return pass[S](s); 2765 } 2766 u8[] test_i64(u8[] slice) { 2767 return pass[u8[]](slice); 2768 } 2769 }; 2770 2771 @TestInfo(&tester110) 2772 immutable test110 = q{--- test110 2773 // Test struct templates 2774 struct Array[T] { 2775 T item; 2776 } 2777 T fun[T](T arg) { return arg; } 2778 Array[i32] test(Array[i32] array) { 2779 return fun[Array[i32]](array); 2780 } 2781 }; 2782 void tester110(ref TestContext ctx) { 2783 assert(ctx.getFunctionPtr!(int, int)("test")(42) == 42); 2784 } 2785 2786 2787 @TestInfo(&tester111) 2788 immutable test111 = q{--- test111 2789 // Test string escapes 2790 u8[] test() { 2791 return "\'\"\?\\\0\a\b\f\n\r\t\v\xAA\uAAAA\U0000AAAA"; 2792 } 2793 }; 2794 void tester111(ref TestContext ctx) { 2795 assert(ctx.getFunctionPtr!(Slice!char)("test")() == "\'\"\?\\\0\a\b\f\n\r\t\v\xAA\uAAAA\U0000AAAA"); 2796 } 2797 2798 @TestInfo(&tester112) 2799 immutable test112 = q{--- test112 2800 // Test int <--> ptr conversions 2801 u64 ptr_to_int(u8* ptr) { 2802 return cast(u64)ptr; 2803 } 2804 u8* int_to_ptr(u64 i) { 2805 return cast(u8*)i; 2806 } 2807 }; 2808 void tester112(ref TestContext ctx) { 2809 assert(ctx.getFunctionPtr!(ulong, ubyte*)("ptr_to_int")(cast(ubyte*)0xFFFF_FFFF_FFFF_FFFF) == 0xFFFF_FFFF_FFFF_FFFF); 2810 assert(ctx.getFunctionPtr!(ubyte*, ulong)("int_to_ptr")(0xFFFF_FFFF_FFFF_FFFF) == cast(ubyte*)0xFFFF_FFFF_FFFF_FFFF); 2811 } 2812 2813 2814 @TestInfo(&tester113) 2815 immutable test113 = q{--- test113 2816 // default initialization of variables 2817 struct S 2818 { 2819 i32 integer; 2820 u8[] slice; 2821 } 2822 void fun() 2823 { 2824 S s; 2825 i32 integer; 2826 u8[] slice; 2827 } 2828 }; 2829 void tester113(ref TestContext ctx) { 2830 } 2831 2832 2833 @TestInfo(&tester114) 2834 immutable test114 = q{--- test114 2835 // test ptr slice correctenss 2836 struct Array 2837 { 2838 i32* bufPtr; 2839 u32 length; 2840 u32 capacity; 2841 2842 i32[] data() 2843 { 2844 return bufPtr[0..length]; 2845 } 2846 } 2847 2848 i32[] test(Array* array) 2849 { 2850 return array.data; 2851 } 2852 }; 2853 void tester114(ref TestContext ctx) { 2854 static struct Array { 2855 int* ptr; 2856 uint length; 2857 uint capacity; 2858 } 2859 int[2] buffer = [42, 0]; 2860 Array array = Array(buffer.ptr, 1, 2); 2861 int[] data = ctx.getFunctionPtr!(Slice!int, Array*)("test")(&array).slice; 2862 assert(data.ptr == buffer.ptr); 2863 assert(data.length == 1); 2864 } 2865 2866 2867 @TestInfo(&tester115) 2868 immutable test115 = q{--- test115 2869 // Test recursive templates 2870 T test[T](T arg) { 2871 if (arg == 0) 2872 return 42; 2873 return test[T](arg-1); 2874 } 2875 i32 test_i32() { 2876 return test[i32](42); 2877 } 2878 }; 2879 void tester115(ref TestContext ctx) { 2880 assert(ctx.getFunctionPtr!(int)("test_i32")() == 42); 2881 } 2882 2883 2884 @TestInfo(&tester116) 2885 immutable test116 = q{--- test116 2886 // Test default arguments 2887 struct S { i32 a; i32 b; } 2888 i32 func_i32(i32 arg = 42) { return arg; } 2889 u8[] func_string(u8[] arg = "Hello") { return arg; } 2890 //S func_struct(S arg = S(1, 2)) { return arg; } // TODO 2891 2892 i32 test_i32() { return func_i32; } 2893 u8[] test_string() { return func_string; } 2894 //S test_struct() { return func_struct; } 2895 }; 2896 void tester116(ref TestContext ctx) { 2897 assert(ctx.getFunctionPtr!(int)("test_i32")() == 42); 2898 assert(ctx.getFunctionPtr!SliceString("test_string")().slice == "Hello"); 2899 } 2900 2901 2902 @TestInfo(&tester117) 2903 immutable test117 = q{--- test117 2904 // BUG: passing small constant (u8) as big (u32) argument causes u8 <- u8 mov instead of u32 <- u32 2905 u32 pass(u32 param) { 2906 return param; 2907 } 2908 u64 test() { 2909 u64 val = pass(0xFFFF_FFFF); // fill register with garbage 2910 val += pass(0); // BUG: sets only the lowest byte, passing 0xFFFF_FF00 as an argument 2911 return val; 2912 } 2913 }; 2914 void tester117(ref TestContext ctx) { 2915 assert(ctx.getFunctionPtr!(ulong)("test")() == 0xFFFF_FFFF); 2916 } 2917 2918 2919 @TestInfo(&tester118) 2920 immutable test118 = q{--- test118 2921 // Test global ptr deref assign 2922 u32* glob_ptr; 2923 u32** get_ptr() { return &glob_ptr; } 2924 void set_value(u32 val) { *glob_ptr = val; } 2925 }; 2926 void tester118(ref TestContext ctx) { 2927 auto get_ptr = ctx.getFunctionPtr!(uint**)("get_ptr"); 2928 auto set_value = ctx.getFunctionPtr!(void, uint)("set_value"); 2929 uint val; 2930 (*get_ptr()) = &val; 2931 set_value(100); 2932 assert(val == 100); 2933 } 2934 2935 2936 @TestInfo(&tester119) 2937 immutable test119 = q{--- test119 2938 // Test global scalar initialization 2939 u32 glob = 42; 2940 u32 read_global() { return glob; } 2941 void set_global(u32 val) { glob = val; } 2942 }; 2943 void tester119(ref TestContext ctx) { 2944 auto read_global = ctx.getFunctionPtr!(uint)("read_global"); 2945 auto set_global = ctx.getFunctionPtr!(void, uint)("set_global"); 2946 assert(read_global() == 42); 2947 set_global(100); 2948 assert(read_global() == 100); 2949 } 2950 2951 2952 @TestInfo(&tester120) 2953 immutable test120 = q{--- test120 2954 // Test global struct initialization 2955 struct S { 2956 u32 a; 2957 u32 b; 2958 u32 c; 2959 u32 d; 2960 } 2961 S glob = S(1, 2, 3, 4); 2962 S read_global() { return glob; } 2963 void set_global(S val) { glob = val; } 2964 }; 2965 void tester120(ref TestContext ctx) { 2966 struct S { 2967 uint a; 2968 uint b; 2969 uint c; 2970 uint d; 2971 } 2972 auto read_global = ctx.getFunctionPtr!(S)("read_global"); 2973 auto set_global = ctx.getFunctionPtr!(void, S)("set_global"); 2974 assert(read_global() == S(1, 2, 3, 4)); 2975 set_global(S(10, 20, 30, 40)); 2976 assert(read_global() == S(10, 20, 30, 40)); 2977 } 2978 2979 2980 @TestInfo(&tester121) 2981 immutable test121 = q{--- test121 2982 // Test global struct initialization with pointers 2983 u32 a = 1; 2984 u32 b = 2; 2985 u32 c = 3; 2986 u32 d = 4; 2987 struct S { 2988 u32* a; 2989 u32* b; 2990 u32* c; 2991 u32* d; 2992 } 2993 S glob = S(&a, &b, &c, &d); 2994 S read_global() { return glob; } 2995 }; 2996 void tester121(ref TestContext ctx) { 2997 struct S { 2998 uint* a; 2999 uint* b; 3000 uint* c; 3001 uint* d; 3002 } 3003 auto read_global = ctx.getFunctionPtr!(S)("read_global"); 3004 //import utils : printHex; 3005 //printHex(ctx.driver.context.staticDataBuffer.data, 16); 3006 S s = read_global(); 3007 assert(*s.a == 1); 3008 assert(*s.b == 2); 3009 assert(*s.c == 3); 3010 assert(*s.d == 4); 3011 } 3012 3013 3014 @TestInfo(&tester122) 3015 immutable test122 = q{--- test122 3016 // Test global pointer initialization 3017 u32 glob = 42; 3018 u32* glob_ptr = &glob; 3019 u32* get_ptr() { return glob_ptr; } 3020 u32 read_global() { return *glob_ptr; } 3021 void set_global(u32 val) { *glob_ptr = val; } 3022 }; 3023 void tester122(ref TestContext ctx) { 3024 auto get_ptr = ctx.getFunctionPtr!(uint*)("get_ptr"); 3025 auto read_global = ctx.getFunctionPtr!(uint)("read_global"); 3026 auto set_global = ctx.getFunctionPtr!(void, uint)("set_global"); 3027 //writefln("%X %s", get_ptr(), *get_ptr()); 3028 //writefln("%s", read_global()); 3029 assert(read_global() == 42); 3030 set_global(100); 3031 //writefln("%X %s", get_ptr(), *get_ptr()); 3032 //writefln("%s", read_global()); 3033 assert(read_global() == 100); 3034 } 3035 3036 3037 @TestInfo(&tester123) 3038 immutable test123 = q{--- test123 3039 // Test switch 3040 i32 fun(i32 val) { 3041 switch (val) { 3042 0 { return 40; } 3043 1 { return 10; } 3044 2 { return 15; } 3045 else { return 0; } 3046 } 3047 } 3048 }; 3049 void tester123(ref TestContext ctx) { 3050 auto fun = ctx.getFunctionPtr!(int, int)("fun"); 3051 assert(fun(0) == 40); 3052 assert(fun(1) == 10); 3053 assert(fun(2) == 15); 3054 assert(fun(100) == 0); 3055 assert(fun(200) == 0); 3056 assert(fun(-200) == 0); 3057 } 3058 3059 @TestInfo(&tester124) 3060 immutable test124 = q{--- test124 3061 // Test global in separate module 3062 import file2; 3063 i64 read_global() { return noop(glob); } 3064 i64 noop(i64 val) { return val; } 3065 --- file2 3066 i64 glob = 42; 3067 }; 3068 void tester124(ref TestContext ctx) { 3069 auto read_global = ctx.getFunctionPtr!(uint)("read_global"); 3070 assert(read_global() == 42); 3071 } 3072 3073 3074 @TestInfo() 3075 immutable test125 = q{--- test125 3076 // Index expression over template should copy isType of template body 3077 void freeArray[T](T[] array) {} 3078 3079 struct Array[T] 3080 { 3081 T* bufPtr; 3082 u32 length; 3083 u32 capacity; 3084 3085 void free() 3086 { 3087 freeArray[T](bufPtr[0..length]); 3088 } 3089 } 3090 alias int_array = Array[i32]; 3091 }; 3092 3093 @TestInfo() 3094 immutable test126 = q{--- test126 3095 // Template bug. .ptr PtrTypeNode was not marked as type checked 3096 void run() { 3097 i32[] slice; 3098 freeArray[i32](slice); 3099 } 3100 3101 void freeArray[T](T[] array) 3102 { 3103 if (array.ptr == null) return; 3104 } 3105 }; 3106 3107 @TestInfo(&tester127) 3108 immutable test127 = q{--- test127 3109 // Small struct store 3110 void put(Point* bufPtr, Point item) { 3111 bufPtr[0] = item; 3112 } 3113 struct Point { i32 x; i32 y; } 3114 }; 3115 void tester127(ref TestContext ctx) { 3116 static struct Point { int x; int y; } 3117 auto put = ctx.getFunctionPtr!(void, Point*, Point)("put"); 3118 Point point; 3119 put(&point, Point(42, 90)); 3120 assert(point == Point(42, 90)); 3121 } 3122 3123 3124 @TestInfo() 3125 immutable test128 = q{--- test128 3126 // Test member access on null constant 3127 struct Tile { 3128 u16 a; 3129 u16 b; 3130 } 3131 void run() { 3132 Tile* t; 3133 t.b = 42; // member of null pointer 3134 } 3135 }; 3136 3137 3138 @TestInfo() 3139 immutable test129 = `--- test129 3140 // Test inlining a recursive function inside non-recursive caller 3141 i32 caller(i32 param) { 3142 return callee(param) + 10; 3143 } 3144 3145 i32 callee(i32 param) #inline { 3146 if (param == 0) return 42; 3147 return callee(param - 1); 3148 } 3149 `; 3150 3151 @TestInfo() 3152 immutable test130 = `--- test130 3153 // Test inlining with phi function 3154 // Test inlining with array used 3155 i32 caller(i32 param) { 3156 return sign(param); 3157 } 3158 3159 i32 sign(i32 number) #inline { 3160 if (number < 0) return 0-1; 3161 else if (number > 0) return 1; 3162 else return 0; 3163 } 3164 `; 3165 3166 3167 @TestInfo(null, [HostSymbol("log", cast(void*)&external_print_i64_func)]) 3168 immutable test131 = q{--- test131 3169 i64 fac(i64 x) { 3170 if (x < 2) { 3171 return 1; 3172 } else { 3173 return fac(x - 1) * x; 3174 } 3175 } 3176 @extern(module, "host") 3177 void log(i64); 3178 void run() { 3179 log(fac(5)); 3180 } 3181 }; 3182 3183 3184 @TestInfo() 3185 immutable test132 = q{--- test132 3186 #assert(true, "Assert test"); 3187 }; 3188 3189 3190 @TestInfo() 3191 immutable test133 = q{--- test133 3192 #assert(false, "Assert test"); 3193 --- <error> 3194 test133:1:2: Error: #assert: "Assert test" 3195 }; 3196 3197 3198 @TestInfo() 3199 immutable test134 = q{--- test134 3200 $alias func() { 3201 return func; // return alias to itself 3202 } 3203 }; 3204 3205 @TestInfo() 3206 immutable test135 = q{--- test135 3207 $alias func() { 3208 return func; // return alias to itself 3209 } 3210 }; 3211 3212 @TestInfo(&tester136) 3213 immutable test136 = q{--- test136 3214 // Various meta types tests 3215 i32 func() { return 42; } 3216 $alias metaFun1() { return func; } // return $alias of func 3217 $alias metaFun2() { return u8; } // return $alias of built-in 3218 $type metaFun3() { return u8; } // return $type 3219 enum bool res1 = metaFun1() == u8; // false 3220 enum bool res2 = metaFun2() == u8; // true 3221 enum bool res3 = metaFun3() == u8; // true 3222 3223 enum $alias a = func; 3224 //enum $type t = i32; 3225 i32 run() { return a(); } 3226 bool run1() { return res1; } 3227 bool run2() { return res2; } 3228 bool run3() { return res3; } 3229 3230 bool isInteger($type type) { 3231 return type == u8 3232 || type == i8 3233 || type == u16 3234 || type == i16 3235 || type == u32 3236 || type == i32 3237 || type == u64 3238 || type == i64; 3239 } 3240 enum bool res4 = 3241 isInteger(u8) && 3242 isInteger(i8) && 3243 isInteger(u16) && 3244 isInteger(i16) && 3245 isInteger(u32) && 3246 isInteger(i32) && 3247 isInteger(u64) && 3248 isInteger(i64); 3249 bool run4() { return res4; } 3250 }; 3251 void tester136(ref TestContext ctx) { 3252 auto run = ctx.getFunctionPtr!(int)("run"); 3253 auto run1 = ctx.getFunctionPtr!(bool)("run1"); 3254 auto run2 = ctx.getFunctionPtr!(bool)("run2"); 3255 auto run3 = ctx.getFunctionPtr!(bool)("run3"); 3256 auto run4 = ctx.getFunctionPtr!(bool)("run4"); 3257 assert(run() == 42); 3258 assert(run1() == false); 3259 assert(run2() == true); 3260 assert(run3() == true); 3261 assert(run4() == true); 3262 } 3263 3264 3265 @TestInfo() 3266 immutable test137 = q{--- test137 3267 // ctfe only structs 3268 struct S1 { 3269 $alias ctfeVar; 3270 } 3271 struct S2 { 3272 $alias ctfeFun(){ return S1; } 3273 } 3274 }; 3275 3276 3277 @TestInfo(null, [HostSymbol("crash", cast(void*)&external_noop)]) 3278 immutable test138 = q{--- test138 3279 // noreturn 3280 @extern(module, "host") 3281 noreturn crash(); 3282 void run1() { 3283 crash(); 3284 } 3285 noreturn run2() { 3286 crash(); 3287 } 3288 // should not complain about missing return 3289 i32 run3() { 3290 crash(); 3291 } 3292 }; 3293 3294 3295 @TestInfo() 3296 immutable test139 = q{--- test139 3297 // builtin functions 3298 bool run() { 3299 return val; 3300 } 3301 enum val = $compileError("CTFE error"); 3302 --- <error> 3303 test139:5:26: Error: CTFE error 3304 }; 3305 3306 3307 @TestInfo() 3308 immutable test140 = q{--- test140 3309 // CTFE in type check pass 3310 #assert(callee1, "test"); 3311 bool callee1() { 3312 return callee2(); 3313 } 3314 bool callee2() { 3315 return false; 3316 } 3317 --- <error> 3318 test140:2:2: Error: #assert: "test" 3319 }; 3320 3321 3322 // TODO: no file/line number in the error 3323 @TestInfo() 3324 immutable test141 = q{--- test141 3325 // builtin functions 3326 #assert(callee1, "test"); 3327 bool callee1() { 3328 return callee2(); 3329 } 3330 3331 bool callee2() { 3332 $compileError("CTFE error"); 3333 } 3334 --- <error> 3335 : Error: CTFE error 3336 }; 3337 3338 3339 @TestInfo(&tester142) 3340 immutable test142 = q{--- test142 3341 // Store $alias and $type in alias 3342 alias type1 = getType1(); 3343 $alias getType1() { return u8; } 3344 type1 run1() { 3345 return 42; 3346 } 3347 alias type2 = getType2(); 3348 $type getType2() { return u8; } 3349 type2 run2() { 3350 return 42; 3351 } 3352 }; 3353 void tester142(ref TestContext ctx) { 3354 auto run1 = ctx.getFunctionPtr!(ubyte)("run1"); 3355 auto run2 = ctx.getFunctionPtr!(ubyte)("run2"); 3356 assert(run1() == 42); 3357 assert(run2() == 42); 3358 } 3359 3360 3361 @TestInfo(&tester143) 3362 immutable test143 = q{--- test143 3363 // bool $isSlice($type type) 3364 bool run1() { 3365 enum bool val = $isSlice(u8[]); 3366 return val; // true 3367 } 3368 bool run2() { 3369 enum bool val = $isSlice(u8); 3370 return val; // false 3371 } 3372 }; 3373 void tester143(ref TestContext ctx) { 3374 auto run1 = ctx.getFunctionPtr!(bool)("run1"); 3375 auto run2 = ctx.getFunctionPtr!(bool)("run2"); 3376 assert(run1() == true); 3377 assert(run2() == false); 3378 } 3379 3380 3381 @TestInfo(&tester144, [ 3382 HostSymbol("printStr", cast(void*)&external_print_string), 3383 HostSymbol("printInt", cast(void*)&external_print_i64_func)]) 3384 immutable test144 = q{--- test144 3385 // select function 3386 @extern(module, "host") 3387 void printStr(u8[]); 3388 @extern(module, "host") 3389 void printInt(i64 i); 3390 bool isInteger($type type) { 3391 return type == u8 3392 || type == i8 3393 || type == u16 3394 || type == i16 3395 || type == u32 3396 || type == i32 3397 || type == u64 3398 || type == i64; 3399 } 3400 $alias selectPrintFunc($type T) { 3401 if (isInteger(T)) 3402 return printInt; 3403 if ($isSlice(T)) 3404 return printStr; 3405 $compileError("Invalid type"); 3406 } 3407 void run() { 3408 alias func1 = selectPrintFunc(u8[]); 3409 func1("Hello"); 3410 alias func2 = selectPrintFunc(i32); 3411 func2(42); 3412 } 3413 }; 3414 void tester144(ref TestContext ctx) { 3415 auto run = ctx.getFunctionPtr!(void)("run"); 3416 run(); 3417 assert(testSink.text == "Hello42"); 3418 } 3419 3420 3421 @TestInfo() 3422 immutable test145 = q{--- test145 3423 // Test implicit function template instantiation (0 args) 3424 void fun[]() {} 3425 void run(){ fun(); } 3426 }; 3427 3428 3429 @TestInfo() 3430 immutable test146 = q{--- test146 3431 // Test implicit function template instantiation (1 arg) 3432 void fun[T](T param) {} 3433 void run(){ fun(42); } 3434 }; 3435 3436 3437 @TestInfo() 3438 immutable test147 = q{--- test147 3439 // Test implicit function template instantiation (2 equivalent types on single arg) 3440 void fun[T](T param1, T param2) {} 3441 void run(){ fun(42, 42); } 3442 }; 3443 3444 3445 @TestInfo(&tester148) 3446 immutable test148 = q{--- test148 3447 // Test implicit function template instantiation 3448 T min[T](T a, T b) { 3449 if (a < b) return a; 3450 return b; 3451 } 3452 i8 test_i8(i8 a, i8 b) { 3453 return min(a, b) + min(a, b); 3454 } 3455 i16 test_i16(i16 a, i16 b) { 3456 return min(a, b) + min(a, b); 3457 } 3458 i32 test_i32(i32 a, i32 b) { 3459 return min(a, b) + min(a, b); 3460 } 3461 i64 test_i64(i64 a, i64 b) { 3462 return min(a, b) + min(a, b); 3463 } 3464 }; 3465 void tester148(ref TestContext ctx) { 3466 auto test_i8 = ctx.getFunctionPtr!(byte, byte, byte)("test_i8"); 3467 auto test_i16 = ctx.getFunctionPtr!(short, short, short)("test_i16"); 3468 auto test_i32 = ctx.getFunctionPtr!(int, int, int)("test_i32"); 3469 auto test_i64 = ctx.getFunctionPtr!(long, long, long)("test_i64"); 3470 assert(test_i8(42, 120) == 42 * 2); 3471 assert(test_i16(420, 1200) == 420 * 2); 3472 assert(test_i32(-10_000, 10_000) == -10_000 * 2); 3473 assert(test_i64(-10_000, 10_000) == -10_000 * 2); 3474 } 3475 3476 3477 @TestInfo() 3478 immutable test149 = q{--- test149 3479 // Test implicit function template instantiation (2 different types that have common type) 3480 void fun[T](T param1, T param2) {} 3481 void run(){ fun(42, 500); } 3482 }; 3483 3484 3485 @TestInfo(&tester150, [ 3486 HostSymbol("printStr", cast(void*)&external_print_string), 3487 HostSymbol("printInt", cast(void*)&external_print_i64_func)]) 3488 immutable test150 = q{--- test150 3489 // $isInteger + IFTI 3490 @extern(module, "host") 3491 void printStr(u8[]); 3492 @extern(module, "host") 3493 void printInt(i64 i); 3494 $alias selectPrintFunc($type T) { 3495 if ($isInteger(T)) 3496 return printInt; 3497 if ($isSlice(T)) 3498 return printStr; 3499 $compileError("Invalid type"); 3500 } 3501 void write[T](T val) { 3502 alias func = selectPrintFunc(T); 3503 func(val); 3504 } 3505 void run() { 3506 write("Hello"); 3507 write(42); 3508 } 3509 }; 3510 void tester150(ref TestContext ctx) { 3511 auto run = ctx.getFunctionPtr!(void)("run"); 3512 run(); 3513 assert(testSink.text == "Hello42"); 3514 } 3515 3516 3517 @TestInfo() 3518 immutable test151 = q{--- test151 3519 // Variadic template arg (0 uses, 0 args) 3520 void fun[Args...]() { 3521 #assert(Args.length == 0); 3522 } 3523 void run(){ fun(); } 3524 }; 3525 3526 3527 @TestInfo() 3528 immutable test152 = q{ 3529 --- test152 3530 // Variadic template arg (0 uses, 0 args, 2 variadics) 3531 void fun[Args1..., Args2...]() {} 3532 void run(){ fun(); } 3533 --- <error> 3534 test152:2:21: Error: Only single variadic template parameter allowed 3535 }; 3536 3537 3538 @TestInfo() 3539 immutable test153 = q{ 3540 --- test153 3541 // Variadic template arg (0 uses, 0 args, 1 variadic, 1 param after variadic) 3542 void fun[Args..., T]() {} 3543 void run(){ fun(); } 3544 --- <error> 3545 test153:2:20: Error: Cannot have template parameters after variadic parameter (WIP) 3546 }; 3547 3548 3549 @TestInfo() 3550 immutable test154 = q{--- test154 3551 // Variadic template arg (0 args) 3552 void fun[Args...](Args... args) { 3553 #assert(Args.length == 0); 3554 } 3555 void run(){ fun(); } 3556 }; 3557 3558 3559 @TestInfo() 3560 immutable test155 = q{--- test155 3561 // Variadic template arg (1 arg) 3562 void fun[Args...](Args... args) { 3563 #assert(Args.length == 1); 3564 } 3565 void run(){ fun(42); } 3566 }; 3567 3568 3569 @TestInfo() 3570 immutable test156 = q{--- test156 3571 // Variadic template arg (2 args) 3572 void fun[Args...](Args... args) { 3573 #assert(Args.length == 2); 3574 } 3575 void run(){ fun(42, 4096); } 3576 }; 3577 3578 3579 @TestInfo() 3580 immutable test157 = q{--- test157 3581 // Variadic template arg (3 args) 3582 void fun[Args...](Args... args) { 3583 #assert(Args.length == 3); 3584 } 3585 void run(){ fun(42, 4096, 200000); } 3586 }; 3587 3588 3589 @TestInfo() 3590 immutable test158 = q{--- test158 3591 // Variadic template arg, same instance (2 args) 3592 void fun[Args...](Args... args) { 3593 #assert(Args.length == 3); 3594 } 3595 void run(){ 3596 fun(42, 4096, 200000); 3597 fun(50, 3000, 300000); 3598 } 3599 }; 3600 3601 3602 @TestInfo() 3603 immutable test159 = q{--- test159 3604 // Variadic template arg, 2 different instances (2 args) 3605 void fun[Args...](Args... args) {} 3606 void run(){ 3607 fun(42, 4096); 3608 fun(50, 3000, 300000); 3609 } 3610 }; 3611 3612 3613 @TestInfo() 3614 immutable test160 = q{--- test160 3615 // Non-variadic + Variadic template arg 3616 void fun[Args...](u8 par, Args... args) { 3617 #assert(Args.length == 1); 3618 } 3619 void run(){ fun(42, 4096); } 3620 }; 3621 3622 3623 @TestInfo() 3624 immutable test161 = q{--- test161 3625 // Non-variadic + 0 Variadic template args 3626 void fun[Args...](u8 par, Args... args) { 3627 #assert(Args.length == 0); 3628 } 3629 void run(){ fun(42); } 3630 }; 3631 3632 3633 @TestInfo() 3634 immutable test162 = q{--- test162 3635 // Non-variadic + 0 Variadic template args 3636 void fun[Args...](u8 par) { 3637 #assert(Args.length == 0); 3638 } 3639 void run(){ fun(42); } 3640 }; 3641 3642 3643 @TestInfo() 3644 immutable test163 = q{--- test163 3645 // Non-variadic + 0 Variadic template args + default RT params 3646 void fun[Args...](u8 par1, Args... args, u8 par2 = 50) { 3647 #assert(Args.length == 0); 3648 } 3649 void run(){ fun(42); } 3650 }; 3651 3652 3653 @TestInfo() 3654 immutable test164 = q{--- test164 3655 // Non-variadic + 0 Variadic template args + non-default RT param 3656 void fun[Args...](u8 par1, Args... args, u8 par2) { 3657 #assert(Args.length == 0); 3658 } 3659 void run(){ fun(42, 50); } 3660 }; 3661 3662 3663 @TestInfo() 3664 immutable test165 = q{--- test165 3665 // Non-variadic + 1 Variadic template args + non-default RT param 3666 void fun[Args...](u8 par1, Args... args, u8 par2) { 3667 #assert(Args.length == 1); 3668 } 3669 void run(){ fun(42, 50, 60); } 3670 }; 3671 3672 3673 @TestInfo() 3674 immutable test166 = q{--- test166 3675 // Access variadic variable 3676 i32 fun[Args...](Args... args) { 3677 return args[0]; 3678 } 3679 #assert(fun(42) == 42); 3680 }; 3681 3682 3683 @TestInfo() 3684 immutable test167 = q{--- test167 3685 // Access variadic variable 3686 i32 fun[Args...](Args... args) { 3687 alias arg0 = args[0]; 3688 alias T0 = Args[0]; 3689 T0 result = arg0; 3690 return result; 3691 } 3692 #assert(fun(42) == 42); 3693 }; 3694 3695 3696 @TestInfo() 3697 immutable test168 = q{--- test168 3698 // #foreach 3699 i64 fun[Args...](Args... args) { 3700 i64 sum = 0; 3701 #foreach(i, arg; args) { 3702 sum += arg; 3703 } 3704 return sum; 3705 } 3706 #assert(fun(1, 2, 3) == 6); 3707 }; 3708 3709 3710 @TestInfo(&tester169, [ 3711 HostSymbol("printStr", cast(void*)&external_print_string), 3712 HostSymbol("printInt", cast(void*)&external_print_i64_func)]) 3713 immutable test169 = q{--- test169 3714 // #foreach with multiple statements 3715 @extern(module, "host") 3716 void printStr(u8[]); 3717 @extern(module, "host") 3718 void printInt(i64 i); 3719 $alias selectPrintFunc($type T) { 3720 if ($isInteger(T)) 3721 return printInt; 3722 if ($isSlice(T)) 3723 return printStr; 3724 $compileError("Invalid type"); 3725 } 3726 void write[Args...](Args... args) { 3727 #foreach(i, arg; args) { 3728 alias func = selectPrintFunc(Args[i]); 3729 func(arg); 3730 } 3731 } 3732 void run() { 3733 write("Hello", 42); 3734 } 3735 }; 3736 void tester169(ref TestContext ctx) { 3737 auto run = ctx.getFunctionPtr!(void)("run"); 3738 run(); 3739 assert(testSink.text == "Hello42"); 3740 } 3741 3742 3743 @TestInfo() 3744 immutable test170 = q{ 3745 --- test170_1 3746 // Use name from other module in func signature 3747 import test170_2; 3748 void fun(Struct s){} 3749 --- test170_2 3750 struct Struct {} 3751 }; 3752 3753 3754 @TestInfo() 3755 immutable test171 = q{ 3756 --- test171 3757 // Variadic function parameter (2 expanded parameters) 3758 void fun[Args...](Args... args, Args... args2) { 3759 #assert(Args.length == 1); 3760 } 3761 void run(){ fun(42); } 3762 --- <error> 3763 test171:2:38: Error: Cannot have two expanded parameters 3764 }; 3765 3766 3767 //@TestInfo() 3768 //immutable test172 = q{--- test172 3769 // // No parenths variadic call 3770 // i64 fun[Args...](Args... args) { 3771 // return 0; 3772 // } 3773 // #assert(fun == 0); 3774 //}; 3775 3776 3777 @TestInfo() 3778 @(TargetOs.linux) 3779 immutable test173 = q{--- test173 3780 // Extern attribute 3781 @extern(syscall, 60) 3782 void exit(); 3783 void run() { 3784 exit(); 3785 } 3786 }; 3787 3788 3789 @TestInfo() 3790 @(TargetOs.linux) 3791 immutable test174 = q{--- test174 3792 // 2 Extern attributes 3793 @extern(syscall, 60) 3794 void exit(); 3795 3796 // var attributes 3797 @extern(syscall, 42) 3798 u8 var; 3799 3800 // struct attribute 3801 @extern(syscall, 1) 3802 struct A { 3803 // member var attribute 3804 @extern(syscall, 2) 3805 u8 var; 3806 3807 // member func attribute 3808 @extern(syscall, 3) 3809 void foo(); 3810 } 3811 }; 3812 3813 3814 @TestInfo(&tester_float_1) 3815 immutable test_float_1 = q{--- test_float_1.vx 3816 // floats negation 3817 f32 neg_f32(f32 n) { return -n; } 3818 f64 neg_f64(f64 n) { return -n; } 3819 }; 3820 void tester_float_1(ref TestContext ctx) { 3821 assert(ctx.getFunctionPtr!(float, float)("neg_f32")(2) == -2); 3822 assert(ctx.getFunctionPtr!(double, double)("neg_f64")(2) == -2); 3823 } 3824 3825 3826 @TestInfo(&tester_float_2) 3827 immutable test_float_2 = q{--- test_float_2 3828 // floats: arithmetics and comparisons 3829 f32 f32_add(f32 a, f32 b) { return a + b; } 3830 f64 f64_add(f64 a, f64 b) { return a + b; } 3831 f32 f32_sub(f32 a, f32 b) { return a - b; } 3832 f64 f64_sub(f64 a, f64 b) { return a - b; } 3833 f32 f32_mul(f32 a, f32 b) { return a * b; } 3834 f64 f64_mul(f64 a, f64 b) { return a * b; } 3835 f32 f32_div(f32 a, f32 b) { return a / b; } 3836 f64 f64_div(f64 a, f64 b) { return a / b; } 3837 bool f32_lt(f32 a, f32 b) { return a < b; } 3838 bool f64_lt(f64 a, f64 b) { return a < b; } 3839 bool f32_le(f32 a, f32 b) { return a <= b; } 3840 bool f64_le(f64 a, f64 b) { return a <= b; } 3841 bool f32_eq(f32 a, f32 b) { return a == b; } 3842 bool f64_eq(f64 a, f64 b) { return a == b; } 3843 bool f32_ne(f32 a, f32 b) { return a != b; } 3844 bool f64_ne(f64 a, f64 b) { return a != b; } 3845 bool f32_gt(f32 a, f32 b) { return a > b; } 3846 bool f64_gt(f64 a, f64 b) { return a > b; } 3847 bool f32_ge(f32 a, f32 b) { return a >= b; } 3848 bool f64_ge(f64 a, f64 b) { return a >= b; } 3849 }; 3850 void tester_float_2(ref TestContext ctx) { 3851 auto f32_add = ctx.getFunctionPtr!(float, float, float)("f32_add"); 3852 assert(f32_add(42, 100) == 42f + 100f); 3853 auto f64_add = ctx.getFunctionPtr!(double, double, double)("f64_add"); 3854 assert(f64_add(42, 100) == 42.0 + 100.0); 3855 3856 auto f32_sub = ctx.getFunctionPtr!(float, float, float)("f32_sub"); 3857 assert(f32_sub(42, 100) == 42f - 100f); 3858 auto f64_sub = ctx.getFunctionPtr!(double, double, double)("f64_sub"); 3859 assert(f64_sub(42, 100) == 42.0 - 100.0); 3860 3861 auto f32_mul = ctx.getFunctionPtr!(float, float, float)("f32_mul"); 3862 assert(f32_mul(42, 100) == 42f * 100f); 3863 auto f64_mul = ctx.getFunctionPtr!(double, double, double)("f64_mul"); 3864 assert(f64_mul(42, 100) == 42.0 * 100.0); 3865 3866 auto f32_div = ctx.getFunctionPtr!(float, float, float)("f32_div"); 3867 assert(f32_div(42, 100) == 42f / 100f); 3868 auto f64_div = ctx.getFunctionPtr!(double, double, double)("f64_div"); 3869 assert(f64_div(42, 100) == 42.0 / 100.0); 3870 3871 auto f32_lt = ctx.getFunctionPtr!(bool, float, float)("f32_lt"); 3872 assert(f32_lt(42, 42) == (42f < 42f)); 3873 assert(f32_lt(42, 100) == (42f < 100f)); 3874 assert(f32_lt(100, 42) == (100f < 42f)); 3875 assert(f32_lt(-100, -42) == (-100f < -42f)); 3876 auto f64_lt = ctx.getFunctionPtr!(bool, double, double)("f64_lt"); 3877 assert(f64_lt(42, 42) == (42.0 < 42.0)); 3878 assert(f64_lt(42, 100) == (42.0 < 100.0)); 3879 assert(f64_lt(100, 42) == (100.0 < 42.0)); 3880 assert(f64_lt(-100, -42) == (-100.0 < -42.0)); 3881 3882 auto f32_le = ctx.getFunctionPtr!(bool, float, float)("f32_le"); 3883 assert(f32_le(42, 42) == (42f <= 42f)); 3884 assert(f32_le(42, 100) == (42f <= 100f)); 3885 assert(f32_le(100, 42) == (100f <= 42f)); 3886 assert(f32_le(-100, -42) == (-100f <= -42f)); 3887 auto f64_le = ctx.getFunctionPtr!(bool, double, double)("f64_le"); 3888 assert(f64_le(42, 42) == (42.0 <= 42.0)); 3889 assert(f64_le(42, 100) == (42.0 <= 100.0)); 3890 assert(f64_le(100, 42) == (100.0 <= 42.0)); 3891 assert(f64_le(-100, -42) == (-100.0 <= -42.0)); 3892 3893 auto f32_eq = ctx.getFunctionPtr!(bool, float, float)("f32_eq"); 3894 assert(f32_eq(42, 42) == (42f == 42f)); 3895 assert(f32_eq(42, 100) == (42f == 100f)); 3896 assert(f32_eq(100, 42) == (100f == 42f)); 3897 assert(f32_eq(-100, -42) == (-100f == -42f)); 3898 auto f64_eq = ctx.getFunctionPtr!(bool, double, double)("f64_eq"); 3899 assert(f64_eq(42, 42) == (42.0 == 42.0)); 3900 assert(f64_eq(42, 100) == (42.0 == 100.0)); 3901 assert(f64_eq(100, 42) == (100.0 == 42.0)); 3902 assert(f64_eq(-100, -42) == (-100.0 == -42.0)); 3903 3904 auto f32_ne = ctx.getFunctionPtr!(bool, float, float)("f32_ne"); 3905 assert(f32_ne(42, 42) == (42f != 42f)); 3906 assert(f32_ne(42, 100) == (42f != 100f)); 3907 assert(f32_ne(100, 42) == (100f != 42f)); 3908 assert(f32_ne(-100, -42) == (-100f != -42f)); 3909 auto f64_ne = ctx.getFunctionPtr!(bool, double, double)("f64_ne"); 3910 assert(f64_ne(42, 42) == (42.0 != 42.0)); 3911 assert(f64_ne(42, 100) == (42.0 != 100.0)); 3912 assert(f64_ne(100, 42) == (100.0 != 42.0)); 3913 assert(f64_ne(-100, -42) == (-100.0 != -42.0)); 3914 3915 auto f32_gt = ctx.getFunctionPtr!(bool, float, float)("f32_gt"); 3916 assert(f32_gt(42, 42) == (42f > 42f)); 3917 assert(f32_gt(42, 100) == (42f > 100f)); 3918 assert(f32_gt(100, 42) == (100f > 42f)); 3919 assert(f32_gt(-100, -42) == (-100f > -42f)); 3920 auto f64_gt = ctx.getFunctionPtr!(bool, double, double)("f64_gt"); 3921 assert(f64_gt(42, 42) == (42.0 > 42.0)); 3922 assert(f64_gt(42, 100) == (42.0 > 100.0)); 3923 assert(f64_gt(100, 42) == (100.0 > 42.0)); 3924 assert(f64_gt(-100, -42) == (-100.0 > -42.0)); 3925 3926 auto f32_ge = ctx.getFunctionPtr!(bool, float, float)("f32_ge"); 3927 assert(f32_ge(42, 42) == (42f >= 42f)); 3928 assert(f32_ge(42, 100) == (42f >= 100f)); 3929 assert(f32_ge(100, 42) == (100f >= 42f)); 3930 assert(f32_ge(-100, -42) == (-100f >= -42f)); 3931 auto f64_ge = ctx.getFunctionPtr!(bool, double, double)("f64_ge"); 3932 assert(f64_ge(42, 42) == (42.0 >= 42.0)); 3933 assert(f64_ge(42, 100) == (42.0 >= 100.0)); 3934 assert(f64_ge(100, 42) == (100.0 >= 42.0)); 3935 assert(f64_ge(-100, -42) == (-100.0 >= -42.0)); 3936 } 3937 3938 /* 3939 @TestInfo(&tester_float_3) 3940 immutable test_float_3 = q{--- test_float_3.vx 3941 // floats compare with literal 3942 bool f32_lt_l(f32 b) { return 0 < b; } 3943 bool f64_lt_l(f64 b) { return 0 < b; } 3944 bool f32_le_l(f32 b) { return 0 <= b; } 3945 bool f64_le_l(f64 b) { return 0 <= b; } 3946 bool f32_eq_l(f32 b) { return 0 == b; } 3947 bool f64_eq_l(f64 b) { return 0 == b; } 3948 bool f32_ne_l(f32 b) { return 0 != b; } 3949 bool f64_ne_l(f64 b) { return 0 != b; } 3950 bool f32_gt_l(f32 b) { return 0 > b; } 3951 bool f64_gt_l(f64 b) { return 0 > b; } 3952 bool f32_ge_l(f32 b) { return 0 >= b; } 3953 bool f64_ge_l(f64 b) { return 0 >= b; } 3954 3955 bool f32_lt_r(f32 a) { return a < 0; } 3956 bool f64_lt_r(f64 a) { return a < 0; } 3957 bool f32_le_r(f32 a) { return a <= 0; } 3958 bool f64_le_r(f64 a) { return a <= 0; } 3959 bool f32_eq_r(f32 a) { return a == 0; } 3960 bool f64_eq_r(f64 a) { return a == 0; } 3961 bool f32_ne_r(f32 a) { return a != 0; } 3962 bool f64_ne_r(f64 a) { return a != 0; } 3963 bool f32_gt_r(f32 a) { return a > 0; } 3964 bool f64_gt_r(f64 a) { return a > 0; } 3965 bool f32_ge_r(f32 a) { return a >= 0; } 3966 bool f64_ge_r(f64 a) { return a >= 0; } 3967 }; 3968 void tester_float_3(ref TestContext ctx) { 3969 3970 }*/ 3971 3972 3973 @TestInfo(&tester_float_4) 3974 immutable test_float_4 = q{--- test_float_4 3975 // floats: argument passing via stack and registers 3976 f32 f32_add(f32 p1, f32 p2, f32 p3, f32 p4, f32 p5, f32 p6, f32 p7, f32 p8, f32 p9) { 3977 return p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9; 3978 } 3979 f64 f64_add(f64 p1, f64 p2, f64 p3, f64 p4, f64 p5, f64 p6, f64 p7, f64 p8, f64 p9) { 3980 return p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9; 3981 } 3982 f32 f32_call(f32 p1, f32 p2, f32 p3, f32 p4, f32 p5, f32 p6, f32 p7, f32 p8, f32 p9) { 3983 return f32_add(p1, p2, p3, p4, p5, p6, p7, p8, p9); 3984 } 3985 f64 f64_call(f64 p1, f64 p2, f64 p3, f64 p4, f64 p5, f64 p6, f64 p7, f64 p8, f64 p9) { 3986 return f64_add(p1, p2, p3, p4, p5, p6, p7, p8, p9); 3987 } 3988 }; 3989 void tester_float_4(ref TestContext ctx) { 3990 auto f32_add = ctx.getFunctionPtr!(float, float, float, float, float, float, float, float, float, float)("f32_add"); 3991 assert(f32_add(1, 2, 3, 4, 5, 6, 7, 8, 9) == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9); 3992 auto f64_add = ctx.getFunctionPtr!(double, double, double, double, double, double, double, double, double, double)("f64_add"); 3993 assert(f64_add(1, 2, 3, 4, 5, 6, 7, 8, 9) == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9); 3994 auto f32_call = ctx.getFunctionPtr!(float, float, float, float, float, float, float, float, float, float)("f32_call"); 3995 assert(f32_call(1, 2, 3, 4, 5, 6, 7, 8, 9) == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9); 3996 auto f64_call = ctx.getFunctionPtr!(double, double, double, double, double, double, double, double, double, double)("f64_call"); 3997 assert(f64_call(1, 2, 3, 4, 5, 6, 7, 8, 9) == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9); 3998 } 3999 4000 4001 @TestInfo(&tester177) 4002 immutable test177 = q{--- test177 4003 f64 func_f32_to_f64(f32 a) { return a; } // f32 -> f64 4004 f32 func_f64_to_f32(f64 a) { return cast(f32)a; } // f64 -> f32 4005 4006 f32 func_f32_zero1() { return 0; } 4007 f64 func_f64_zero1() { return 0; } 4008 f32 func_f32_zero2() { return 0.0; } 4009 f64 func_f64_zero2() { return 0.0; } 4010 f32 func_f32_const() { return 0.5; } 4011 f64 func_f64_const() { return 0.5; } 4012 4013 f32 func_f32_const_mult(f32 a) { return a * cast(f32)0.5; } 4014 f64 func_f64_const_mult(f64 a) { return a * 0.5; } 4015 4016 f32 func_const_f32_mult(f32 a) { return cast(f32)0.5 * a; } 4017 f64 func_const_f64_mult(f64 a) { return 0.5 * a; } 4018 4019 i8 func_f32_to__i8(f32 a) { return a; } // f32 -> i8 4020 i16 func_f32_to_i16(f32 a) { return a; } // f32 -> i16 4021 i32 func_f32_to_i32(f32 a) { return a; } // f32 -> i32 4022 i64 func_f32_to_i64(f32 a) { return a; } // f32 -> i64 4023 4024 u8 func_f32_to__u8(f32 a) { return a; } // f32 -> u8 4025 u16 func_f32_to_u16(f32 a) { return a; } // f32 -> u16 4026 u32 func_f32_to_u32(f32 a) { return a; } // f32 -> u32 4027 u64 func_f32_to_u64(f32 a) { return a; } // f32 -> u64 // TODO: more precise conversion 4028 4029 i8 func_f64_to__i8(f64 a) { return a; } // f64 -> i8 4030 i16 func_f64_to_i16(f64 a) { return a; } // f64 -> i16 4031 i32 func_f64_to_i32(f64 a) { return a; } // f64 -> i32 4032 i64 func_f64_to_i64(f64 a) { return a; } // f64 -> i64 4033 4034 u8 func_f64_to__u8(f64 a) { return a; } // f64 -> u8 4035 u16 func_f64_to_u16(f64 a) { return a; } // f64 -> u16 4036 u32 func_f64_to_u32(f64 a) { return a; } // f64 -> u32 4037 u64 func_f64_to_u64(f64 a) { return a; } // f64 -> u64 // TODO: more precise conversion 4038 4039 f32 func__i8_to_f32( i8 a) { return a; } // i8 -> f32 4040 f32 func_i16_to_f32(i16 a) { return a; } // i16 -> f32 4041 f32 func_i32_to_f32(i32 a) { return a; } // i32 -> f32 4042 f32 func_i64_to_f32(i64 a) { return a; } // i64 -> f32 4043 4044 f32 func__u8_to_f32( u8 a) { return a; } // u8 -> f32 4045 f32 func_u16_to_f32(u16 a) { return a; } // u16 -> f32 4046 f32 func_u32_to_f32(u32 a) { return a; } // u32 -> f32 4047 f32 func_u64_to_f32(u64 a) { return a; } // u64 -> f32 // TODO: more precise conversion 4048 4049 f64 func__i8_to_f64( i8 a) { return a; } // i8 -> f64 4050 f64 func_i16_to_f64(i16 a) { return a; } // i16 -> f64 4051 f64 func_i32_to_f64(i32 a) { return a; } // i32 -> f64 4052 f64 func_i64_to_f64(i64 a) { return a; } // i64 -> f64 4053 4054 f64 func__u8_to_f64( u8 a) { return a; } // u8 -> f64 4055 f64 func_u16_to_f64(u16 a) { return a; } // u16 -> f64 4056 f64 func_u32_to_f64(u32 a) { return a; } // u32 -> f64 4057 f64 func_u64_to_f64(u64 a) { return a; } // u64 -> f64 // TODO: more precise conversion 4058 }; 4059 void tester177(ref TestContext ctx) { 4060 assert(ctx.getFunctionPtr!(double, float)("func_f32_to_f64")(42.54f) == 42.54f.force); 4061 assert(ctx.getFunctionPtr!(float, double)("func_f64_to_f32")(42.54) == 42.54f.force); 4062 4063 assert(ctx.getFunctionPtr!(float)("func_f32_zero1")() == 0f.force); 4064 assert(ctx.getFunctionPtr!(double)("func_f64_zero1")() == 0); 4065 assert(ctx.getFunctionPtr!(float)("func_f32_zero2")() == 0f.force); 4066 assert(ctx.getFunctionPtr!(double)("func_f64_zero2")() == 0); 4067 assert(ctx.getFunctionPtr!(float)("func_f32_const")() == 0.5f.force); 4068 assert(ctx.getFunctionPtr!(double)("func_f64_const")() == 0.5); 4069 4070 assert(ctx.getFunctionPtr!(float, float)("func_f32_const_mult")(1) == 0.5f.force); 4071 assert(ctx.getFunctionPtr!(double, double)("func_f64_const_mult")(1) == 0.5); 4072 4073 assert(ctx.getFunctionPtr!(float, float)("func_const_f32_mult")(1) == 0.5f.force); 4074 assert(ctx.getFunctionPtr!(double, double)("func_const_f64_mult")(1) == 0.5); 4075 4076 assert(ctx.getFunctionPtr!( byte, float)("func_f32_to__i8")(-127.6f.force) == -127); 4077 assert(ctx.getFunctionPtr!( short, float)("func_f32_to_i16")(-127.6f.force) == -127); 4078 assert(ctx.getFunctionPtr!( int, float)("func_f32_to_i32")(-127.6f.force) == -127); 4079 assert(ctx.getFunctionPtr!( long, float)("func_f32_to_i64")(-127.6f.force) == -127); 4080 assert(ctx.getFunctionPtr!( ubyte, float)("func_f32_to__u8")(255.6f.force) == 255); 4081 assert(ctx.getFunctionPtr!(ushort, float)("func_f32_to_u16")(255.6f.force) == 255); 4082 assert(ctx.getFunctionPtr!( uint, float)("func_f32_to_u32")(255.6f.force) == 255); 4083 assert(ctx.getFunctionPtr!( ulong, float)("func_f32_to_u64")(255.6f.force) == 255); 4084 4085 assert(ctx.getFunctionPtr!( byte, double)("func_f64_to__i8")(-127.6.force) == -127); 4086 assert(ctx.getFunctionPtr!( short, double)("func_f64_to_i16")(-127.6.force) == -127); 4087 assert(ctx.getFunctionPtr!( int, double)("func_f64_to_i32")(-127.6.force) == -127); 4088 assert(ctx.getFunctionPtr!( long, double)("func_f64_to_i64")(-127.6.force) == -127); 4089 assert(ctx.getFunctionPtr!( ubyte, double)("func_f64_to__u8")(255.6.force) == 255); 4090 assert(ctx.getFunctionPtr!(ushort, double)("func_f64_to_u16")(255.6.force) == 255); 4091 assert(ctx.getFunctionPtr!( uint, double)("func_f64_to_u32")(255.6.force) == 255); 4092 assert(ctx.getFunctionPtr!( ulong, double)("func_f64_to_u64")(255.6.force) == 255); 4093 4094 assert(ctx.getFunctionPtr!( float, byte)("func__i8_to_f32")(-127) == -127.0f.force); 4095 assert(ctx.getFunctionPtr!( float, short)("func_i16_to_f32")(-127) == -127.0f.force); 4096 assert(ctx.getFunctionPtr!( float, int)("func_i32_to_f32")(-127) == -127.0f.force); 4097 assert(ctx.getFunctionPtr!( float, long)("func_i64_to_f32")(-127) == -127.0f.force); 4098 assert(ctx.getFunctionPtr!( float, ubyte)("func__u8_to_f32")(127) == 127.0f.force); 4099 assert(ctx.getFunctionPtr!( float, ushort)("func_u16_to_f32")(127) == 127.0f.force); 4100 assert(ctx.getFunctionPtr!( float, uint)("func_u32_to_f32")(127) == 127.0f.force); 4101 assert(ctx.getFunctionPtr!( float, ulong)("func_u64_to_f32")(127) == 127.0f.force); 4102 4103 assert(ctx.getFunctionPtr!(double, byte)("func__i8_to_f64")(-127) == -127.0); 4104 assert(ctx.getFunctionPtr!(double, short)("func_i16_to_f64")(-127) == -127.0); 4105 assert(ctx.getFunctionPtr!(double, int)("func_i32_to_f64")(-127) == -127.0); 4106 assert(ctx.getFunctionPtr!(double, long)("func_i64_to_f64")(-127) == -127.0); 4107 assert(ctx.getFunctionPtr!(double, ubyte)("func__u8_to_f64")(127) == 127.0); 4108 assert(ctx.getFunctionPtr!(double, ushort)("func_u16_to_f64")(127) == 127.0); 4109 assert(ctx.getFunctionPtr!(double, uint)("func_u32_to_f64")(127) == 127.0); 4110 assert(ctx.getFunctionPtr!(double, ulong)("func_u64_to_f64")(127) == 127.0); 4111 } 4112 4113 4114 @TestInfo(&tester178) 4115 immutable test178 = q{--- test178 4116 struct Result { i32 sum; i32 maxflips; } 4117 // https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/fannkuchredux.html 4118 Result fannkuch(i32 n) { 4119 i32 signx; 4120 i32 maxflips; 4121 i32 sum; 4122 i32 i; 4123 i32 j; 4124 i32 k; 4125 i32 q1; 4126 i32 flips; 4127 i32 qq; 4128 i32 t; 4129 i32 sx; 4130 i32 tt; 4131 i32[100] p; 4132 i32[100] q; 4133 i32[100] s; 4134 4135 signx = 1; 4136 maxflips = 0; 4137 sum = 0; 4138 for (i=1; i<=n; ++i) { 4139 p[i-1] = i; 4140 q[i-1] = i; 4141 s[i-1] = i; 4142 } 4143 while (true) { 4144 q1 = p[1-1]; 4145 if (q1 != 1) { 4146 for (i=2; i<=n; ++i) { 4147 q[i-1] = p[i-1]; 4148 } 4149 flips = 1; 4150 while (true) { 4151 qq = q[q1-1]; 4152 if (qq == 1) { 4153 sum += signx*flips; 4154 if (flips > maxflips) { 4155 maxflips = flips; 4156 } 4157 break; 4158 } 4159 q[q1-1] = q1; 4160 if (q1 >= 4) { 4161 i = 2; 4162 j = q1-1; 4163 while (true) { 4164 { 4165 i32 temp = q[i-1]; 4166 q[i-1] = q[j-1]; 4167 q[j-1] = temp; 4168 } 4169 ++i; 4170 --j; 4171 if (i >= j) break; 4172 } 4173 } 4174 q1 = qq; 4175 ++flips; 4176 } 4177 } 4178 if (signx == 1) { 4179 { 4180 i32 temp = p[2-1]; 4181 p[2-1] = p[1-1]; 4182 p[1-1] = temp; 4183 } 4184 signx = -1; 4185 } 4186 else { 4187 { 4188 i32 temp = p[2-1]; 4189 p[2-1] = p[3-1]; 4190 p[3-1] = temp; 4191 } 4192 signx = 1; 4193 for (i=3; i<=n; ++i) { 4194 sx = s[i-1]; 4195 if (sx != 1) { 4196 s[i-1] = sx-1; 4197 break; 4198 } 4199 if (i == n) { 4200 return Result(sum, maxflips); 4201 } 4202 s[i-1] = i; 4203 tt = p[1-1]; 4204 for (j=1; j<=i; ++j) { 4205 p[j-1] = p[j+1-1]; 4206 } 4207 p[i+1-1] = tt; 4208 } 4209 } 4210 } 4211 } 4212 }; 4213 void tester178(ref TestContext ctx) { 4214 static struct Result { int sum; int maxflips; } 4215 auto fannkuch = ctx.getFunctionPtr!(Result, int)("fannkuch"); 4216 assert(fannkuch(3) == Result(2, 2)); 4217 //assert(fannkuch(11) == Result(556355, 51)); // slow: ~2s 4218 } 4219 4220 /* 4221 // aggregate lowering bug 4222 @TestInfo(&tester179) 4223 immutable test179 = q{--- test179 4224 void use(i64, i64){} 4225 // floats: argument passing via stack and registers 4226 u8[] decompress(i32 res, u8[] data, u8[] outBuffer) 4227 { 4228 //i32 res = LZ4_decompress_safe(data.ptr, outBuffer.ptr, cast(i32)data.length, cast(i32)outBuffer.length); 4229 if (res < 0) 4230 { 4231 use(cast(i64)data.length, cast(i64)outBuffer.length); 4232 return null; 4233 } 4234 return outBuffer[0..res]; 4235 } 4236 }; 4237 void tester179(ref TestContext ctx) { 4238 } 4239 */ 4240 4241 @TestInfo() 4242 // empty source 4243 immutable test180 = q{--- test180}; 4244 4245 4246 @TestInfo() 4247 immutable test181 = q{--- test181 4248 // alias as enum type 4249 alias ENetSocketType = i32; 4250 enum : ENetSocketType 4251 { 4252 ENET_SOCKET_TYPE_STREAM = 1, 4253 ENET_SOCKET_TYPE_DATAGRAM = 2, 4254 } 4255 }; 4256 4257 4258 @TestInfo() 4259 immutable test182 = q{--- test182 4260 // store {{}*, i8}* s0, {{}*, i8} {zeroinit, 1} 4261 // isSameType gets to compare pointers to different structs, with different number of members 4262 Struct run1() { 4263 return Struct(); 4264 } 4265 void run2() { 4266 Struct s; 4267 } 4268 struct GLFWwindow; 4269 struct Struct { 4270 GLFWwindow* window; 4271 bool isRunning = true; 4272 } 4273 }; 4274 4275 4276 @TestInfo(&tester183) 4277 immutable test183 = q{--- test183 4278 // operations on enum types 4279 enum F : u32 { 4280 f1 = 0b01, 4281 f2 = 0b10, 4282 } 4283 u32 run1() { 4284 return F.f1 | F.f2; 4285 } 4286 F run2() { 4287 return F.f1 | F.f2; 4288 } 4289 F run3(F a, F b) { 4290 return a | b; 4291 } 4292 F run4(F a) { 4293 return ~a; 4294 } 4295 }; 4296 void tester183(ref TestContext ctx) { 4297 assert(ctx.getFunctionPtr!(uint)("run1")() == 3); 4298 assert(ctx.getFunctionPtr!(uint)("run2")() == 3); 4299 assert(ctx.getFunctionPtr!(uint, uint, uint)("run3")(1, 2) == 3); 4300 assert(ctx.getFunctionPtr!(uint, uint)("run4")(1) == ~1); 4301 } 4302 4303 4304 // packages 4305 @TestInfo() 4306 immutable test184 = q{--- test184/mod1.vx 4307 module test184.mod1; 4308 --- test184/mod2.vx 4309 module test184.mod2; 4310 }; 4311 4312 4313 @TestInfo() 4314 immutable test185 = q{--- test185/mod1.vx 4315 module test185.mod1; 4316 --- test185/mod2.vx 4317 module mod2; 4318 }; 4319 4320 4321 @TestInfo(&tester186) 4322 immutable test186 = q{--- test186/mod1.vx 4323 module test186.mod1; 4324 i32 test() { return 42; } 4325 --- test186/mod2.vx 4326 module test186.mod2; 4327 import test186.mod1; 4328 i32 run() { return test(); } 4329 }; 4330 void tester186(ref TestContext ctx) { 4331 assert(ctx.getFunctionPtr!(uint)("run")() == 42); 4332 } 4333 4334 @TestInfo() 4335 immutable test187 = q{--- test187 4336 // lexer bug with leading underscore 4337 i32 _import; 4338 i32 _module; 4339 }; 4340 4341 4342 @TestInfo() 4343 immutable test188 = q{--- test188 4344 // Union 4345 union VkClearColorValue { 4346 f32[4] float32; 4347 i32[4] int32; 4348 u32[4] uint32; 4349 } 4350 VkClearColorValue getf32(f32[4] val) { 4351 VkClearColorValue result; 4352 result.float32 = val; 4353 return result; 4354 } 4355 VkClearColorValue geti32(i32[4] val) { 4356 VkClearColorValue result; 4357 result.int32 = val; 4358 return result; 4359 } 4360 VkClearColorValue getu32(u32[4] val) { 4361 VkClearColorValue result; 4362 result.uint32 = val; 4363 return result; 4364 } 4365 }; 4366 4367 4368 @TestInfo(&tester189) 4369 immutable test189 = q{--- test189 4370 // Call function pointer in member variable 4371 i32 get42(){ return 42; } 4372 struct DispatchDevice { 4373 i32 DestroyDevice() { return vkDestroyDevice(); } 4374 i32 function() vkDestroyDevice = &get42; 4375 } 4376 i32 run() { 4377 DispatchDevice dev; 4378 return dev.DestroyDevice(); 4379 } 4380 }; 4381 void tester189(ref TestContext ctx) { 4382 assert(ctx.getFunctionPtr!(int)("run")() == 42); 4383 } 4384 4385 4386 @TestInfo() 4387 immutable test190 = q{--- test190 4388 // Null enum initializer 4389 enum VK_NULL_HANDLE = null; 4390 void* run() { return VK_NULL_HANDLE; } 4391 }; 4392 4393 4394 @TestInfo() 4395 immutable test191 = q{--- test191 4396 // Unary op eval 4397 enum VK_ATTACHMENT_UNUSED = (~0); 4398 }; 4399 4400 4401 @TestInfo(&tester192) 4402 immutable test192 = q{--- test192 4403 // Default value of enum 4404 enum VkStructureType { 4405 VK_STRUCTURE_TYPE_APPLICATION_INFO = 0, 4406 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1, 4407 } 4408 struct VkBaseInStructure { 4409 VkStructureType sType; // enum default value is needed 4410 VkBaseInStructure* pNext; // recursive type 4411 } 4412 VkStructureType run() { 4413 VkBaseInStructure s; 4414 return s.sType; 4415 } 4416 }; 4417 void tester192(ref TestContext ctx) { 4418 enum VkStructureType { 4419 VK_STRUCTURE_TYPE_APPLICATION_INFO = 0, 4420 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1, 4421 } 4422 assert(ctx.getFunctionPtr!(VkStructureType)("run")() == VkStructureType.VK_STRUCTURE_TYPE_APPLICATION_INFO); 4423 } 4424 4425 @TestInfo() 4426 immutable test193 = q{--- test193 4427 // circular dependency on enum type 4428 VkStructureType sType = VkStructureType.VK_STRUCTURE_TYPE_APPLICATION_INFO; 4429 enum VkStructureType { 4430 VK_STRUCTURE_TYPE_APPLICATION_INFO = 0, 4431 } 4432 }; 4433 4434 4435 @TestInfo(&tester194) 4436 immutable test194 = q{--- test194 4437 // #version 4438 #version(windows) { 4439 i32 run() { return 1; } 4440 } 4441 else #version(linux) { 4442 i32 run() { return 2; } 4443 } 4444 else #version(macos) { 4445 i32 run() { return 3; } 4446 } 4447 else #assert(false, "Unsupported OS"); 4448 }; 4449 void tester194(ref TestContext ctx) { 4450 version(Windows) int result = 1; 4451 else version(linux) int result = 2; 4452 else version(OSX) int result = 3; 4453 assert(ctx.getFunctionPtr!int("run")() == result); 4454 } 4455 4456 4457 @TestInfo() 4458 immutable test195 = q{--- test195 4459 // Circular deps on enum type 4460 bool run() { 4461 VkResult result; 4462 return result != VkResult.VK_SUCCESS; 4463 } 4464 enum VkResult { 4465 VK_SUCCESS = 0 4466 } 4467 }; 4468 4469 4470 @TestInfo() 4471 immutable test196 = q{--- test196 4472 u8*[] var; 4473 }; 4474 4475 4476 @TestInfo() 4477 immutable test197 = q{--- test197 4478 void run() { 4479 u8* ptr; 4480 foo(ptr); 4481 } 4482 void foo(void*){} 4483 }; 4484 4485 /* 4486 @TestInfo() 4487 immutable test198 = q{--- test198 4488 // TODO: Need to either deduplicate types, or special code for == on types, or $sameType 4489 bool isU8Ptr($type type) { 4490 return type == u8*; 4491 } 4492 #assert(isU8Ptr(u8*)); 4493 }; 4494 */ 4495 4496 @TestInfo(&tester199) 4497 immutable test199 = q{--- test199 4498 alias i32_funType = i32 function(); 4499 enum i32_funType funPtrEnum = &i32Fun; 4500 i32 i32Fun() { return 42; } 4501 i32 test2() { 4502 return funPtrEnum(); 4503 } 4504 }; 4505 void tester199(ref TestContext ctx) { 4506 assert(ctx.getFunctionPtr!(int)("test2")() == 42); 4507 } 4508 4509 4510 @TestInfo() 4511 immutable test200 = q{--- test200 4512 // Common type between enum and u32 4513 enum MDBX_env_flags_t : u32 { 4514 MDBX_SAFE_NOSYNC = 0x10000, 4515 MDBX_MAPASYNC = MDBX_SAFE_NOSYNC, 4516 MDBX_UTTERLY_NOSYNC = MDBX_SAFE_NOSYNC | 0x100000, 4517 } 4518 }; 4519 4520 4521 @TestInfo() 4522 immutable test201 = q{--- test201 4523 // Enum of structs 4524 enum Colors : Color { 4525 UNEXPLORED = Color(0, 0, 0), 4526 DARK_WALL = Color(0, 0, 100), 4527 } 4528 struct Color { 4529 u8 r; 4530 u8 g; 4531 u8 b; 4532 } 4533 // Cast from enum to base struct 4534 Color color = Colors.DARK_WALL; 4535 }; 4536 4537 4538 @TestInfo() 4539 immutable test202 = q{--- test202 4540 // aggregate lowering with phi function (two paths that return a big struct) and phi has constant argument 4541 u8[] fromStringz(u8* cString, u64 len) { 4542 if (cString == null) return null; 4543 return cString[0..len]; 4544 } 4545 }; 4546 4547 4548 @TestInfo() 4549 immutable test203 = q{--- test203 4550 // String literal to u8* in ctfe 4551 u8* ptr = "hello"; 4552 struct TracyLoc { 4553 u8* name; 4554 u8* func; 4555 u8* file; 4556 u32 line; 4557 u32 color; 4558 } 4559 TracyLoc zone_loc = TracyLoc("Zonename", "update", "main.vx", 81, 0xFF00FF); 4560 }; 4561 4562 4563 @TestInfo() 4564 immutable test204 = q{--- test204 4565 // aggregate lowering 4566 struct A { 4567 i32 val1; 4568 i32 val2; 4569 } 4570 A run(A res, bool cond, i32 val) { 4571 if (cond) res.val1 = val; 4572 return res; 4573 } 4574 }; 4575 4576 4577 @TestInfo(&tester205) 4578 immutable test205 = q{--- test205 4579 // aggregate lowering 4580 struct Struct { 4581 i32 member; 4582 void set42() { 4583 this.member += 42; 4584 member = 42; 4585 } 4586 } 4587 i32 testMethod5() { 4588 Struct[1] s; 4589 s[0].set42; 4590 return s[0].member; 4591 } 4592 }; 4593 void tester205(ref TestContext ctx) { 4594 assert(ctx.getFunctionPtr!(int)("testMethod5")() == 42); 4595 } 4596 4597 4598 @TestInfo() 4599 immutable test206 = q{--- test206 4600 // 4601 struct Tile { 4602 bool blocked; 4603 bool block_sight; 4604 } 4605 4606 struct GameMap { 4607 enum map_width = 40; 4608 enum map_height = 40; 4609 Tile[40] tiles; 4610 } 4611 4612 void initialize_tiles(Tile[40]* map, i32 x) { 4613 (*map)[x].block_sight = true; 4614 } 4615 void initialize_tiles2(i32 x) { 4616 Tile[40] map; 4617 map[x].block_sight = true; 4618 } 4619 }; 4620 4621 4622 @TestInfo(&tester207) 4623 immutable test207 = q{--- test207 4624 // aggregate lowering 4625 u8[] fromStringz(u8* cString) { 4626 if (cString == null) return null; 4627 u8* cursor = cString; 4628 while(*cursor) ++cursor; 4629 u64 length = cast(u64)(cursor - cString); 4630 return cString[0..length]; 4631 } 4632 }; 4633 void tester207(ref TestContext ctx) { 4634 assert(ctx.getFunctionPtr!(Slice!(const(char)), const(char)*)("fromStringz")("test") == "test"); 4635 } 4636 4637 4638 @TestInfo(&tester208, [HostSymbol("print", cast(void*)&test208_print)]) 4639 immutable test208 = q{--- test208 4640 // bug. Could not encode 32-bit offset because static data sections were too big. 4641 void run() { 4642 print("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); 4643 print("1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); 4644 print("2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"); 4645 print("3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"); 4646 print("4444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444"); 4647 print("5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555"); 4648 print("6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666"); 4649 print("7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777"); 4650 print("8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888"); 4651 print("9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"); 4652 print("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); 4653 print("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); 4654 print("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"); 4655 print("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"); 4656 print("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"); 4657 print("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); 4658 } 4659 @extern(module, "host") 4660 void print(u8[]); 4661 }; 4662 extern(C) void test208_print(SliceString str) { 4663 testSink.put(str.slice); 4664 } 4665 void tester208(ref TestContext ctx) { 4666 ctx.getFunctionPtr!(void)("run")(); 4667 assert(testSink.text == 4668 "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"~ 4669 "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"~ 4670 "2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"~ 4671 "3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333"~ 4672 "4444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444"~ 4673 "5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555"~ 4674 "6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666"~ 4675 "7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777"~ 4676 "8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888"~ 4677 "9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"~ 4678 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"~ 4679 "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"~ 4680 "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"~ 4681 "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"~ 4682 "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"~ 4683 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); 4684 } 4685 4686 4687 @TestInfo() 4688 immutable test209 = q{--- test209 4689 // 4690 $alias selectPrintFunc($type T) { 4691 return printInt; 4692 } 4693 void printInt() { 4694 print("res"); 4695 } 4696 void print[Args...](Args... args) { 4697 alias func = selectPrintFunc(u8[]); 4698 func(); 4699 } 4700 }; 4701 4702 4703 @TestInfo(&tester210) 4704 immutable test210 = q{--- test210 4705 // struct size with forward reference 4706 u64 run() { return VkExtensionProperties.sizeof; } // 260 4707 4708 VkExtensionProperties[11] extensions; 4709 struct VkExtensionProperties { 4710 u8[256] extensionName; 4711 u32 specVersion; 4712 } 4713 }; 4714 void tester210(ref TestContext ctx) { 4715 assert(ctx.getFunctionPtr!(ulong)("run")() == 260); 4716 } 4717 4718 4719 @TestInfo(&tester211) 4720 immutable test211 = q{--- test211 4721 // code gen of `add reg global` 4722 VkExtensionProperties[11] extensions; 4723 struct VkExtensionProperties { 4724 u8[256] extensionName; 4725 } 4726 u8* get(i32 i) { 4727 return extensions[i].extensionName.ptr; 4728 } 4729 }; 4730 void tester211(ref TestContext ctx) { 4731 auto get = ctx.getFunctionPtr!(ubyte*, int)("get"); 4732 void* arenaPtr = ctx.driver.context.staticDataBuffer.bufPtr; 4733 assert(get(1) - get(0) == 256); 4734 assert(get(0) == arenaPtr); 4735 assert(get(1) == arenaPtr + 256); 4736 } 4737 4738 4739 @TestInfo() 4740 immutable test212 = q{--- test212 4741 // Forward reference for variable init value -> enum init value -> enum member init value 4742 VkQueryType queryType; 4743 enum VkQueryType { 4744 VK_QUERY_TYPE_OCCLUSION = 0, 4745 } 4746 }; 4747 4748 4749 /*@TestInfo() 4750 immutable test213 = q{--- test213 4751 // Recursive type 4752 struct Qq 4753 { 4754 i32[Qq.sizeof]* a; 4755 } 4756 };*/ 4757 4758 4759 @TestInfo(&tester214) 4760 immutable test214 = q{--- test214 4761 // code gen of add rax, imm32 generated add eax, imm32 4762 VkExtensionProperties[11] extensions; 4763 struct VkExtensionProperties { 4764 u8[256] extensionName; 4765 u32 specVersion; 4766 } 4767 void* get(i32 i) { 4768 return &extensions[i].specVersion; 4769 } 4770 }; 4771 void tester214(ref TestContext ctx) { 4772 auto get = ctx.getFunctionPtr!(void*, int)("get"); 4773 void* arenaPtr = ctx.driver.context.staticDataBuffer.bufPtr; 4774 void* ptr = get(0); 4775 4776 assert(ptr == arenaPtr + 256); 4777 assert(get(1) - get(0) == 260); 4778 } 4779 4780 4781 @TestInfo() 4782 immutable test215 = q{--- test215 4783 // UFCS for ptr type 4784 VkExtensionProperties[11] extensions; 4785 struct VkExtensionProperties { 4786 u8[256] extensionName; 4787 u32 specVersion; 4788 } 4789 void run() { 4790 extensions[0].extensionName.ptr.fromStringz; 4791 } 4792 void fromStringz(u8*){} 4793 }; 4794 4795 4796 @TestInfo() 4797 immutable test216 = q{--- test216 4798 // $baseOf 4799 #assert($baseOf(u8[]) == u8); 4800 #assert($baseOf(u8*) == u8); 4801 #assert($baseOf(u8[10]) == u8); 4802 #assert($baseOf(u16[10]) != u8); 4803 }; 4804 4805 4806 @TestInfo() 4807 immutable test217 = q{--- test217 4808 // doIfti missing ref on AstNodes, causing UFCS call that replaced node to use stale array 4809 struct VkLayerProperties { 4810 u8[1] description; 4811 } 4812 u8[] fromStringz(u8* cString) { return null; } 4813 void println[Args...](Args... args) {} 4814 void run() { 4815 VkLayerProperties layer; 4816 println(layer.description.ptr.fromStringz); 4817 println("", layer.description.ptr.fromStringz); 4818 } 4819 }; 4820 4821 @TestInfo(&tester218) 4822 immutable test218 = q{--- test218 4823 // indexing of call 4824 struct App { 4825 u8*[1] validationLayers; 4826 void init() { 4827 validationLayers[0] = "VK_LAYER_KHRONOS_validation"; 4828 } 4829 u8** get() { 4830 return validationLayers.ptr; 4831 } 4832 } 4833 u8* run() { 4834 App app; 4835 app.init; 4836 return app.get()[0]; 4837 } 4838 }; 4839 void tester218(ref TestContext ctx) { 4840 import std.string : fromStringz; 4841 auto run = ctx.getFunctionPtr!(char*)("run"); 4842 assert(run().fromStringz == "VK_LAYER_KHRONOS_validation"); 4843 } 4844 4845 @TestInfo(&tester219) 4846 immutable test219 = q{--- test219 4847 // Assigning struct member array 4848 struct S { 4849 u8** ptr; 4850 } 4851 struct App { 4852 u8*[1] validationLayers; 4853 void init() { 4854 validationLayers[0] = "VK_LAYER_KHRONOS_validation"; // here 4855 } 4856 S get() { 4857 return S(validationLayers.ptr); // also test access via .ptr 4858 } 4859 } 4860 S run() { 4861 App app; 4862 app.init; 4863 return app.get(); 4864 } 4865 }; 4866 void tester219(ref TestContext ctx) { 4867 import std.string : fromStringz; 4868 auto run = ctx.getFunctionPtr!(char**)("run"); 4869 assert((*run()).fromStringz == "VK_LAYER_KHRONOS_validation"); 4870 } 4871 4872 4873 @TestInfo(&tester220) 4874 immutable test220 = q{--- test220 4875 // slicing of static array bug 4876 struct App { 4877 u8*[1] validationLayers; 4878 void init() { 4879 validationLayers[0] = "VK_LAYER_KHRONOS_validation"; 4880 } 4881 u8* get() { 4882 return accessor(validationLayers); // here 4883 } 4884 } 4885 u8* accessor(u8*[] layers) { return layers[0]; } 4886 u8* run() { 4887 App app; 4888 app.init; 4889 return app.get(); 4890 } 4891 }; 4892 void tester220(ref TestContext ctx) { 4893 import std.string : fromStringz; 4894 auto run = ctx.getFunctionPtr!(char*)("run"); 4895 assert(run().fromStringz == "VK_LAYER_KHRONOS_validation"); 4896 } 4897 4898 4899 @TestInfo() 4900 immutable test221 = q{--- test221 4901 // store function pointer into struct member 4902 // `debugCallback` IR type was not generated because it is located after `run` 4903 struct S { 4904 void function() funcPtr; 4905 } 4906 void run() { 4907 S createInfo; 4908 createInfo.funcPtr = &debugCallback; 4909 } 4910 void debugCallback() {} 4911 }; 4912 4913 4914 @TestInfo(null, [HostSymbol("ExitProcess", cast(void*)&external_noop)]) 4915 immutable test222 = q{--- test222 4916 /// @extern(module) 4917 @extern(module, "host") 4918 noreturn ExitProcess(u32 uExitCode); 4919 }; 4920 4921 4922 @TestInfo(null, [HostSymbol("ExitProcess", cast(void*)&external_noop)]) 4923 immutable test223 = q{ 4924 /// Issue #16. `TypeCheckState.curFunc` was used in func signature, while it pointed to the caller function. 4925 void main() { 4926 ExitProcess(0); 4927 } 4928 @extern(module, "host") 4929 noreturn ExitProcess(u32 uExitCode); 4930 }; 4931 4932 4933 @TestInfo() 4934 immutable test224 = q{--- test224 4935 /// Bug with circular dependency 4936 void main() { 4937 Client client; 4938 client.run(); // 1 call 4939 } 4940 struct Client { // 4 Client 4941 void run() {} // 2 func signature, 3 Client* this, 5 run function, 6 func signature 4942 } 4943 }; 4944 4945 4946 @TestInfo() 4947 immutable test225 = q{--- test225 4948 /// Feature: `@attr:` 4949 /// Should not give an error if function with the body has broadcasted @extern attribute 4950 @extern(module, "modA"): // both are broadcasted 4951 @extern(module, "modB"): // each attribute with its own : 4952 void withAttrib(){} 4953 }; 4954 4955 4956 @TestInfo() 4957 immutable test226 = q{--- test226 4958 /// Feature: `@attr:` 4959 @extern(module, "modA") // both are broadcasted 4960 @extern(module, "modB"): // with single : 4961 void withAttrib(){} 4962 }; 4963 4964 4965 @TestInfo(null, [HostSymbol("withAttribA", cast(void*)&external_noop), HostSymbol("withAttribB", cast(void*)&external_noop)]) 4966 immutable test227 = q{--- test227 4967 /// Feature: `@attr:` 4968 /// Multiple functions with the same attribute 4969 @extern(module, "host"): 4970 void withAttribA(); 4971 void withAttribB(); 4972 }; 4973 4974 4975 @TestInfo() 4976 immutable test227_1 = q{--- test227_1 4977 /// No definitions after @: 4978 @extern(module, "modB"): 4979 }; 4980 4981 4982 /* // TODO: 4983 immutable 4984 /// Feature: `@attr:` 4985 /// Overriding with later attribute 4986 @extern(module, "host1"): 4987 void withAttribA(); 4988 @extern(module, "host2"): 4989 void withAttribB(); 4990 }; 4991 immutable 4992 /// Feature: `@attr:` 4993 /// Overriding with later attribute 4994 @extern(module, "host1"): 4995 void withAttribA(); 4996 @extern(module, "host2") 4997 void withAttribB(); 4998 }; 4999 */ 5000 5001 5002 @TestInfo() 5003 immutable test228 = q{--- test228 5004 /// Take alias of global var 5005 u32 hey; 5006 $alias getHey() { 5007 return hey; 5008 } 5009 5010 void run() { 5011 alias u = getHey(); 5012 foo(u); 5013 } 5014 5015 void foo(u32 a){} 5016 }; 5017 5018 5019 @TestInfo() 5020 immutable test229 = q{--- test229 5021 /// Attribute scope 5022 @extern(module, "host") { 5023 void foo(u32 a){} 5024 } 5025 // shouldn't get the attribute. TODO: need ability to assert that. 5026 void bar(u32 a){} 5027 }; 5028 5029 5030 @TestInfo() 5031 immutable test230 = q{--- test230 5032 /// All call variants 5033 struct S { 5034 void methodCaller() { 5035 method; 5036 method(); 5037 5038 methodT; 5039 methodT(); 5040 5041 methodT[]; 5042 methodT[](); 5043 } 5044 void method() {} 5045 void methodT[]() {} 5046 } 5047 5048 void funcCaller() { 5049 S s; 5050 5051 s.method; 5052 s.method(); 5053 5054 s.methodT; 5055 s.methodT(); 5056 5057 s.methodT[]; 5058 s.methodT[](); 5059 5060 func; 5061 func(); 5062 5063 funcT; 5064 funcT(); 5065 5066 funcT[]; 5067 funcT[](); 5068 5069 // s.funcT; // TODO 5070 // s.funcT(); // TODO 5071 // s.funcT[](); // TODO 5072 } 5073 5074 void func() {} 5075 void funcT[]() {} 5076 5077 // TODO: 5078 // UFCS 5079 // call func ptr variable 5080 // call through alias 5081 // call member functions through pointer 5082 }; 5083 5084 5085 @TestInfo(&tester231) 5086 immutable test231 = q{--- test231 5087 /// sign extension of 64-bit constants 5088 i64 run() { 5089 return -1; 5090 } 5091 }; 5092 void tester231(ref TestContext ctx) { 5093 auto run = ctx.getFunctionPtr!(long)("run"); 5094 assert(run() == -1); 5095 } 5096 5097 5098 /*@TestInfo() 5099 immutable test232 = q{--- test232 5100 /// TODO 5101 /// Semantic ordering bug. Trying to access NUM's type before it was computed 5102 void run() { 5103 for(u32 i = 0; i < S.NUM; ++i) { 5104 } 5105 } 5106 struct S { 5107 enum NUM = 2; 5108 } 5109 };*/ 5110 5111 5112 /* @TestInfo() 5113 immutable test233 = q{--- test233 5114 /// TODO 5115 /// Semantic ordering bug 5116 void run() { 5117 A a; 5118 a.b.foo(); 5119 } 5120 struct A { 5121 B[] b; 5122 } 5123 struct B[] { 5124 void foo(){} 5125 } 5126 };*/ 5127 5128 5129 @TestInfo() 5130 immutable test234 = q{--- test234 5131 /// IR gen bug. Address of `arr` must be taken and passed as first parameter of `data`. Instead it is passed by value. 5132 struct Array 5133 { 5134 u64* ptr; 5135 u64 length; 5136 u64[] data() { return ptr[0..length]; } 5137 } 5138 u64 get(Array arr) { 5139 return arr.data[0]; 5140 } 5141 }; 5142 5143 5144 @TestInfo() 5145 immutable test235 = q{--- test235 5146 /// Address of this parameter is taken, which forces it to be allocated on the stack 5147 /// Then member assignment doesn't load the stored pointer 5148 /// lowerToMember missed `memberNode.flags |= MemberExprFlags.needsDeref;` line 5149 /// Without it no deref node was generated 5150 struct S { 5151 bool b; 5152 void method() { 5153 b = false; 5154 receive(&this); 5155 } 5156 } 5157 void receive(S**){} 5158 }; 5159 5160 5161 @TestInfo() 5162 immutable test236 = q{--- test236 5163 // Bug #27. be.reg_alloc.move_solver(82): ICE: Assertion failure: Second write to rax detected 5164 5165 // First DCE removes some instructions. This leads to some phi functions not having any users. 5166 // This makes liveness analysis emit empty range for those vregs ([102; 102) and [144; 144) for example). 5167 // Then register allocator allocates two intervals to the same register, because 5168 // overlap of [144; 144) and [144; 148) is not detected and they are both allocated to eax. 5169 // Then move solver sees 2 writes to the same register and reports an error. 5170 5171 f64 to_f64(u8* s) { 5172 f64 a = 0.0; 5173 i32 c; 5174 i32 e = 0; 5175 c = *s++; // This expression will give use the "illegal hardware instruction" issue if I un-comment it 5176 while (c != '\0' && is_digit(c)) { 5177 a = a * 10.0 + (c - '0'); 5178 } 5179 5180 if (c == '.') { 5181 c = *s++; // However, the same expression doesn't give the error here 5182 while (c != '\0' && is_digit(c)) { 5183 a = a * 10.0 + (c - '0'); 5184 e = e - 1; 5185 c = *s++; // And here too! 5186 } 5187 } 5188 5189 if (c == 'e' || c == 'E') { 5190 i32 sign = 1; 5191 i32 i = 0; 5192 c = *s++; 5193 if (c == '+') c = *s++; 5194 else if (c == '-') { 5195 c = *s++; 5196 sign = -1; 5197 } 5198 5199 while (is_digit(c)) { 5200 i = i * 10 + (c - '0'); 5201 c = *s++; 5202 } 5203 e += i*sign; 5204 } 5205 return a; 5206 } 5207 5208 bool is_digit(i32 c) { 5209 return c >= '0' && c <= '9'; 5210 } 5211 }; 5212 5213 5214 @TestInfo() 5215 immutable test237 = q{--- test237 5216 // Bug #27. be.emit_mc_amd64(257): ICE: Assertion failure: reg size mismatch 2 != 3 5217 f64 to_f64(u8* s) { 5218 f64 a = 0.0; 5219 i32 c; 5220 i32 e = 0; 5221 5222 c = *s++; // This expression will give use the "illegal hardware instruction" issue if I un-comment it 5223 while (c != '\0' && is_digit(c)) { 5224 a = a * 10.0 + (c - '0'); 5225 } 5226 5227 if (c == '.') { 5228 c = *s++; // However, the same expression doesn't give the error here 5229 while (c != '\0' && is_digit(c)) { 5230 a = a * 10.0 + (c - '0'); 5231 e = e - 1; 5232 c = *s++; // And here too! 5233 } 5234 } 5235 5236 if (c == 'e' || c == 'E') { 5237 i32 sign = 1; 5238 i32 i = 0; 5239 c = *s++; 5240 if (c == '+') c = *s++; 5241 else if (c == '-') { 5242 c = *s++; 5243 sign = -1; 5244 } 5245 5246 while (is_digit(c)) { 5247 i = i * 10 + (c - '0'); 5248 c = *s++; 5249 } 5250 e += i*sign; 5251 } 5252 5253 while (e > 0) { 5254 a *= 10.0; 5255 e--; 5256 } 5257 5258 while (e < 0) { 5259 a *= 0.1; 5260 e++; 5261 } 5262 5263 return a; 5264 } 5265 5266 bool is_digit(i32 c) { 5267 return c >= '0' && c <= '9'; 5268 } 5269 }; 5270 5271 5272 @TestInfo() 5273 immutable test238 = q{--- test238 5274 /// Bug #28. Missing handling of globals, functions in move solver 5275 u8* retGlobal(i32 num) { 5276 if (num == 0) return "0"; 5277 return "1"; 5278 } 5279 void function() regFunc(i32 num) { 5280 if (num == 0) return &fun1; 5281 return &fun2; 5282 } 5283 void fun1(){} 5284 void fun2(){} 5285 }; 5286 5287 5288 @TestInfo() 5289 immutable test239 = q{--- test239 5290 // circular dependency on enum type 5291 VkSharingMode mode = VkSharingMode.VK_SHARING_MODE_CONCURRENT; 5292 enum VkSharingMode { 5293 VK_SHARING_MODE_CONCURRENT = 1, 5294 VK_SHARING_MODE_END_RANGE = VK_SHARING_MODE_CONCURRENT, 5295 } 5296 }; 5297 5298 5299 @TestInfo() 5300 immutable test240 = q{--- test240 5301 // Recursive type 5302 struct S { 5303 S[] nested1; 5304 S* nested2; 5305 } 5306 }; 5307 5308 5309 @TestInfo(&tester241) 5310 immutable test241 = q{--- test241 5311 // Compile-time int <-> float 5312 f32 i8_to_f32() { return cast(f32)cast( i8)-100; } 5313 f32 i16_to_f32() { return cast(f32)cast(i16)-100; } 5314 f32 i32_to_f32() { return cast(f32)cast(i32)-100; } 5315 f32 i64_to_f32() { return cast(f32)cast(i64)-100; } 5316 5317 f32 u8_to_f32() { return cast(f32)cast( u8)100; } 5318 f32 u16_to_f32() { return cast(f32)cast(u16)100; } 5319 f32 u32_to_f32() { return cast(f32)cast(u32)100; } 5320 f32 u64_to_f32() { return cast(f32)cast(u64)100; } 5321 5322 f64 i8_to_f64() { return cast(f64)cast( i8)-100; } 5323 f64 i16_to_f64() { return cast(f64)cast(i16)-100; } 5324 f64 i32_to_f64() { return cast(f64)cast(i32)-100; } 5325 f64 i64_to_f64() { return cast(f64)cast(i64)-100; } 5326 5327 f64 u8_to_f64() { return cast(f64)cast( u8)100; } 5328 f64 u16_to_f64() { return cast(f64)cast(u16)100; } 5329 f64 u32_to_f64() { return cast(f64)cast(u32)100; } 5330 f64 u64_to_f64() { return cast(f64)cast(u64)100; } 5331 5332 5333 i8 f32_to__i8() { return cast( i8)cast(f32)-100.5; } 5334 i16 f32_to_i16() { return cast(i16)cast(f32)-100.5; } 5335 i32 f32_to_i32() { return cast(i32)cast(f32)-100.5; } 5336 i64 f32_to_i64() { return cast(i64)cast(f32)-100.5; } 5337 5338 u8 f32_to__u8() { return cast( u8)cast(f32)100.5; } 5339 u16 f32_to_u16() { return cast(u16)cast(f32)100.5; } 5340 u32 f32_to_u32() { return cast(u32)cast(f32)100.5; } 5341 u64 f32_to_u64() { return cast(u64)cast(f32)100.5; } 5342 5343 i8 f64_to__i8() { return cast( i8)cast(f64)-100.5; } 5344 i16 f64_to_i16() { return cast(i16)cast(f64)-100.5; } 5345 i32 f64_to_i32() { return cast(i32)cast(f64)-100.5; } 5346 i64 f64_to_i64() { return cast(i64)cast(f64)-100.5; } 5347 5348 u8 f64_to__u8() { return cast( u8)cast(f64)100.5; } 5349 u16 f64_to_u16() { return cast(u16)cast(f64)100.5; } 5350 u32 f64_to_u32() { return cast(u32)cast(f64)100.5; } 5351 u64 f64_to_u64() { return cast(u64)cast(f64)100.5; } 5352 }; 5353 void tester241(ref TestContext ctx) { 5354 assert(ctx.getFunctionPtr!( float)( "i8_to_f32")() == -100); 5355 assert(ctx.getFunctionPtr!( float)("i16_to_f32")() == -100); 5356 assert(ctx.getFunctionPtr!( float)("i32_to_f32")() == -100); 5357 assert(ctx.getFunctionPtr!( float)("i64_to_f32")() == -100); 5358 5359 assert(ctx.getFunctionPtr!( float)( "u8_to_f32")() == 100); 5360 assert(ctx.getFunctionPtr!( float)("u16_to_f32")() == 100); 5361 assert(ctx.getFunctionPtr!( float)("u32_to_f32")() == 100); 5362 assert(ctx.getFunctionPtr!( float)("u64_to_f32")() == 100); 5363 5364 assert(ctx.getFunctionPtr!(double)( "i8_to_f64")() == -100); 5365 assert(ctx.getFunctionPtr!(double)("i16_to_f64")() == -100); 5366 assert(ctx.getFunctionPtr!(double)("i32_to_f64")() == -100); 5367 assert(ctx.getFunctionPtr!(double)("i64_to_f64")() == -100); 5368 5369 assert(ctx.getFunctionPtr!(double)( "u8_to_f64")() == 100); 5370 assert(ctx.getFunctionPtr!(double)("u16_to_f64")() == 100); 5371 assert(ctx.getFunctionPtr!(double)("u32_to_f64")() == 100); 5372 assert(ctx.getFunctionPtr!(double)("u64_to_f64")() == 100); 5373 5374 assert(ctx.getFunctionPtr!( byte)("f32_to__i8")() == -100); 5375 assert(ctx.getFunctionPtr!( short)("f32_to_i16")() == -100); 5376 assert(ctx.getFunctionPtr!( int)("f32_to_i32")() == -100); 5377 assert(ctx.getFunctionPtr!( long)("f32_to_i64")() == -100); 5378 5379 assert(ctx.getFunctionPtr!( ubyte)("f32_to__u8")() == 100); 5380 assert(ctx.getFunctionPtr!(ushort)("f32_to_u16")() == 100); 5381 assert(ctx.getFunctionPtr!( uint)("f32_to_u32")() == 100); 5382 assert(ctx.getFunctionPtr!( ulong)("f32_to_u64")() == 100); 5383 5384 assert(ctx.getFunctionPtr!( byte)("f64_to__i8")() == -100); 5385 assert(ctx.getFunctionPtr!( short)("f64_to_i16")() == -100); 5386 assert(ctx.getFunctionPtr!( int)("f64_to_i32")() == -100); 5387 assert(ctx.getFunctionPtr!( long)("f64_to_i64")() == -100); 5388 5389 assert(ctx.getFunctionPtr!( ubyte)("f64_to__u8")() == 100); 5390 assert(ctx.getFunctionPtr!(ushort)("f64_to_u16")() == 100); 5391 assert(ctx.getFunctionPtr!( uint)("f64_to_u32")() == 100); 5392 assert(ctx.getFunctionPtr!( ulong)("f64_to_u64")() == 100); 5393 } 5394 5395 5396 @TestInfo(&tester242) 5397 immutable test242 = q{--- test242 5398 // Compile-time binary float ops 5399 bool f32_gt() { return cast(f32)100.0 > cast(f32)50.0; } 5400 bool f32_ge() { return cast(f32)100.0 >= cast(f32)50.0; } 5401 bool f32_lt() { return cast(f32)100.0 < cast(f32)50.0; } 5402 bool f32_le() { return cast(f32)100.0 <= cast(f32)50.0; } 5403 5404 f32 f32_add() { return cast(f32)100.0 + cast(f32)100.0; } 5405 f32 f32_sub() { return cast(f32)100.0 - cast(f32)100.0; } 5406 f32 f32_mul() { return cast(f32)100.0 * cast(f32)100.0; } 5407 f32 f32_div() { return cast(f32)100.0 / cast(f32)100.0; } 5408 5409 bool f64_gt() { return cast(f64)100.0 > cast(f64)50.0; } 5410 bool f64_ge() { return cast(f64)100.0 >= cast(f64)50.0; } 5411 bool f64_lt() { return cast(f64)100.0 < cast(f64)50.0; } 5412 bool f64_le() { return cast(f64)100.0 <= cast(f64)50.0; } 5413 5414 f64 f64_add() { return cast(f64)100.0 + cast(f64)100.0; } 5415 f64 f64_sub() { return cast(f64)100.0 - cast(f64)100.0; } 5416 f64 f64_mul() { return cast(f64)100.0 * cast(f64)100.0; } 5417 f64 f64_div() { return cast(f64)100.0 / cast(f64)100.0; } 5418 }; 5419 void tester242(ref TestContext ctx) { 5420 assert(ctx.getFunctionPtr!(bool)("f32_gt")() == true); 5421 assert(ctx.getFunctionPtr!(bool)("f32_ge")() == true); 5422 assert(ctx.getFunctionPtr!(bool)("f32_lt")() == false); 5423 assert(ctx.getFunctionPtr!(bool)("f32_le")() == false); 5424 5425 assert(ctx.getFunctionPtr!(float)("f32_add")() == 100 + 100); 5426 assert(ctx.getFunctionPtr!(float)("f32_sub")() == 100 - 100); 5427 assert(ctx.getFunctionPtr!(float)("f32_mul")() == 100 * 100); 5428 assert(ctx.getFunctionPtr!(float)("f32_div")() == 100 / 100); 5429 5430 assert(ctx.getFunctionPtr!(bool)("f64_gt")() == true); 5431 assert(ctx.getFunctionPtr!(bool)("f64_ge")() == true); 5432 assert(ctx.getFunctionPtr!(bool)("f64_lt")() == false); 5433 assert(ctx.getFunctionPtr!(bool)("f64_le")() == false); 5434 5435 assert(ctx.getFunctionPtr!(double)("f64_add")() == 100 + 100); 5436 assert(ctx.getFunctionPtr!(double)("f64_sub")() == 100 - 100); 5437 assert(ctx.getFunctionPtr!(double)("f64_mul")() == 100 * 100); 5438 assert(ctx.getFunctionPtr!(double)("f64_div")() == 100 / 100); 5439 } 5440 5441 5442 @TestInfo(&tester243) 5443 immutable test243 = q{--- test243 5444 // remainder 5445 i8 rem_i8__fold() { return cast(i8) -32 % 10; } 5446 i16 rem_i16_fold() { return cast(i16)-32 % 10; } 5447 i32 rem_i32_fold() { return cast(i32)-32 % 10; } 5448 i64 rem_i64_fold() { return cast(i64)-32 % 10; } 5449 5450 u8 rem_u8__fold() { return cast(u8) 32 % 10; } 5451 u16 rem_u16_fold() { return cast(u16)32 % 10; } 5452 u32 rem_u32_fold() { return cast(u32)32 % 10; } 5453 u64 rem_u64_fold() { return cast(u64)32 % 10; } 5454 5455 i8 rem_i8__con(i8 a) { return a % 10; } 5456 i16 rem_i16_con(i16 a) { return a % 10; } 5457 i32 rem_i32_con(i32 a) { return a % 10; } 5458 i64 rem_i64_con(i64 a) { return a % 10; } 5459 5460 u8 rem_u8__con(u8 a) { return a % 10; } 5461 u16 rem_u16_con(u16 a) { return a % 10; } 5462 u32 rem_u32_con(u32 a) { return a % 10; } 5463 u64 rem_u64_con(u64 a) { return a % 10; } 5464 5465 i8 rem_i8__var(i8 a, i8 b) { return a % b; } 5466 i16 rem_i16_var(i16 a, i16 b) { return a % b; } 5467 i32 rem_i32_var(i32 a, i32 b) { return a % b; } 5468 i64 rem_i64_var(i64 a, i64 b) { return a % b; } 5469 5470 u8 rem_u8__var(u8 a, u8 b) { return a % b; } 5471 u16 rem_u16_var(u16 a, u16 b) { return a % b; } 5472 u32 rem_u32_var(u32 a, u32 b) { return a % b; } 5473 u64 rem_u64_var(u64 a, u64 b) { return a % b; } 5474 }; 5475 void tester243(ref TestContext ctx) { 5476 assert(ctx.getFunctionPtr!( byte)("rem_i8__fold")() == -32 % 10); 5477 assert(ctx.getFunctionPtr!( short)("rem_i16_fold")() == -32 % 10); 5478 assert(ctx.getFunctionPtr!( int)("rem_i32_fold")() == -32 % 10); 5479 assert(ctx.getFunctionPtr!( long)("rem_i64_fold")() == -32 % 10); 5480 5481 assert(ctx.getFunctionPtr!( ubyte)("rem_u8__fold")() == 32 % 10); 5482 assert(ctx.getFunctionPtr!(ushort)("rem_u16_fold")() == 32 % 10); 5483 assert(ctx.getFunctionPtr!( uint)("rem_u32_fold")() == 32 % 10); 5484 assert(ctx.getFunctionPtr!( ulong)("rem_u64_fold")() == 32 % 10); 5485 5486 assert(ctx.getFunctionPtr!( byte, byte)("rem_i8__con")(-32) == -32 % 10); 5487 assert(ctx.getFunctionPtr!( short, short)("rem_i16_con")(-32) == -32 % 10); 5488 assert(ctx.getFunctionPtr!( int, int)("rem_i32_con")(-32) == -32 % 10); 5489 assert(ctx.getFunctionPtr!( long, long)("rem_i64_con")(-32) == -32 % 10); 5490 5491 assert(ctx.getFunctionPtr!( ubyte, ubyte)("rem_u8__con")(32) == 32 % 10); 5492 assert(ctx.getFunctionPtr!(ushort,ushort)("rem_u16_con")(32) == 32 % 10); 5493 assert(ctx.getFunctionPtr!( uint, uint)("rem_u32_con")(32) == 32 % 10); 5494 assert(ctx.getFunctionPtr!( ulong, ulong)("rem_u64_con")(32) == 32 % 10); 5495 5496 assert(ctx.getFunctionPtr!( byte, byte, byte)("rem_i8__var")(-32, 10) == -32 % 10); 5497 assert(ctx.getFunctionPtr!( short, short, short)("rem_i16_var")(-32, 10) == -32 % 10); 5498 assert(ctx.getFunctionPtr!( int, int, int)("rem_i32_var")(-32, 10) == -32 % 10); 5499 assert(ctx.getFunctionPtr!( long, long, long)("rem_i64_var")(-32, 10) == -32 % 10); 5500 5501 assert(ctx.getFunctionPtr!( ubyte, ubyte, ubyte)("rem_u8__var")(32, 10) == 32 % 10); 5502 assert(ctx.getFunctionPtr!(ushort,ushort,ushort)("rem_u16_var")(32, 10) == 32 % 10); 5503 assert(ctx.getFunctionPtr!( uint, uint, uint)("rem_u32_var")(32, 10) == 32 % 10); 5504 assert(ctx.getFunctionPtr!( ulong, ulong, ulong)("rem_u64_var")(32, 10) == 32 % 10); 5505 } 5506 5507 5508 @TestInfo() 5509 immutable test244 = q{--- test244 5510 // small int literals are implicitly i32 5511 // but they should auto-cast if necessary 5512 5513 i8 lit_i8() { return 1; } 5514 i16 lit_i16() { return 1; } 5515 i32 lit_i32() { return 1; } 5516 i64 lit_i64() { return 1; } 5517 5518 u8 lit_u8() { return 1; } 5519 u16 lit_u16() { return 1; } 5520 u32 lit_u32() { return 1; } 5521 u64 lit_u64() { return 1; } 5522 }; 5523 5524 5525 @TestInfo() 5526 immutable test245 = r"--- test245 5527 // literal type suffix 5528 5529 f32 lit_f32a() { return 1f32; } 5530 f64 lit_f64a() { return 1f64; } 5531 f32 lit_f32b() { return 1.0f32; } 5532 f64 lit_f64b() { return 1.0f64; } 5533 5534 i8 lit_i8_() { return 1i8; } 5535 i16 lit_i16() { return 1i16; } 5536 i32 lit_i32() { return 1i32; } 5537 i64 lit_i64() { return 1i64; } 5538 5539 u8 lit_u8_() { return 1u8; } 5540 u16 lit_u16() { return 1u16; } 5541 u32 lit_u32() { return 1u32; } 5542 u64 lit_u64() { return 1u64; } 5543 5544 i8 lit_i8_b() { return 0b1i8; } 5545 i16 lit_i16b() { return 0b1i16; } 5546 i32 lit_i32b() { return 0b1i32; } 5547 i64 lit_i64b() { return 0b1i64; } 5548 5549 u8 lit_u8_b() { return 0b1u8; } 5550 u16 lit_u16b() { return 0b1u16; } 5551 u32 lit_u32b() { return 0b1u32; } 5552 u64 lit_u64b() { return 0b1u64; } 5553 5554 i8 lit_i8_x() { return 0x1i8; } 5555 i16 lit_i16x() { return 0x1i16; } 5556 i32 lit_i32x() { return 0x1i32; } 5557 i64 lit_i64x() { return 0x1i64; } 5558 5559 u8 lit_u8_x() { return 0x1u8; } 5560 u16 lit_u16x() { return 0x1u16; } 5561 u32 lit_u32x() { return 0x1u32; } 5562 u64 lit_u64x() { return 0x1u64; } 5563 "; 5564 5565 5566 @TestInfo(&tester246) 5567 immutable test246 = q{--- test246 5568 struct MonoTime { 5569 i64 ticks; 5570 Duration sub(MonoTime other) { 5571 return Duration(ticks - other.ticks); 5572 } 5573 } 5574 struct Duration { 5575 i64 ticks; 5576 } 5577 i64 run(i64 a, i64 b) { 5578 MonoTime ma = MonoTime(a); 5579 MonoTime mb = MonoTime(b); 5580 return ma.sub(mb).ticks; 5581 } 5582 }; 5583 void tester246(ref TestContext ctx) { 5584 assert(ctx.getFunctionPtr!(long, long, long)("run")(100, 40) == 60); 5585 } 5586 5587 /* 5588 @TestInfo(&tester247) 5589 immutable test247 = q{--- test247 5590 struct MonoTime { 5591 i64 ticks; 5592 Duration sub(MonoTime other) { 5593 return Duration(ticks - other.ticks); 5594 } 5595 } 5596 struct Duration { 5597 i64 ticks; 5598 } 5599 i64 run(i64 a, i64 b) { 5600 return MonoTime(a).sub(MonoTime(b)).ticks; 5601 } 5602 }; 5603 void tester247(ref TestContext ctx) { 5604 assert(ctx.getFunctionPtr!(long, long, long)("run")(100, 40) == 60); 5605 }*/ 5606 5607 5608 @TestInfo(&tester248) 5609 immutable test248 = q{--- test248.vx 5610 // special keywords 5611 u64 getLine() { return __LINE__; } 5612 u8[] getFile() { return __FILE__; } 5613 u8[] getFunctionName() { return __FUNCTION_NAME__; } 5614 u8[] getModuleName() { return __MODULE_NAME__; } 5615 }; 5616 void tester248(ref TestContext ctx) { 5617 assert(ctx.getFunctionPtr!(ulong)("getLine")() == 2); 5618 assert(ctx.getFunctionPtr!(SliceString)("getFile")() == "test248.vx"); 5619 assert(ctx.getFunctionPtr!(SliceString)("getFunctionName")() == "getFunctionName"); 5620 assert(ctx.getFunctionPtr!(SliceString)("getModuleName")() == "test248"); 5621 } 5622 5623 5624 @TestInfo(&tester249) 5625 immutable test249 = q{ 5626 --- test249_1.vx 5627 // special keywords as a default argument 5628 u64 funLine(u64 line = __LINE__) { return line; } 5629 u8[] funFile(u8[] file = __FILE__) { return file; } 5630 u8[] funFunctionName(u8[] func = __FUNCTION_NAME__) { return func; } 5631 u8[] funModuleName(u8[] mod = __MODULE_NAME__) { return mod; } 5632 --- test249_2.vx 5633 import test249_1; 5634 5635 u64 getLine() { return funLine; } 5636 u8[] getFile() { return funFile; } 5637 u8[] getFunctionName() { return funFunctionName; } 5638 u8[] getModuleName() { return funModuleName; } 5639 }; 5640 void tester249(ref TestContext ctx) { 5641 assert(ctx.getFunctionPtr!(ulong)("getLine")() == 3); 5642 assert(ctx.getFunctionPtr!(SliceString)("getFile")() == "test249_2.vx"); 5643 assert(ctx.getFunctionPtr!(SliceString)("getFunctionName")() == "getFunctionName"); 5644 assert(ctx.getFunctionPtr!(SliceString)("getModuleName")() == "test249_2"); 5645 } 5646 5647 5648 @TestInfo(&tester250) 5649 immutable test250 = q{--- test250.vx 5650 // @static variables inside functions and structs 5651 u64 incAndReturn1() { 5652 @static u64 var = 42; 5653 ++var; 5654 return var; 5655 } 5656 // broadcasted variant 5657 u64 incAndReturn2() { 5658 @static: 5659 u64 var1 = 10; 5660 u64 var2 = 42; 5661 ++var1; 5662 ++var2; 5663 return var1 + var2; 5664 } 5665 5666 struct S { 5667 @static u64 structVar = 50; 5668 u64 incAndReturn1() { 5669 ++structVar; 5670 return structVar; 5671 } 5672 u64 incAndReturn2() { 5673 ++this.structVar; 5674 return this.structVar; 5675 } 5676 } 5677 // @static struct member 5678 u64 incAndReturn3() { 5679 ++S.structVar; 5680 return S.structVar; 5681 } 5682 // through variable 5683 u64 incAndReturn4() { 5684 S s; 5685 ++s.structVar; 5686 return s.structVar; 5687 } 5688 // through method of instance 5689 u64 incAndReturn5() { 5690 S s; 5691 return s.incAndReturn1(); 5692 } 5693 // through method of instance through this 5694 u64 incAndReturn6() { 5695 S s; 5696 return s.incAndReturn2(); 5697 } 5698 }; 5699 void tester250(ref TestContext ctx) { 5700 assert(ctx.getFunctionPtr!(ulong)("incAndReturn1")() == 43); 5701 assert(ctx.getFunctionPtr!(ulong)("incAndReturn1")() == 44); 5702 5703 assert(ctx.getFunctionPtr!(ulong)("incAndReturn2")() == 11 + 43); 5704 assert(ctx.getFunctionPtr!(ulong)("incAndReturn2")() == 12 + 44); 5705 5706 assert(ctx.getFunctionPtr!(ulong)("incAndReturn3")() == 51); 5707 assert(ctx.getFunctionPtr!(ulong)("incAndReturn3")() == 52); 5708 5709 assert(ctx.getFunctionPtr!(ulong)("incAndReturn4")() == 53); 5710 assert(ctx.getFunctionPtr!(ulong)("incAndReturn4")() == 54); 5711 5712 assert(ctx.getFunctionPtr!(ulong)("incAndReturn5")() == 55); 5713 assert(ctx.getFunctionPtr!(ulong)("incAndReturn5")() == 56); 5714 5715 assert(ctx.getFunctionPtr!(ulong)("incAndReturn6")() == 57); 5716 assert(ctx.getFunctionPtr!(ulong)("incAndReturn6")() == 58); 5717 } 5718 5719 5720 @TestInfo() 5721 immutable test251 = q{--- test251.vx 5722 // Forbid @static on parameters 5723 void fun(@static u64 param) {} 5724 --- <error> 5725 test251.vx:2:23: Error: Parameters cannot be @static 5726 }; 5727 5728 5729 @TestInfo(&tester252) 5730 immutable test252 = q{--- test252.vx 5731 // @static methods 5732 struct S { 5733 @static u64 structVar = 50; 5734 @static u64 incAndReturnStatic() { 5735 ++structVar; 5736 return structVar; 5737 } 5738 } 5739 // through static method 5740 u64 incAndReturn1() { 5741 return S.incAndReturnStatic(); 5742 } 5743 // through static method via instance 5744 u64 incAndReturn2() { 5745 S s; 5746 return s.incAndReturnStatic(); 5747 } 5748 // check that access to non-static members from static method is forbidden 5749 }; 5750 void tester252(ref TestContext ctx) { 5751 assert(ctx.getFunctionPtr!(ulong)("incAndReturn1")() == 51); 5752 assert(ctx.getFunctionPtr!(ulong)("incAndReturn1")() == 52); 5753 5754 assert(ctx.getFunctionPtr!(ulong)("incAndReturn2")() == 53); 5755 assert(ctx.getFunctionPtr!(ulong)("incAndReturn2")() == 54); 5756 } 5757 5758 5759 @TestInfo() 5760 immutable test253 = q{--- test253.vx 5761 // Forbid access to non-@static member from @static method 5762 // @static methods 5763 struct S { 5764 u64 structVar = 50; 5765 @static void useNonstatic() { 5766 ++structVar; 5767 } 5768 } 5769 --- <error> 5770 test253.vx:6:6: Error: undefined identifier `this` 5771 }; 5772 5773 5774 @TestInfo() 5775 immutable test254 = q{--- test254.vx 5776 alias PFN_vkAllocationFunction = void* function(void* pUserData); 5777 }; 5778 5779 5780 @TestInfo() 5781 immutable test255 = q{--- test255.vx 5782 // Issue 40 5783 // Incorrect aggregate lowering 5784 // Was checking for isConstant, which ignored zero constants 5785 struct Color { u8 r; u8 g; u8 b; u8 a; } 5786 5787 void draw() { 5788 for(u64 i = 0; i < 4; i++){ 5789 u8 a = cast(u8) i; 5790 Color c = Color(255, 0, 0, a); 5791 } 5792 } 5793 }; 5794 5795 5796 @TestInfo() 5797 immutable test256 = `--- test256.vx 5798 // Logical not CTFE 5799 enum VAL = true; 5800 5801 #if(!VAL) struct A {} 5802 `; 5803 5804 @TestInfo(&tester257) 5805 immutable test257 = q{--- test257.vx 5806 // offsetof 5807 struct Color { u8 r; u8 g; u8 b; u8 a; } 5808 5809 u64 offsetof_r() { return Color.r.offsetof; } 5810 u64 offsetof_g() { return Color.g.offsetof; } 5811 u64 offsetof_b() { return Color.b.offsetof; } 5812 u64 offsetof_a() { return Color.a.offsetof; } 5813 }; 5814 void tester257(ref TestContext ctx) { 5815 assert(ctx.getFunctionPtr!(ulong)("offsetof_r")() == 0); 5816 assert(ctx.getFunctionPtr!(ulong)("offsetof_g")() == 1); 5817 assert(ctx.getFunctionPtr!(ulong)("offsetof_b")() == 2); 5818 assert(ctx.getFunctionPtr!(ulong)("offsetof_a")() == 3); 5819 } 5820 5821 5822 @TestInfo() 5823 immutable test258 = q{--- test258.vx 5824 // offsetof only applies to `type.member`, not `instance.member` 5825 struct Color { u8 r; u8 g; u8 b; u8 a; } 5826 5827 u64 offsetof_a(Color c) { return c.offsetof; } 5828 --- <error> 5829 test258.vx:4:36: Error: `Color` has no member `offsetof` 5830 }; 5831 5832 5833 @TestInfo() 5834 immutable test259 = q{--- test259.vx 5835 // offsetof should not work on non-struct types 5836 enum a; 5837 enum b {m} 5838 enum test_1 = a.offsetof; 5839 enum test_2 = u8.offsetof; 5840 enum test_3 = b.m.offsetof; 5841 --- <error> 5842 test259.vx:4:17: Error: `a` has no member `offsetof` 5843 test259.vx:5:18: Error: `u8` has no member `offsetof` 5844 test259.vx:6:19: Error: `b` has no member `offsetof` 5845 }; 5846 5847 5848 @TestInfo(&tester260) 5849 immutable test260 = q{--- test260.vx 5850 // offsetof with non-static members 5851 struct Color { 5852 u8 r; 5853 enum e; 5854 u8 g; 5855 alias e1 = e; 5856 u8 b; 5857 u8 a; 5858 } 5859 5860 u64 offsetof_r() { return Color.r.offsetof; } 5861 u64 offsetof_g() { return Color.g.offsetof; } 5862 u64 offsetof_b() { return Color.b.offsetof; } 5863 u64 offsetof_a() { return Color.a.offsetof; } 5864 //u64 offsetof_e() { return Color.e.offsetof; } 5865 }; 5866 void tester260(ref TestContext ctx) { 5867 assert(ctx.getFunctionPtr!(ulong)("offsetof_r")() == 0); 5868 assert(ctx.getFunctionPtr!(ulong)("offsetof_g")() == 1); 5869 assert(ctx.getFunctionPtr!(ulong)("offsetof_b")() == 2); 5870 assert(ctx.getFunctionPtr!(ulong)("offsetof_a")() == 3); 5871 } 5872 5873 5874 @TestInfo() 5875 immutable test261 = q{--- test261.vx 5876 // offsetof only applies to non-static memebers 5877 struct Color { enum e; alias e1 = e; @static u8 g; } 5878 5879 u64 offsetof_e() { return Color.e.offsetof; } 5880 u64 offsetof_e1() { return Color.e1.offsetof; } 5881 u64 offsetof_g() { return Color.g.offsetof; } 5882 --- <error> 5883 test261.vx:4:35: Error: `e` has no member `offsetof` 5884 test261.vx:5:37: Error: `e` has no member `offsetof` 5885 test261.vx:6:35: Error: `u8` has no member `offsetof` 5886 }; 5887 5888 5889 @TestInfo() 5890 immutable test262 = q{--- test262.vx 5891 // bug Type [2 x {i32, i32, i32, i32}] of size 32 cannot be stored in a register 5892 // caused by generating load instead of load_aggregate for arrays 5893 struct Color { i32 r; i32 g; i32 b; i32 a; } 5894 Color[2] get() { Color[2] c; return c; } 5895 }; 5896 5897 5898 @TestInfo(&tester266) 5899 immutable test266 = q{--- test266.vx 5900 // using int literals to initialize floats 5901 f32 get_f32() { 5902 f32 val = 1; 5903 return val; 5904 } 5905 f64 get_f64() { 5906 f64 val = 1; 5907 return val; 5908 } 5909 }; 5910 void tester266(ref TestContext ctx) { 5911 assert(ctx.getFunctionPtr!(float)("get_f32")() == 1.0f); 5912 assert(ctx.getFunctionPtr!(double)("get_f64")() == 1.0); 5913 } 5914 5915 5916 @TestInfo(&tester267) 5917 immutable test267 = q{--- test267.vx 5918 // implicit conversion of pointer to bool 5919 bool null_to_bool() { 5920 return null; 5921 } 5922 bool ptr_to_bool(void* ptr) { 5923 return ptr; 5924 } 5925 bool u8_ptr_to_bool(u8* ptr) { 5926 return ptr; 5927 } 5928 struct Handle_dummy; alias Handle = Handle_dummy*; 5929 bool struct_ptr_to_bool(Handle ptr) { 5930 return ptr; 5931 } 5932 u8 null_branch() { 5933 if(null) return 42; 5934 return 12; 5935 } 5936 u8 ptr_branch(void* ptr) { 5937 if(ptr) return 42; 5938 return 12; 5939 } 5940 u8 u8_ptr_branch(u8* ptr) { 5941 if(ptr) return 42; 5942 return 12; 5943 } 5944 u8 struct_ptr_branch(Handle ptr) { 5945 if(ptr) return 42; 5946 return 12; 5947 } 5948 }; 5949 void tester267(ref TestContext ctx) { 5950 ubyte var; 5951 assert(ctx.getFunctionPtr!(bool)("null_to_bool")() == false); 5952 assert(ctx.getFunctionPtr!(bool, void*)("ptr_to_bool")(null) == false); 5953 assert(ctx.getFunctionPtr!(bool, void*)("ptr_to_bool")(&var) == true); 5954 assert(ctx.getFunctionPtr!(bool, void*)("u8_ptr_to_bool")(null) == false); 5955 assert(ctx.getFunctionPtr!(bool, void*)("u8_ptr_to_bool")(&var) == true); 5956 assert(ctx.getFunctionPtr!(bool, void*)("struct_ptr_to_bool")(null) == false); 5957 assert(ctx.getFunctionPtr!(bool, void*)("struct_ptr_to_bool")(&var) == true); 5958 assert(ctx.getFunctionPtr!(ubyte)("null_branch")() == 12); 5959 assert(ctx.getFunctionPtr!(ubyte, void*)("ptr_branch")(null) == 12); 5960 assert(ctx.getFunctionPtr!(ubyte, void*)("ptr_branch")(&var) == 42); 5961 assert(ctx.getFunctionPtr!(ubyte, void*)("u8_ptr_branch")(null) == 12); 5962 assert(ctx.getFunctionPtr!(ubyte, void*)("u8_ptr_branch")(&var) == 42); 5963 assert(ctx.getFunctionPtr!(ubyte, void*)("struct_ptr_branch")(null) == 12); 5964 assert(ctx.getFunctionPtr!(ubyte, void*)("struct_ptr_branch")(&var) == 42); 5965 } 5966 5967 5968 @TestInfo() 5969 immutable test268 = `--- test268.vx 5970 // auto for variable declarations in function body 5971 struct S {} 5972 enum E { e = 1 } 5973 void fun() { 5974 auto val_i8 = 1_i8; 5975 auto val_i16 = 1_i16; 5976 auto val_i32 = 1_i32; 5977 auto val_i64 = 1_i64; 5978 auto val_u8 = 1_u8; 5979 auto val_u16 = 1_u16; 5980 auto val_u32 = 1_u32; 5981 auto val_u64 = 1_u64; 5982 auto val_f32 = 1_f32; 5983 auto val_f64 = 1_f64; 5984 auto val_bool = true; 5985 auto val_null = null; 5986 auto val_S = S(); 5987 auto val_E = E.e; 5988 auto val_type = u8; 5989 } 5990 auto val_i8 = 1_i8; 5991 auto val_i16 = 1_i16; 5992 auto val_i32 = 1_i32; 5993 auto val_i64 = 1_i64; 5994 auto val_u8 = 1_u8; 5995 auto val_u16 = 1_u16; 5996 auto val_u32 = 1_u32; 5997 auto val_u64 = 1_u64; 5998 auto val_f32 = 1_f32; 5999 auto val_f64 = 1_f64; 6000 auto val_bool = true; 6001 auto val_null = null; 6002 auto val_S = S(); 6003 auto val_E = E.e; 6004 auto val_type = u8; 6005 `; 6006 6007 6008 @TestInfo() 6009 immutable test269 = q{--- test269.vx 6010 // functions returning auto 6011 auto fun() {} 6012 --- <error> 6013 test269.vx:2:7: Error: functions cannot return `auto` 6014 }; 6015 6016 6017 @TestInfo() 6018 immutable test270 = q{--- test270.vx 6019 // functions returning auto 6020 auto fun[T]() {} 6021 --- <error> 6022 test270.vx:2:7: Error: functions cannot return `auto` 6023 }; 6024 6025 6026 @TestInfo() 6027 immutable test271 = q{--- test271.vx 6028 // auto variables requiring initializer 6029 auto var; 6030 --- <error> 6031 test271.vx:2:7: Error: variables declared as `auto` must have an initializer 6032 }; 6033 6034 6035 @TestInfo(&tester272) 6036 immutable test272 = q{--- test272.vx 6037 // named arguments 6038 i32 func(i32 param1, i32 param2, i32 param3) { return param1 * 40 + param2 * 20 + param3; } 6039 i32 call_0() { return func(1, 2, 3); } 6040 i32 call_1() { return func(param1: 1, 2, 3); } 6041 i32 call_2() { return func(1, param2: 2, 3); } 6042 i32 call_3() { return func(1, 2, param3: 3); } 6043 i32 call_4() { return func(param1: 1, param2: 2, 3); } 6044 i32 call_5() { return func(param2: 2, 3, param1: 1, ); } 6045 i32 call_6() { return func(param1: 1, 2, param3: 3); } 6046 i32 call_7() { return func(param3: 3, param1: 1, 2); } 6047 i32 call_8() { return func(1, param2: 2, param3: 3); } 6048 i32 call_9() { return func(1, param3: 3, param2: 2); } 6049 i32 call10() { return func(param1: 1, param2: 2, param3: 3); } 6050 i32 call11() { return func(param1: 1, param3: 3, param2: 2); } 6051 i32 call12() { return func(param2: 2, param1: 1, param3: 3); } 6052 i32 call13() { return func(param2: 2, param3: 3, param1: 1); } 6053 i32 call14() { return func(param3: 3, param1: 1, param2: 2); } 6054 i32 call15() { return func(param3: 3, param2: 2, param1: 1); } 6055 }; 6056 void tester272(ref TestContext ctx) { 6057 assert(ctx.getFunctionPtr!(int)("call_0")() == 83); 6058 assert(ctx.getFunctionPtr!(int)("call_1")() == 83); 6059 assert(ctx.getFunctionPtr!(int)("call_2")() == 83); 6060 assert(ctx.getFunctionPtr!(int)("call_3")() == 83); 6061 assert(ctx.getFunctionPtr!(int)("call_4")() == 83); 6062 assert(ctx.getFunctionPtr!(int)("call_5")() == 83); 6063 assert(ctx.getFunctionPtr!(int)("call_6")() == 83); 6064 assert(ctx.getFunctionPtr!(int)("call_7")() == 83); 6065 assert(ctx.getFunctionPtr!(int)("call_8")() == 83); 6066 assert(ctx.getFunctionPtr!(int)("call_9")() == 83); 6067 assert(ctx.getFunctionPtr!(int)("call10")() == 83); 6068 assert(ctx.getFunctionPtr!(int)("call11")() == 83); 6069 assert(ctx.getFunctionPtr!(int)("call12")() == 83); 6070 assert(ctx.getFunctionPtr!(int)("call13")() == 83); 6071 assert(ctx.getFunctionPtr!(int)("call14")() == 83); 6072 } 6073 6074 @TestInfo() 6075 immutable test273 = q{--- test273.vx 6076 // named arguments, error cases 6077 i32 func(i32 param1, i32 param2, i32 param3) { return param1 * 40 + param2 * 20 + param3; } 6078 i32 call_1() { return func(param4: 4, 1, 2); } // nonexisting named parameter 6079 i32 call_2() { return func(param2: 2, 1, 3); } // setting parameter 4, param1 not set 6080 i32 call_3() { return func(param3: 3, 1, 2); } // setting parameter 4 and 5, params 1 and 2 not set 6081 i32 call_4() { return func(param1: 1, param1: 1, 2); } // setting parameter 1 twice 6082 --- <error> 6083 test273.vx:3:29: Error: Function `func` has no parameter named `param4` 6084 test273.vx:3:28: Error: Missing argument for parameter 1: `param1` 6085 test273.vx:3:28: Error: Missing argument for parameter 2: `param2` 6086 test273.vx:3:28: Error: Missing argument for parameter 3: `param3` 6087 test273.vx:4:43: Error: Trying to provide parameter 4, while `func` has 3 parameters 6088 test273.vx:4:28: Error: Missing argument for parameter 1: `param1` 6089 test273.vx:5:40: Error: Trying to provide parameter 4, while `func` has 3 parameters 6090 test273.vx:5:43: Error: Trying to provide parameter 5, while `func` has 3 parameters 6091 test273.vx:5:28: Error: Missing argument for parameter 1: `param1` 6092 test273.vx:5:28: Error: Missing argument for parameter 2: `param2` 6093 test273.vx:6:40: Error: Parameter `param1` provided several times 6094 test273.vx:6:28: Error: Missing argument for parameter 3: `param3` 6095 }; 6096 6097 6098 @TestInfo(&tester274) 6099 immutable test274 = q{--- test274.vx 6100 // named arguments with default arguments 6101 i32 func(i32 param1, i32 param2, i32 param3 = 3) { return param1 * 40 + param2 * 20 + param3; } 6102 i32 call_0() { return func(1, 2); } 6103 i32 call_1() { return func(1, 2, 3); } 6104 i32 call_2() { return func(param1: 1, 2); } 6105 i32 call_3() { return func(1, param2: 2); } 6106 i32 call_4() { return func(param1: 1, param2: 2); } 6107 i32 call_5() { return func(param2: 2, param1: 1); } 6108 }; 6109 void tester274(ref TestContext ctx) { 6110 assert(ctx.getFunctionPtr!(int)("call_0")() == 83); 6111 assert(ctx.getFunctionPtr!(int)("call_1")() == 83); 6112 assert(ctx.getFunctionPtr!(int)("call_2")() == 83); 6113 assert(ctx.getFunctionPtr!(int)("call_3")() == 83); 6114 assert(ctx.getFunctionPtr!(int)("call_4")() == 83); 6115 assert(ctx.getFunctionPtr!(int)("call_5")() == 83); 6116 } 6117 6118 6119 @TestInfo() 6120 immutable test275 = q{--- test275.vx 6121 // named arguments, anonymous parameters 6122 void func(i32) {} 6123 void call() { return func(__param_0: 1); } 6124 --- <error> 6125 test275.vx:3:28: Error: Function `func` has no parameter named `__param_0` 6126 test275.vx:3:27: Error: Missing argument for anonymous parameter 1 6127 }; 6128 6129 6130 @TestInfo(&tester276) 6131 immutable test276 = q{--- test276.vx 6132 // return void typed expression from void function 6133 void func() {} 6134 void call() { return func(); } 6135 }; 6136 void tester276(ref TestContext ctx) { 6137 ctx.getFunctionPtr!(void)("call")(); 6138 } 6139 6140 6141 @TestInfo(&tester277) 6142 immutable test277 = q{--- test277.vx 6143 // named arguments for structs (named cannot be mixed with positional) 6144 struct Color { u8 r = 1; u8 g = 2; u8 b = 3; u8 a; } 6145 Color make_0() { return Color(r: 1, g: 2, b: 3, a: 4); } 6146 Color make_1() { return Color(r: 1); } 6147 Color make_2() { return Color(r: 1, a: 4); } 6148 Color make_3() { return Color(a: 4, b: 3, g: 2, r: 1); } 6149 //union Union { u32 u; bool b; f32 f; } 6150 //Union make_4() { return Union(u: 100); } 6151 //Union make_5() { return Union(b: true); } 6152 //Union make_6() { return Union(f: 10); } 6153 }; 6154 void tester277(ref TestContext ctx) { 6155 static struct Color { ubyte r; ubyte g; ubyte b; ubyte a; } 6156 static struct Union { 6157 this(uint u){ this.u = u; } 6158 this(bool b){ this.b = b; } 6159 this(float f){ this.f = f; } 6160 uint u; 6161 bool b; 6162 float f; 6163 } 6164 assert(ctx.getFunctionPtr!(Color)("make_0")() == Color(1, 2, 3, 4)); 6165 assert(ctx.getFunctionPtr!(Color)("make_1")() == Color(1, 2, 3, 0)); 6166 assert(ctx.getFunctionPtr!(Color)("make_2")() == Color(1, 2, 3, 4)); 6167 assert(ctx.getFunctionPtr!(Color)("make_3")() == Color(1, 2, 3, 4)); 6168 //assert(ctx.getFunctionPtr!(Union)("make_4")() == Union(100)); 6169 } 6170 6171 6172 @TestInfo() 6173 immutable test278 = q{--- test278.vx 6174 // nnamed arguments for structs, errors 6175 struct Color { u8 r = 1; u8 g = 2; u8 b = 3; u8 a; } 6176 struct ColorStatic { @static u8 r = 1; u8 g = 2; u8 b = 3; u8 a; } 6177 union U { u8 b; f32 f; } 6178 Color make_1() { return Color(r: 1, g: 2, b: 3, w: 4); } 6179 ColorStatic make_2() { return ColorStatic(r: 1); } 6180 Color make_3() { return Color(1, 2, 3, 4, 5); } 6181 Color make_4() { return Color(r: 1, 2, 3, 4, 5); } 6182 U make_5() { return U(b: 1, f: 1.0); } 6183 --- <error> 6184 test278.vx:5:50: Error: struct `Color` has no member named `w` 6185 test278.vx:6:44: Error: cannot initialize variable `r` of struct `ColorStatic` 6186 test278.vx:7:31: Error: cannot initialize struct `Color` with 5 arguments, it has 4 members 6187 test278.vx:8:31: Error: cannot initialize struct `Color` with 5 arguments, it has 4 members 6188 test278.vx:8:38: Error: named and positional arguments cannot be mixed in struct constructor 6189 test278.vx:9:23: Error: union constructor must have a single argument, not 2 6190 }; 6191 6192 6193 @TestInfo() 6194 immutable test279 = q{--- test279.vx 6195 // issue 42. Call expression of index expression didn't account for different template kinds and always assumed function template 6196 struct Vector[T] { 6197 T* ptr; 6198 u64 capacity; 6199 u64 length; 6200 } 6201 6202 void main() { 6203 Vector[i32] numbers = Vector[i32](null, 10, 0); 6204 } 6205 }; 6206 6207 6208 @TestInfo() 6209 immutable test280 = q{--- test280.vx 6210 // issue 43. Missing check for expand operator on non-templated function 6211 void printa(u8[]... data) {} 6212 --- <error> 6213 test280.vx:2:22: Error: Variadic arrays are not yet implemented 6214 }; 6215 6216 6217 @TestInfo() 6218 immutable test281 = q{--- test281.vx 6219 // issue 44. Missing check for expand operator on templated function without variadic parameter 6220 void print[Args](Args... data) {} 6221 void run() { 6222 print("Hello", ", ", "world!\n"); 6223 } 6224 --- <error> 6225 test281.vx:2:27: Error: Variadic parameters are not implemented 6226 }; 6227 6228 6229 @TestInfo() 6230 immutable test282 = q{--- test282.vx 6231 // issue 44 6232 void print[Args](Args data) {} 6233 void run() { 6234 print("Hello", ", ", "world!\n"); 6235 } 6236 --- <error> 6237 test282.vx:4:8: Error: Cannot infer template parameters. Number of runtime arguments (3) does not match number of function parameters (1) 6238 }; 6239 6240 6241 @TestInfo() 6242 immutable test283 = q{--- test283.vx 6243 // Templated method with IFTI 6244 struct S { 6245 void methodCaller() { 6246 methodT(42); 6247 methodT[](42); 6248 } 6249 void method(i32 arg) {} 6250 void methodT[](i32 arg) {} 6251 } 6252 }; 6253 6254 6255 @TestInfo() 6256 immutable test284 = q{--- test284.vx 6257 // Check for expand on incorrect template parameter 6258 void print[T, Args...](T... data) {} 6259 void run() { 6260 print("Hello", ", ", "world!\n"); 6261 } 6262 --- <error> 6263 test284.vx:2:30: Error: Should be `Args... data` 6264 test284.vx:2:30: Error: Cannot expand non-variadic template parameter T 6265 }; 6266 6267 6268 @TestInfo() 6269 immutable test285 = q{--- test285.vx 6270 // Use of non-expanded variadic type 6271 void print[Args...](Args data) {} 6272 void run() { 6273 print("Hello", ", ", "world!\n"); 6274 } 6275 --- <error> 6276 test285.vx:2:22: Error: Should be `Args... data` 6277 test285.vx:4:8: Error: Cannot infer template parameters. Number of runtime arguments (3) does not match number of function parameters (1) 6278 }; 6279 6280 6281 6282 @TestInfo() 6283 immutable test286 = q{--- test286.vx 6284 // Report error on out-of-bound access to array 6285 void sys_write(void* ptr){} 6286 void printa[Args...](Args... data) { 6287 sys_write(data[3].ptr); 6288 } 6289 void main() { 6290 printa("Hello", ", ", "world!\n"); 6291 } 6292 --- <error> 6293 test286.vx:4:17: Error: Accessing index 3 of array of length 3 6294 }; 6295 6296 6297 @TestInfo() 6298 immutable test287 = q{--- test287.vx 6299 // Forward reference bug. Type of `b` was not type checked 6300 struct Array[T] {} 6301 struct Ctx { 6302 S a; 6303 } 6304 struct S { 6305 Array[i32] b; 6306 } 6307 }; 6308 6309 6310 @TestInfo(&tester288) 6311 immutable test288 = q{--- test288.vx 6312 // Aggregate lowering bug with constant aggregate nested inside non-constant one 6313 struct vec3 { f32 x; f32 y; f32 z; } 6314 struct Vertex { 6315 f32 pos; 6316 vec3 color; 6317 } 6318 Vertex putQuadAt(f32 pos) { 6319 return Vertex(pos, vec3(1, 0, 0)); 6320 } 6321 }; 6322 void tester288(ref TestContext ctx) { 6323 static struct vec3 { float x; float y; float z; } 6324 static struct Vertex { float pos; vec3 color; } 6325 assert(ctx.getFunctionPtr!(Vertex, float)("putQuadAt")(56.0f) == Vertex(56.0f, vec3(1, 0, 0))); 6326 } 6327 6328 6329 /* 6330 TODO 6331 @TestInfo(&tester289) 6332 immutable test289 = q{--- test289.vx 6333 // Aggregate of float type 6334 struct vec2 { f32 x; f32 y; } 6335 vec2 make(f32 x, f32 y) { 6336 return vec2(x, y); 6337 } 6338 }; 6339 void tester289(ref TestContext ctx) { 6340 static struct vec2 { float x; float y; } 6341 assert(ctx.getFunctionPtr!(vec2, float, float)("make")(56.0f, 30.0f) == vec2(56.0f, 30.0f)); 6342 }*/ 6343 6344 6345 @TestInfo(&tester290, [HostSymbol("noop", cast(void*)&external_noop)]) 6346 immutable test290 = q{--- test290.vx 6347 // Taking address of the external symbol 6348 @extern(module, "host") void noop(); 6349 void* run() { 6350 return &noop; 6351 } 6352 }; 6353 void tester290(ref TestContext ctx) { 6354 assert(ctx.getFunctionPtr!(void*)("run")() == &external_noop); 6355 }