1# Copyright (c) 2021-2022 Huawei Device Co., Ltd. 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13--- 14definitions: 15 - name: PandaAssembly 16 template: > 17 .language PandaAssembly 18 - name: r_A 19 template: | 20 .record A {} 21 22 .function void A.constructor(A a0) <ctor> { 23 return.void 24 } 25 - name: NPE 26 template: | 27 .record panda.NullPointerException <external> 28 - name: j_NPE 29 template: | 30 .record panda.NullPointerException <external> 31 - name: AME 32 template: | 33 .record panda.AbstractMethodError <external> 34 .record panda.Class <external> 35 - name: j_AME 36 template: | 37 .record panda.AbstractMethodError <external> 38 .record panda.Class <external> 39tests: 40 - file-name: call.virt.range_base 41 isa: 42 instructions: 43 - sig: call.virt.range method_id, v:in:top 44 acc: out:top 45 format: [op_v_8_id_16] 46 title: Object calls 47 description: > 48 Call indicated object method, i.e. create new frame, pass values of arguments and 49 continue execution from the first instruction of a method. 50 Callee should treat accumulator value as undefined and cannot use it until accumulator 51 definition in the new frame. 52 Result (if any) is returned in accumulator (see 'Calling sequence' chapter for more details). 53 Method, its class and the number of argument is resolved by given method_id in runtime 54 constant-pool based on object reference using language-specific semantics (currently only PandaAssembly 55 virtual methods are supported, further extensions are TBD). 56 Object reference is passed in the first source register, arguments are passed starting from 57 the second source register in the same order as in method signature. 58 Non-range instructions can be used to pass up to 4 arguments (including object reference). 59 Unused register slot values will be discarded and corresponding registers will not be 60 passed to the callee). 61 For methods with more arguments range kinds of instruction are to be used, which takes 62 the needed number of arguments starting from 'vs' register (including object reference). 63 verification: 64 - method_id_non_static 65 - compatible_arguments 66 - method_id_accessible 67 exceptions: 68 - x_null 69 - x_abstract 70 commands: 71 - file-name: method_call 72 isa: 73 instructions: 74 - sig: call.virt.range method_id, v:in:top 75 acc: out:top 76 format: [op_v_8_id_16] 77 header-template: [r_A] 78 description: > 79 Invoke virtual method with different amount (0, 1, 2 or 3) and type of argument. Primitives and reference types are used as second argument. 80 Check return value. 81 tags: ['tsan'] 82 code-template: | 83 *s 84 .function %s A.foo(A a0*s) { 85 %s 86 } 87 88 .function i32 main() { 89 initobj.short A.constructor 90 sta.obj v0 91 *s 92 call.virt.range A.foo, v0 93 %s 94 template-cases: 95 - values: 96 - i32 97 - | 98 # 99 ldai 123456789 100 return 101 - | 102 # 103 movi v0, 123456789 104 jne v0, set_failure 105 ldai 0 106 jmp fall_through 107 set_failure: 108 ldai 1 109 fall_through: 110 - values: 111 - i64 112 - | 113 # 114 ldai.64 123456789 115 return.64 116 - | 117 # 118 movi.64 v0, 123456789 119 cmp.64 v0 120 - values: 121 - f64 122 - | 123 # 124 fldai.64 1234567.89 125 return.64 126 - | 127 # 128 fmovi.64 v0, 1234567.89 129 fcmpg.64 v0 130 check-type: check-positive 131 cases: 132 - values: 133 - '' 134 - '' 135 - '' 136 - values: 137 - '' 138 - ', i32 a1' 139 - 'movi v1, 123' 140 - values: 141 - '' 142 - ',i64 a1' 143 - 'movi.64 v1, 123' 144 - values: 145 - '' 146 - ',i64[] a1' 147 - | 148 # 149 movi v1, 123 150 newarr v1, v1, i64[] 151 - values: 152 - '' 153 - ',A a1' 154 - | 155 # 156 initobj.short A.constructor 157 sta.obj v1 158 - values: 159 - '' 160 - ', i32[] a1, i64 a2' 161 - | 162 # 163 movi v1, 123 164 newarr v1, v1, i32[] 165 movi.64 v2, 0x100000000 166 - values: 167 - '' 168 - ', i64[] a1, A a2' 169 - | 170 # 171 movi v1, 123 172 newarr v1, v1, i64[] 173 initobj.short A.constructor 174 sta.obj v2 175 - values: 176 - '' 177 - ',A[] a1, f64 a2' 178 - | 179 # 180 movi v1, 123 181 newarr v1, v1, A[] 182 fmovi.64 v2, 123.321 183 - values: 184 - '.record panda.String <external>' 185 - ', f64[] a1, panda.String a2' 186 - | 187 # 188 movi v1, 123 189 newarr v1, v1, f64[] 190 lda.str "some string" 191 sta.obj v2 192 - values: 193 - | 194 .record panda.String <external> 195 .record panda.Object <external> 196 - ', panda.String[] a1, panda.Object[] a2' 197 - | 198 # 199 movi v1, 123 200 newarr v1, v1, panda.String[] 201 movi v2, 321 202 newarr v2, v2, panda.Object[] 203 - values: 204 - '.record panda.Object <external>' 205 - ', panda.Object[] a1, panda.Object a2' 206 - | 207 # 208 movi v1, 123 209 newarr v1, v1, panda.Object[] 210 mov.null v2 211 - values: 212 - '.record panda.Object <external>' 213 - ', i32[] a1, i64 a2, panda.Object[] a3' 214 - | 215 # 216 movi v1, 123 217 newarr v1, v1, i32[] 218 movi.64 v2, 0x100000000 219 movi v3, 333 220 newarr v3, v3, panda.Object[] 221 - values: 222 - '.record panda.String <external>' 223 - ', i64[] a1, A a2, panda.String a3' 224 - | 225 # 226 movi v1, 123 227 newarr v1, v1, i64[] 228 initobj.short A.constructor 229 sta.obj v2 230 lda.str "some string" 231 sta.obj v3 232 - values: 233 - '.record panda.Object <external>' 234 - ',A[] a1, f64 a2, panda.Object a3' 235 - | 236 # 237 movi v1, 123 238 newarr v1, v1, A[] 239 fmovi.64 v2, 123.321 240 mov.null v3 241 - values: 242 - '.record panda.String <external>' 243 - ', f64[] a1, panda.String a2, panda.String[] a3' 244 - | 245 # 246 movi v1, 123 247 newarr v1, v1, f64[] 248 lda.str "some string" 249 sta.obj v2 250 movi v3, 123 251 newarr v3, v3, panda.String[] 252 - values: 253 - | 254 .record panda.String <external> 255 .record panda.Object <external> 256 - ', panda.String[] a1, panda.Object[] a2, panda.String[] a3' 257 - | 258 # 259 movi v1, 123 260 newarr v1, v1, panda.String[] 261 movi v2, 321 262 newarr v2, v2, panda.Object[] 263 movi v3, 333 264 newarr v3, v3, panda.String[] 265 - values: 266 - '.record panda.Object <external>' 267 - ', panda.Object[] a1, panda.Object a2, f64[] a3' 268 - | 269 # 270 movi v1, 123 271 newarr v1, v1, panda.Object[] 272 mov.null v2 273 movi v3, 321 274 newarr v3, v3, f64[] 275 276 - file-name: p_method_call_args 277 isa: 278 instructions: 279 - sig: call.virt.range method_id, v:in:top 280 acc: out:top 281 format: [op_v_8_id_16] 282 header-template: [xorshift32] 283 description: > 284 Invoke virtual method with different pseudo-random values and check if correct value is stored in object field. Check i32, i64, f64 and reference types. 285 Use PandaAssembly language context. 286 tags: ['tsan', 'irtoc_ignore'] 287 code-template: | 288 %s 289 290 .function void R.constructor(R a0) <ctor> { 291 return.void 292 } 293 294 .function void R.storeValue(R a0, %s) { 295 %s 296 return.void 297 } 298 299 .function i32 main() { 300 # Create R object 301 initobj.short R.constructor 302 # Keep them in v0 303 sta.obj v0 304 # Iterations 305 movi v2, 10 306 # Start value 307 movi v3, *s 308 loop: 309 %s 310 inci v2, -1 311 lda v2 312 jnez loop 313 ldai 0 314 return 315 exit_err: 316 ldai 1 317 return 318 319 check-type: none 320 321 template-cases: 322 - values: 323 - | 324 .record R { 325 i32 f1 326 i32 f2 327 i32 f3 328 } 329 - i32 a1, i32 a2, i32 a3 330 - | 331 # 332 lda a1 333 stobj a0, R.f1 334 lda a2 335 stobj a0, R.f2 336 lda a3 337 stobj a0, R.f3 338 - | 339 # Get next random number 340 call.short nextRand, v3 341 sta v5 342 call.short nextRand, v5 343 sta v6 344 call.short nextRand, v6 345 sta v7 346 sta v3 347 # Store in object 348 mov.obj v4, v0 349 call.virt.range R.storeValue, v4 350 # Check record R content 351 ldobj v0, R.f1 352 jne v5, exit_err 353 ldobj v0, R.f2 354 jne v6, exit_err 355 ldobj v0, R.f3 356 jne v7, exit_err 357 - values: 358 - | 359 .record R { 360 i32[] f1 361 i32 f2 362 i32[] f3 363 } 364 - i32[] a1, i32 a2, i32[] a3 365 - | 366 # 367 lda.obj a1 368 stobj.obj a0, R.f1 369 lda a2 370 stobj a0, R.f2 371 lda.obj a3 372 stobj.obj a0, R.f3 373 - | 374 # Get next random number 375 call.short nextRand, v3 376 sta v5 377 andi 0x7f 378 sta v6 379 newarr v6, v6, i32[] 380 call.short nextRand, v5 381 sta v7 382 call.short nextRand, v7 383 sta v8 384 andi 0x7f 385 sta v9 386 newarr v8, v9, i32[] 387 # Store in object 388 mov.obj v5, v0 389 call.virt.range R.storeValue, v5 390 # Check R content 391 ldobj.obj v0, R.f1 392 jne.obj v6, exit_err 393 ldobj v0, R.f2 394 jne v7, exit_err 395 ldobj.obj v0, R.f3 396 jne.obj v8, exit_err 397 - values: 398 - | 399 .record R { 400 i64[] f1 401 i32 f2 402 f64[] f3 403 } 404 - i64[] a1, i32 a2, f64[] a3 405 - | 406 # 407 lda.obj a1 408 stobj.obj a0, R.f1 409 lda a2 410 stobj a0, R.f2 411 lda.obj a3 412 stobj.obj a0, R.f3 413 - | 414 # Get next random number 415 call.short nextRand, v3 416 sta v5 417 andi 0x7f 418 sta v6 419 newarr v6, v6, i64[] 420 call.short nextRand, v5 421 sta v7 422 call.short nextRand, v7 423 sta v8 424 andi 0x7f 425 sta v9 426 newarr v8, v9, f64[] 427 mov.obj v5, v0 428 # Store in object 429 call.virt.range R.storeValue, v5 430 # Check R content 431 ldobj.obj v0, R.f1 432 jne.obj v6, exit_err 433 ldobj v0, R.f2 434 jne v7, exit_err 435 ldobj.obj v0, R.f3 436 jne.obj v8, exit_err 437 438 - values: 439 - | 440 .record R { 441 i64 f1 442 i32 f2 443 f64 f3 444 } 445 - i64 a1, i32 a2, f64 a3 446 - | 447 # 448 lda.64 a1 449 stobj.64 a0, R.f1 450 lda a2 451 stobj a0, R.f2 452 lda.64 a3 453 stobj.64 a0, R.f3 454 - | 455 # Get next random number 456 call.short nextRand, v3 457 sta v3 458 u32toi64 459 movi.64 v4, 32 460 shl2.64 v4 461 sta.64 v4 462 call.short nextRand, v3 463 sta v3 464 u32toi64 465 or2.64 v4 466 sta.64 v4 467 468 call.short nextRand, v3 469 sta v3 470 sta v5 471 call.short nextRand, v3 472 sta v3 473 u32toi64 474 movi.64 v6, 32 475 shl2.64 v6 476 sta.64 v6 477 call.short nextRand, v3 478 sta v3 479 u32toi64 480 or2.64 v6 481 i64tof64 482 sta.64 v6 483 mov.obj v7, v0 484 mov.64 v8, v4 485 mov v9, v5 486 mov.64 v10, v6 487 call.virt.range R.storeValue, v7 488 # Check R content 489 ldobj.64 v0, R.f1 490 cmp.64 v8 491 jnez exit_err 492 ldobj v0, R.f2 493 jne v9, exit_err 494 ldobj.64 v0, R.f3 495 fcmpg.64 v10 496 jnez exit_err 497 498 - values: 499 - | 500 .record R { 501 f64[] f1 502 R[] f2 503 R f3 504 } 505 - f64[] a1, R[] a2, R a3 506 - | 507 # 508 lda.obj a1 509 stobj.obj a0, R.f1 510 lda.obj a2 511 stobj.obj a0, R.f2 512 lda.obj a3 513 stobj.obj a0, R.f3 514 - | 515 # Get next random number 516 call.short nextRand, v3 517 sta v3 518 andi 0x7f 519 sta v4 520 newarr v4, v4, f64[] 521 call.short nextRand, v3 522 sta v3 523 andi 0x7f 524 sta v5 525 newarr v5, v5, R[] 526 mov.null v6 527 # Store in object 528 mov.obj v7, v0 529 mov.obj v8, v4 530 mov.obj v9, v5 531 mov.obj v10, v6 532 call.virt.range R.storeValue, v7 533 # Check R content 534 ldobj.obj v0, R.f1 535 jne.obj v8, exit_err 536 ldobj.obj v0, R.f2 537 jne.obj v9, exit_err 538 ldobj.obj v0, R.f3 539 jne.obj v10, exit_err 540 cases: 541 - values: 542 - "0xBADC0FFE" 543 - values: 544 - "0x12345678" 545 - values: 546 - "0xFEDCBA98" 547 - values: 548 - "1" 549 - values: 550 - "0xFFFFFFFF" 551 - values: 552 - "0x80000000" 553 - values: 554 - "0x7FFFFFFF" 555 556 - file-name: j_method_call_args 557 isa: 558 instructions: 559 - sig: call.virt.range method_id, v:in:top 560 acc: out:top 561 format: [op_v_8_id_16] 562 runner-options: [use-pa] 563 header-template: [PandaAssembly, xorshift32] 564 description: > 565 Invoke virtual method with different pseudo-random values and check if correct value is stored in object field. Check i32, i64, f64 and reference types. 566 Use PandaAssembly language context. 567 tags: ['tsan', 'irtoc_ignore'] 568 code-template: | 569 %s 570 571 .record S<panda.extends=R> {} 572 573 .function void R.constructor(R a0) <ctor> { 574 return.void 575 } 576 577 .function void S.constructor(S a0) <ctor> { 578 return.void 579 } 580 581 .function void R.storeValue(R a0, %s) <noimpl> 582 583 .function void S.storeValue(S a0, %s) { 584 %s 585 return.void 586 } 587 588 .function i32 main() { 589 # Create S object 590 initobj.short S.constructor 591 # Keep them in v0 592 sta.obj v0 593 # Iterations 594 movi v2, 10 595 # Start value 596 movi v3, *s 597 loop: 598 %s 599 inci v2, -1 600 lda v2 601 jnez loop 602 ldai 0 603 return 604 exit_err: 605 ldai 1 606 return 607 check-type: none 608 template-cases: 609 - values: 610 - | 611 .record R { 612 i32 f1 613 i32 f2 614 i32 f3 615 } 616 - i32 a1, i32 a2, i32 a3 617 - i32 a1, i32 a2, i32 a3 618 - | 619 # 620 lda a1 621 stobj a0, R.f1 622 lda a2 623 stobj a0, R.f2 624 lda a3 625 stobj a0, R.f3 626 - | 627 # Get next random number 628 call.short nextRand, v3 629 sta v4 630 call.short nextRand, v4 631 sta v5 632 call.short nextRand, v5 633 sta v6 634 sta v3 635 # Place values starting from v7 for call.virt.range 636 mov.obj v7, v0 637 mov v8, v4 638 mov v9, v5 639 mov v10, v6 640 # Store in object 641 call.virt.range %s.storeValue, v7 642 # Check record R content 643 ldobj v0, R.f1 644 jne v8, exit_err 645 ldobj v0, R.f2 646 jne v9, exit_err 647 ldobj v0, R.f3 648 jne v10, exit_err 649 - values: 650 - | 651 .record R { 652 i32[] f1 653 i32 f2 654 i32[] f3 655 } 656 - i32[] a1, i32 a2, i32[] a3 657 - i32[] a1, i32 a2, i32[] a3 658 - | 659 # 660 lda.obj a1 661 stobj.obj a0, R.f1 662 lda a2 663 stobj a0, R.f2 664 lda.obj a3 665 stobj.obj a0, R.f3 666 - | 667 # Get next random number 668 call.short nextRand, v3 669 sta v4 670 andi 0x7f 671 sta v5 672 newarr v5, v5, i32[] 673 call.short nextRand, v4 674 sta v6 675 call.short nextRand, v6 676 sta v7 677 andi 0x7f 678 sta v8 679 newarr v8, v8, i32[] 680 # Place values starting from v9 for call.virt.range 681 mov.obj v9, v0 682 mov.obj v10, v5 683 mov v11, v6 684 mov.obj v12, v8 685 # Store in object 686 call.virt.range %s.storeValue, v9 687 # Check R content 688 ldobj.obj v0, R.f1 689 jne.obj v10, exit_err 690 ldobj v0, R.f2 691 jne v11, exit_err 692 ldobj.obj v0, R.f3 693 jne.obj v12, exit_err 694 - values: 695 - | 696 .record R { 697 i64[] f1 698 i32 f2 699 f64[] f3 700 } 701 - i64[] a1, i32 a2, f64[] a3 702 - i64[] a1, i32 a2, f64[] a3 703 - | 704 # 705 lda.obj a1 706 stobj.obj a0, R.f1 707 lda a2 708 stobj a0, R.f2 709 lda.obj a3 710 stobj.obj a0, R.f3 711 - | 712 # Get next random number 713 call.short nextRand, v3 714 sta v4 715 andi 0x7f 716 sta v5 717 newarr v5, v5, i64[] 718 call.short nextRand, v4 719 sta v6 720 call.short nextRand, v6 721 sta v7 722 andi 0x7f 723 sta v8 724 newarr v8, v8, f64[] 725 # Place values starting from v9 for call.virt.range 726 mov.obj v9, v0 727 mov.obj v10, v5 728 mov v11, v6 729 mov.obj v12, v8 730 # Store in object 731 call.virt.range %s.storeValue, v9 732 # Check R content 733 ldobj.obj v0, R.f1 734 jne.obj v10, exit_err 735 ldobj v0, R.f2 736 jne v11, exit_err 737 ldobj.obj v0, R.f3 738 jne.obj v12, exit_err 739 - values: 740 - | 741 .record R { 742 i64 f1 743 i32 f2 744 f64 f3 745 } 746 - i64 a1, i32 a2, f64 a3 747 - i64 a1, i32 a2, f64 a3 748 - | 749 # 750 lda.64 a1 751 stobj.64 a0, R.f1 752 lda a2 753 stobj a0, R.f2 754 lda.64 a3 755 stobj.64 a0, R.f3 756 - | 757 # Get next random number 758 call.short nextRand, v3 759 sta v3 760 u32toi64 761 movi.64 v4, 32 762 shl2.64 v4 763 sta.64 v4 764 call.short nextRand, v3 765 sta v3 766 u32toi64 767 or2.64 v4 768 sta.64 v4 769 call.short nextRand, v3 770 sta v3 771 sta v5 772 call.short nextRand, v3 773 sta v3 774 u32toi64 775 movi.64 v6, 32 776 shl2.64 v6 777 sta.64 v6 778 call.short nextRand, v3 779 sta v3 780 u32toi64 781 or2.64 v6 782 i64tof64 783 sta.64 v6 784 # Place values starting from v7 for call.virt.range 785 mov.obj v7, v0 786 mov.64 v8, v4 787 mov v9, v5 788 mov.64 v10, v6 789 call.virt.range %s.storeValue, v7 790 # Check R content 791 ldobj.64 v0, R.f1 792 cmp.64 v8 793 jnez exit_err 794 ldobj v0, R.f2 795 jne v9, exit_err 796 ldobj.64 v0, R.f3 797 fcmpg.64 v10 798 jnez exit_err 799 - values: 800 - | 801 .record R { 802 f64[] f1 803 R[] f2 804 R f3 805 } 806 - f64[] a1, R[] a2, R a3 807 - f64[] a1, R[] a2, R a3 808 - | 809 # 810 lda.obj a1 811 stobj.obj a0, R.f1 812 lda.obj a2 813 stobj.obj a0, R.f2 814 lda.obj a3 815 stobj.obj a0, R.f3 816 - | 817 # Get next random number 818 call.short nextRand, v3 819 sta v3 820 andi 0x7f 821 sta v4 822 newarr v4, v4, f64[] 823 call.short nextRand, v3 824 sta v3 825 andi 0x7f 826 sta v5 827 newarr v5, v5, R[] 828 mov.null v6 829 # Place values starting from v7 for call.virt.range 830 mov.obj v7, v0 831 mov.obj v8, v4 832 mov.obj v9, v5 833 mov.obj v10, v6 834 # Store in object 835 call.virt.range %s.storeValue, v7 836 # Check R content 837 ldobj.obj v0, R.f1 838 jne.obj v8, exit_err 839 ldobj.obj v0, R.f2 840 jne.obj v9, exit_err 841 ldobj.obj v0, R.f3 842 jne.obj v10, exit_err 843 cases: 844 - values: 845 - "0xBADC0FFE" 846 - "R" 847 description: Call using parent object method. 848 - values: 849 - "0xBADC0FFE" 850 - "S" 851 description: Call using current object method. 852 - values: 853 - "0x12345678" 854 - "R" 855 description: Call using parent object method. 856 - values: 857 - "0x12345678" 858 - "S" 859 description: Call using current object method. 860 - values: 861 - "0xFEDCBA98" 862 - "R" 863 description: Call using parent object method. 864 - values: 865 - "0xFEDCBA98" 866 - "S" 867 description: Call using current object method. 868 - values: 869 - "1" 870 - "R" 871 description: Call using parent object method. 872 - values: 873 - "1" 874 - "S" 875 description: Call using current object method. 876 - values: 877 - "0xFFFFFFFF" 878 - "R" 879 description: Call using parent object method. 880 - values: 881 - "0xFFFFFFFF" 882 - "S" 883 description: Call using current object method. 884 - values: 885 - "0x80000000" 886 - "R" 887 description: Call using parent object method. 888 - values: 889 - "0x80000000" 890 - "S" 891 description: Call using current object method. 892 - values: 893 - "0x7FFFFFFF" 894 - "R" 895 description: Call using parent object method. 896 - values: 897 - "0x7FFFFFFF" 898 - "S" 899 description: Call using current object method. 900 901 - file-name: restore_register 902 isa: 903 instructions: 904 - sig: call.virt.range method_id, v:in:top 905 acc: out:top 906 format: [op_v_8_id_16] 907 header-template: [r_A] 908 description: > 909 Invoke virtual method and check if registers after calling is restored. 910 code-template: | 911 .function void A.foo(A a0) { 912 %s 913 lda.null 914 sta.obj v0 915 mov.obj v256, v0 916 return.void 917 } 918 919 .function i32 main() { 920 initobj.short A.constructor 921 sta.obj v0 922 %s 923 mov%s v256, %s 924 call.virt.range A.foo, v0 925 mov%s v100, v256 926 lda%s v100 927 %s 928 check-type: check-positive 929 cases: 930 - values: 931 - 'movi v1, 123' 932 - 'movi v1, 321' 933 - '' 934 - 'v1' 935 - '' 936 - '' 937 - | 938 # 939 jne v1, set_failure 940 ldai 0 941 jmp fall_through 942 set_failure: 943 ldai 1 944 fall_through: 945 - values: 946 - 'movi.64 v8, 123' 947 - 'movi v8, 321' 948 - '' 949 - 'v8' 950 - '' 951 - '' 952 - | 953 # 954 jne v8, set_failure 955 ldai 0 956 jmp fall_through 957 set_failure: 958 ldai 1 959 fall_through: 960 - values: 961 - 'fmovi.64 v16, 123' 962 - 'movi v16, 321' 963 - '' 964 - 'v16' 965 - '' 966 - '' 967 - | 968 # 969 jne v16, set_failure 970 ldai 0 971 jmp fall_through 972 set_failure: 973 ldai 1 974 fall_through: 975 - values: 976 - 'mov.null v128' 977 - 'movi v128, 321' 978 - '' 979 - 'v128' 980 - '' 981 - '' 982 - | 983 # 984 jne v128, set_failure 985 ldai 0 986 jmp fall_through 987 set_failure: 988 ldai 1 989 fall_through: 990 - values: 991 - | 992 # 993 lda.str "123" 994 sta.obj v255 995 - 'movi v255, 321' 996 - '' 997 - 'v255' 998 - '' 999 - '' 1000 - | 1001 # 1002 jne v255, set_failure 1003 ldai 0 1004 jmp fall_through 1005 set_failure: 1006 ldai 1 1007 fall_through: 1008 - values: ['movi v1, 123', 'movi.64 v1, 321', '.64', 'v1', '.64', '.64', 'cmp.64 v1'] 1009 - values: ['movi.64 v8, 123', 'movi.64 v8, 321', '.64', 'v8', '.64', '.64', 'cmp.64 v8'] 1010 - values: ['fmovi.64 v16, 123', 'movi.64 v16, 321', '.64', 'v16', '.64', '.64', 'cmp.64 v16'] 1011 - values: ['mov.null v128', 'movi.64 v128, 321', '.64', 'v128', '.64', '.64', 'cmp.64 v128'] 1012 - values: 1013 - | 1014 # 1015 lda.str "123" 1016 sta.obj v255 1017 - 'movi.64 v255, 321' 1018 - '.64' 1019 - 'v255' 1020 - '.64' 1021 - '.64' 1022 - 'cmp.64 v255' 1023 - values: ['movi v1, 123', 'fmovi.64 v1, 321', '.64', 'v1', '.64', '.64', 'fcmpg.64 v1'] 1024 - values: ['movi.64 v8, 123', 'fmovi.64 v8, 321', '.64', 'v8', '.64', '.64', 'fcmpg.64 v8'] 1025 - values: ['fmovi.64 v16, 123', 'fmovi.64 v16, 321', '.64', 'v16', '.64', '.64', 'fcmpg.64 v16'] 1026 - values: ['mov.null v128', 'fmovi.64 v128, 321', '.64', 'v128', '.64', '.64', 'fcmpg.64 v128'] 1027 - values: 1028 - | 1029 # 1030 lda.str "123" 1031 sta.obj v255 1032 - 'fmovi.64 v255, 321' 1033 - '.64' 1034 - 'v255' 1035 - '.64' 1036 - '.64' 1037 - 'fcmpg.64 v255' 1038 1039 - file-name: regs 1040 isa: 1041 instructions: 1042 - sig: call.virt.range method_id, v:in:top 1043 acc: out:top 1044 format: [op_v_8_id_16] 1045 header-template: [r_A] 1046 description: > 1047 Check available registers number and registers width. 1048 code-template: | 1049 .function void A.foo(A a0%s) { 1050 return.void 1051 } 1052 1053 .function i32 main() { 1054 call.virt.range A.foo, %s 1055 } 1056 check-type: empty 1057 runner-options: [compile-only] 1058 cases: 1059 - values: ['', 'v255'] 1060 - values: ['', 'v256'] 1061 runner-options: [compile-failure] 1062 - values: ['', '0'] 1063 runner-options: [compile-failure] 1064 - values: [',i32 a1', 'v255'] 1065 - values: [',i32 a1', 'v256'] 1066 runner-options: [compile-failure] 1067 - values: [',i32 a1', 'v0, 0'] 1068 runner-options: [compile-failure] 1069 - values: [',i32 a1', 'v256, v15'] 1070 runner-options: [compile-failure] 1071 - values: [',i32 a1', 'v256, 0'] 1072 runner-options: [compile-failure] 1073 - values: [',i32 a1', 'v255, 0'] 1074 runner-options: [compile-failure] 1075 - values: [',i32 a1', '0, 0'] 1076 runner-options: [compile-failure] 1077 - values: ['', 'v0, v255'] 1078 runner-options: [compile-failure] 1079 - values: ['', 'v0, v256'] 1080 runner-options: [compile-failure] 1081 - values: ['', 'v256, v255'] 1082 runner-options: [compile-failure] 1083 - values: ['', 'v256, v256'] 1084 runner-options: [compile-failure] 1085 - values: ['', 'v0, v0, v255'] 1086 runner-options: [compile-failure] 1087 - values: ['', 'v0, v0, v256'] 1088 runner-options: [compile-failure] 1089 1090 1091 - file-name: panda_npe 1092 isa: 1093 instructions: 1094 - sig: call.virt.range method_id, v:in:top 1095 acc: out:top 1096 format: [op_v_8_id_16] 1097 exceptions: 1098 - x_null 1099 header-template: [NPE] 1100 description: > 1101 Check incorrect usage of `call.virt.range` instruction. 1102 Null reference usage causes to panda.NullPointerException. Method_id points to virtual method of base class. Use PandaAssembly language context. 1103 tags: ['tsan', 'irtoc_ignore'] 1104 code-template: | 1105 %s 1106 .record B {} 1107 1108 .function void B.constructor(B a0) <ctor> { 1109 return.void 1110 } 1111 1112 .function i32 B.func(B a0%s) <noimpl> 1113 1114 .function i32 main() { 1115 mov.null v0 1116 %s 1117 begin: 1118 call.virt.range B.func, v0 1119 end: 1120 ldai 1 1121 return 1122 1123 catch_NPE: 1124 ldai 0 # Expected panda.NullPointerException 1125 return 1126 1127 catch_all: 1128 ldai 2 # Unexpected exception, test failed 1129 return 1130 1131 .catch panda.NullPointerException, begin, end, catch_NPE 1132 .catchall begin, end, catch_all 1133 1134 check-type: none 1135 cases: 1136 - values: 1137 - '' 1138 - '' 1139 - '' 1140 - values: 1141 - '' 1142 - ', i32 a1' 1143 - 'movi v1, 0' 1144 - values: 1145 - '' 1146 - ', i64 a1' 1147 - 'movi.64 v1, 0' 1148 - values: 1149 - '' 1150 - ', f64 a1' 1151 - 'fmovi.64 v1, 0' 1152 - values: 1153 - '' 1154 - ', B a1' 1155 - | 1156 initobj B.constructor 1157 sta.obj v1 1158 - values: 1159 - '.record panda.String <external>' 1160 - ', panda.String a1' 1161 - | 1162 lda.str "some string" 1163 sta.obj v1 1164 1165 - values: 1166 - '.record panda.Class <external>' 1167 - ', panda.Class a1' 1168 - | 1169 # 1170 lda.type B 1171 sta.obj v1 1172 - values: 1173 - '' 1174 - ', i32 a1, f64 a2, i64 a3' 1175 - | 1176 # 1177 movi v1, 1 1178 fmovi.64 v2, 123.456 1179 movi.64 v3, 0x100000000 1180 - values: 1181 - '' 1182 - ', i64 a1, i64[] a2, i64[] a3' 1183 - | 1184 # 1185 movi.64 v1, 1 1186 mov.null v2 1187 mov.null v3 1188 - values: 1189 - '' 1190 - ', f64[] a1, i64[] a2, i32[] a3' 1191 - | 1192 # 1193 mov.null v1 1194 mov.null v2 1195 mov.null v3 1196 1197 - file-name: PandaAssembly_npe 1198 isa: 1199 instructions: 1200 - sig: call.virt.range method_id, v:in:top 1201 acc: out:top 1202 format: [op_v_8_id_16] 1203 exceptions: 1204 - x_null 1205 header-template: [PandaAssembly, j_NPE] 1206 runner-options: [use-pa] 1207 description: > 1208 Check incorrect usage of `call.virt.range` instruction. 1209 Null reference usage causes to panda.NullPointerException. Method_id points to virtual method of base class. Use PandaAssembly language context. 1210 tags: ['tsan', 'irtoc_ignore'] 1211 template-cases: 1212 - values: 1213 - | 1214 *s 1215 .record B {} 1216 1217 .function void B.constructor(B a0) <ctor> { 1218 return.void 1219 } 1220 1221 .function i32 B.func(B a0%s) <noimpl> 1222 ##- %s This line will be removed 1223 - values: 1224 - | 1225 *s 1226 .record A {} 1227 .record B <panda.extends=A> {} 1228 1229 .function void B.constructor(B a0) <ctor> { 1230 return.void 1231 } 1232 1233 .function i32 B.func(B a0*s) <noimpl> 1234 .function i32 A.func(B a0*s) <noimpl> 1235 - values: 1236 - | 1237 *s 1238 .record A {} 1239 .record C <panda.extends=A> {} 1240 .record B <panda.extends=C> {} 1241 1242 .function void B.constructor(B a0) <ctor> { 1243 return.void 1244 } 1245 1246 .function i32 B.func(B a0*s) <noimpl> 1247 .function i32 A.func(B a0*s) <noimpl> 1248 code-template: | 1249 %s 1250 1251 .function i32 main() { 1252 mov.null v0 1253 *s 1254 begin: 1255 call.virt.range B.func, v0 1256 end: 1257 ldai 1 1258 return 1259 1260 catch_NPE: 1261 ldai 0 # Expected panda.NullPointerException 1262 return 1263 1264 catch_all: 1265 ldai 2 # Unexpected exception, test failed 1266 return 1267 1268 .catch panda.NullPointerException, begin, end, catch_NPE 1269 .catchall begin, end, catch_all 1270 1271 check-type: none 1272 cases: 1273 - values: 1274 - '' 1275 - '' 1276 - '' 1277 - '' 1278 - '' 1279 - values: 1280 - '' 1281 - ', i32 a1' 1282 - ', i32 a1' 1283 - 'movi v1, 0' 1284 - values: 1285 - '' 1286 - ', i64 a1' 1287 - ', i64 a1' 1288 - 'movi.64 v1, 0' 1289 - values: 1290 - '' 1291 - ', f64 a1' 1292 - ', f64 a1' 1293 - 'fmovi.64 v1, 0' 1294 - values: 1295 - '' 1296 - ', B a1' 1297 - ', B a1' 1298 - | 1299 initobj B.constructor 1300 sta.obj v1 1301 - values: 1302 - '.record panda.String <external>' 1303 - ', panda.String a1' 1304 - ', panda.String a1' 1305 - | 1306 lda.str "some string" 1307 sta.obj v1 1308 - values: 1309 - '.record panda.Object <external>' 1310 - ', panda.Object a1' 1311 - ', panda.Object a1' 1312 - | 1313 # 1314 lda.type B 1315 sta.obj v1 1316 - values: 1317 - '' 1318 - ', i32 a1, f64 a2, i64 a3' 1319 - ', i32 a1, f64 a2, i64 a3' 1320 - | 1321 # 1322 movi v1, 1 1323 fmovi.64 v2, 123.456 1324 movi.64 v3, 0x100000000 1325 - values: 1326 - '' 1327 - ', i64 a1, i64[] a2, i64[] a3' 1328 - ', i64 a1, i64[] a2, i64[] a3' 1329 - | 1330 # 1331 movi.64 v1, 1 1332 mov.null v2 1333 mov.null v3 1334 - values: 1335 - '' 1336 - ', f64[] a1, i64[] a2, i32[] a3' 1337 - ', f64[] a1, i64[] a2, i32[] a3' 1338 - | 1339 # 1340 mov.null v1 1341 mov.null v2 1342 mov.null v3 1343 1344 - file-name: panda_ame 1345 isa: 1346 instructions: 1347 - sig: call.virt.range method_id, v:in:top 1348 acc: out:top 1349 format: [op_v_8_id_16] 1350 exceptions: 1351 - x_abstract 1352 header-template: [AME] 1353 description: > 1354 Check incorrect usage of `call.virt.range` instruction. Call of abstract method, check if panda.AbstractMethodError is thrown. 1355 Use PandaAssembly language context. 1356 tags: ['tsan', 'irtoc_ignore'] 1357 code-template: | 1358 %s 1359 .record B {} 1360 1361 .function void B.constructor(B a0) <ctor> { 1362 return.void 1363 } 1364 1365 .function i32 B.func(B a0%s) <noimpl> 1366 1367 .function i32 main() { 1368 initobj.short B.constructor 1369 sta.obj v0 1370 %s 1371 begin: 1372 call.virt.range B.func, v0 1373 end: 1374 ldai 1 1375 return 1376 1377 catch_AME: 1378 ldai 0 # Expected panda.AbstractMethodError 1379 return 1380 1381 catch_all: 1382 ldai 2 # Unexpected exception, test failed 1383 return 1384 1385 .catch panda.AbstractMethodError, begin, end, catch_AME 1386 .catchall begin, end, catch_all 1387 1388 check-type: none 1389 cases: 1390 - values: 1391 - '' 1392 - '' 1393 - '' 1394 - values: 1395 - '' 1396 - ', i32 a1' 1397 - 'movi v1, 0' 1398 - values: 1399 - '' 1400 - ', i64 a1' 1401 - 'movi.64 v1, 0' 1402 - values: 1403 - '' 1404 - ', f64 a1' 1405 - 'fmovi.64 v1, 0' 1406 - values: 1407 - '' 1408 - ', B a1' 1409 - | 1410 initobj.short B.constructor 1411 sta.obj v1 1412 - values: 1413 - '.record panda.String <external>' 1414 - ', panda.String a1' 1415 - | 1416 lda.str "some string" 1417 sta.obj v1 1418 - values: 1419 - '' 1420 - ', panda.Class a1' 1421 - | 1422 # 1423 lda.type B 1424 sta.obj v1 1425 - values: 1426 - '' 1427 - ', i32 a1, f64 a2, i64 a3' 1428 - | 1429 # 1430 movi v1, 1 1431 fmovi.64 v2, 123.456 1432 movi.64 v3, 0x100000000 1433 - values: 1434 - '' 1435 - ', i64 a1, i64[] a2, i64[] a3' 1436 - | 1437 # 1438 movi.64 v1, 1 1439 mov.null v2 1440 mov.null v3 1441 - values: 1442 - '' 1443 - ', f64[] a1, i64[] a2, i32[] a3' 1444 - | 1445 # 1446 mov.null v1 1447 mov.null v2 1448 mov.null v3 1449 1450 - file-name: PandaAssembly_ame 1451 isa: 1452 instructions: 1453 - sig: call.virt.range method_id, v:in:top 1454 acc: out:top 1455 format: [op_v_8_id_16] 1456 exceptions: 1457 - x_abstract 1458 header-template: [PandaAssembly, j_AME] 1459 description: > 1460 Check incorrect usage of `call.virt.range` instruction. Call of abstract method, check if panda.AbstractMethodError is thrown. 1461 Use PandaAssembly language context. 1462 tags: ['tsan', 'irtoc_ignore'] 1463 runner-options: [use-pa] 1464 template-cases: 1465 - values: 1466 - | 1467 *s 1468 .record B {} 1469 1470 .function void B.constructor(B a0) <ctor> { 1471 return.void 1472 } 1473 1474 .function i32 B.func(B a0*s) <noimpl> 1475 - values: 1476 - | 1477 *s 1478 .record A {} 1479 .record B <panda.extends=A> {} 1480 1481 .function void B.constructor(B a0) <ctor> { 1482 return.void 1483 } 1484 1485 .function i32 B.func(B a0*s) <noimpl> 1486 - values: 1487 - | 1488 *s 1489 .record A {} 1490 .record C <panda.extends=A> {} 1491 .record B <panda.extends=C> {} 1492 1493 .function void B.constructor(B a0) <ctor> { 1494 return.void 1495 } 1496 1497 .function i32 B.func(B a0*s) <noimpl> 1498 1499 code-template: | 1500 %s 1501 1502 .function i32 main() { 1503 initobj.short B.constructor 1504 sta.obj v0 1505 *s 1506 begin: 1507 call.virt.range B.func, v0 1508 end: 1509 ldai 1 1510 return 1511 1512 catch_AME: 1513 ldai 0 # Expected panda.AbstractMethodError 1514 return 1515 1516 catch_all: 1517 ldai 2 # Unexpected exception, test failed 1518 return 1519 1520 .catch panda.AbstractMethodError, begin, end, catch_AME 1521 .catchall begin, end, catch_all 1522 1523 check-type: none 1524 cases: 1525 - values: 1526 - '' 1527 - '' 1528 - '' 1529 - values: 1530 - '' 1531 - ', i32 a1' 1532 - 'movi v1, 0' 1533 - values: 1534 - '' 1535 - ', i64 a1' 1536 - 'movi.64 v1, 0' 1537 - values: 1538 - '' 1539 - ', f64 a1' 1540 - 'fmovi.64 v1, 0' 1541 - values: 1542 - '' 1543 - ', B a1' 1544 - | 1545 initobj.short B.constructor 1546 sta.obj v1 1547 - values: 1548 - '.record panda.String <external>' 1549 - ', panda.String a1' 1550 - | 1551 lda.str "some string" 1552 sta.obj v1 1553 - values: 1554 - '' 1555 - ', panda.Class a1' 1556 - | 1557 # 1558 lda.type B 1559 sta.obj v1 1560 - values: 1561 - '' 1562 - ', i32 a1, f64 a2, i64 a3' 1563 - | 1564 # 1565 movi v1, 1 1566 fmovi.64 v2, 123.456 1567 movi.64 v3, 0x100000000 1568 - values: 1569 - '' 1570 - ', i64 a1, i64[] a2, i64[] a3' 1571 - | 1572 # 1573 movi.64 v1, 1 1574 mov.null v2 1575 mov.null v3 1576 - values: 1577 - '' 1578 - ', f64[] a1, i64[] a2, i32[] a3' 1579 - | 1580 # 1581 mov.null v1 1582 mov.null v2 1583 mov.null v3 1584