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