1# Copyright (c) 2021 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: java 16 template: > 17 .language Java 18 - name: r_A 19 template: | 20 .record A {} 21 22 .function void A.constructor(A a0) <ctor> { 23 return.void 24 } 25 - name: r_R 26 template: | 27 # Record to test 28 .record R { 29 i32 fi32 30 i64 fi64 31 f64 ff64 32 panda.String[] fstr 33 panda.Object[] faPO 34 i32[] fai32 35 i64[] fai64 36 f64[] faf64 37 } 38 - name: r_RJ 39 template: | 40 # Record to test 41 .record R { 42 i32 fi32 43 i64 fi64 44 f64 ff64 45 java.lang.String[] fstr 46 java.lang.Object[] faPO 47 i32[] fai32 48 i64[] fai64 49 f64[] faf64 50 } 51 - name: NPE 52 template: | 53 .record panda.NullPointerException <external> 54 - name: j_NPE 55 template: | 56 .record java.lang.NullPointerException <external> 57 - name: AME 58 template: | 59 .record panda.AbstractMethodError <external> 60 .record panda.Class <external> 61 - name: j_AME 62 template: | 63 .record java.lang.AbstractMethodError <external> 64 .record java.lang.Class <external> 65tests: 66 - file-name: call.virt.short 67 isa: 68 instructions: 69 - sig: call.virt.short method_id, v1:in:top, v2:in:top 70 acc: out:top 71 format: [op_v1_4_v2_4_id_16] 72 title: Object calls 73 description: > 74 Call indicated object method, i.e. create new frame, pass values of arguments and 75 continue execution from the first instruction of a method. 76 Callee should treat accumulator value as undefined and cannot use it until accumulator 77 definition in the new frame. 78 Result (if any) is returned in accumulator (see 'Calling sequence' chapter for more details). 79 Method, its class and the number of argument is resolved by given method_id in runtime 80 constant-pool based on object reference using language-specific semantics (currently only Java 81 virtual methods are supported, further extensions are TBD). 82 Object reference is passed in the first source register, arguments are passed starting from 83 the second source register in the same order as in method signature. 84 Non-range instructions can be used to pass up to 4 arguments (including object reference). 85 Unused register slot values will be discarded and corresponding registers will not be 86 passed to the callee). 87 For methods with more arguments range kinds of instruction are to be used, which takes 88 the needed number of arguments starting from 'vs' register (including object reference). 89 verification: 90 - method_id_non_static 91 - compatible_arguments 92 - method_id_accessible 93 exceptions: 94 - x_null 95 - x_abstract 96 commands: 97 - file-name: method_call 98 isa: 99 instructions: 100 - sig: call.virt.short method_id, v1:in:top, v2:in:top 101 acc: out:top 102 format: [op_v1_4_v2_4_id_16] 103 header-template: [r_A] 104 description: > 105 Invoke virtual method with different amount (0 or 1) and type of argument. Primitives and reference types are used as second argument. 106 Check return value. 107 tags: ['tsan'] 108 code-template: | 109 *s 110 .function %s A.foo(A a0*s) { 111 %s 112 } 113 114 .function i32 main() { 115 initobj.short A.constructor 116 sta.obj v0 117 *s 118 call.virt.short A.foo, v0*s 119 %s 120 template-cases: 121 - values: 122 - i32 123 - | 124 # 125 ldai 123456789 126 return 127 - | 128 # 129 movi v0, 123456789 130 jne v0, exit_failure 131 ldai 0 132 return 133 exit_failure: 134 ldai 1 135 return 136 - values: 137 - i64 138 - | 139 # 140 ldai.64 123456789 141 return.64 142 - | 143 # 144 movi.64 v0, 123456789 145 cmp.64 v0 146 jnez exit_failure 147 ldai 0 148 return 149 exit_failure: 150 ldai 1 151 return 152 - values: 153 - f64 154 - | 155 # 156 fldai.64 1234567.89 157 return.64 158 - | 159 # 160 fmovi.64 v0, 1234567.89 161 fcmpg.64 v0 162 jnez exit_failure 163 ldai 0 164 return 165 exit_failure: 166 ldai 1 167 return 168 check-type: none 169 cases: 170 - values: 171 - '' 172 - '' 173 - '' 174 - '' 175 - values: 176 - '' 177 - ',i32 a1' 178 - 'movi v1, 123' 179 - ', v1' 180 - values: 181 - '' 182 - ',i32[] a1' 183 - | 184 # 185 movi v1, 123 186 newarr v1, v1, i32[] 187 - ', v1' 188 - values: 189 - '' 190 - ',i64 a1' 191 - 'movi.64 v1, 123' 192 - ', v1' 193 - values: 194 - '' 195 - ',i64[] a1' 196 - | 197 # 198 movi v1, 123 199 newarr v1, v1, i64[] 200 - ', v1' 201 - values: 202 - '' 203 - ',A a1' 204 - | 205 # 206 initobj.short A.constructor 207 sta.obj v1 208 - ', v1' 209 - values: 210 - '' 211 - ',A[] a1' 212 - | 213 # 214 movi v1, 123 215 newarr v1, v1, A[] 216 - ', v1' 217 218 - values: 219 - '' 220 - ',f64 a1' 221 - 'fmovi.64 v1, 123.321' 222 - ', v1' 223 - values: 224 - '' 225 - ',f64[] a1' 226 - | 227 # 228 movi v1, 123 229 newarr v1, v1, f64[] 230 - ', v1' 231 - values: 232 - '.record panda.String <external>' 233 - ',panda.String a1' 234 - | 235 # 236 lda.str "some string" 237 sta.obj v1 238 - ', v1' 239 - values: 240 - '.record panda.String <external>' 241 - ',panda.String[] a1' 242 - | 243 # 244 movi v1, 123 245 newarr v1, v1, panda.String[] 246 - ', v1' 247 248 - values: 249 - '.record panda.Object <external>' 250 - ',panda.Object[] a1' 251 - | 252 # 253 movi v1, 123 254 newarr v1, v1, panda.Object[] 255 - ', v1' 256 - values: 257 - '.record panda.Object <external>' 258 - ',panda.Object[] a1' 259 - 'mov.null v1' 260 - ', v1' 261 262 - values: 263 - '.record panda.Object <external>' 264 - ',panda.Object a1' 265 - | 266 # 267 mov.null v1 268 - ', v1' 269 270 - file-name: p_method_call_args 271 isa: 272 instructions: 273 - sig: call.virt.short method_id, v1:in:top, v2:in:top 274 acc: out:top 275 format: [op_v1_4_v2_4_id_16] 276 header-template: [xorshift32, r_R] 277 description: > 278 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. 279 Use PandaAssembly language context. 280 tags: ['tsan'] 281 code-template: | 282 .record panda.String <external> 283 .record panda.Object <external> 284 285 .function void R.constructor(R a0) <ctor> { 286 return.void 287 } 288 289 .function void R.storeValue(R a0, %s a1) { 290 lda%s a1 291 stobj%s a0, R.%s 292 return.void 293 } 294 295 .function i32 main() { 296 # Create R object 297 initobj.short R.constructor 298 # Keep them in v0 299 sta.obj v0 300 # Iterations 301 movi v2, 10 302 # Start value 303 movi v3, *s 304 305 loop: 306 %s 307 inci v2, -1 308 lda v2 309 jnez loop 310 ldai 0 311 return 312 exit_err: 313 ldai 1 314 return 315 check-type: none 316 template-cases: 317 - values: 318 - i32 319 - '' 320 - '' 321 - fi32 322 - | 323 # Get next random number 324 call.short nextRand, v3 325 sta v3 326 # Store in object 327 call.virt.short R.storeValue, v0, v3 328 # Get object field 329 ldobj v0, R.fi32 330 # Compare field value 331 jne v3, exit_err 332 - values: 333 - i32[] 334 - '.obj' 335 - '.obj' 336 - fai32 337 - | 338 # Get next random number 339 call.short nextRand, v3 340 sta v3 341 andi 0x7f 342 sta v4 343 newarr v4, v4, i32[] 344 # Store in object 345 call.virt.short R.storeValue, v0, v4 346 # Get object field 347 ldobj.obj v0, R.fai32 348 # Compare field value 349 jne.obj v4, exit_err 350 - values: 351 - i64 352 - '.64' 353 - '.64' 354 - fi64 355 - | 356 # Get next random number 357 call.short nextRand, v3 358 sta v3 359 # Convert to i64 to get high 32 bits 360 u32toi64 361 movi.64 v5, 32 362 shl2.64 v5 363 sta.64 v5 364 # Get next random 365 call.short nextRand, v3 366 sta v3 367 # Convert to i64 to get lowest 32 bits 368 u32toi64 369 or2.64 v5 370 sta.64 v4 371 # Store in object 372 call.virt.short R.storeValue, v0, v4 373 # Get object field value 374 ldobj.64 v0, R.fi64 375 # Compare field value 376 cmp.64 v4 377 jnez exit_err 378 - values: 379 - i64[] 380 - '.obj' 381 - '.obj' 382 - fai64 383 - | 384 # Get next random number 385 call.short nextRand, v3 386 sta v3 387 andi 0xff 388 sta v4 389 newarr v4, v4, i64[] 390 # Store in object 391 call.virt.short R.storeValue, v0, v4 392 # Get object field 393 ldobj.obj v0, R.fai64 394 # Compare field value 395 jne.obj v4, exit_err 396 - values: 397 - f64 398 - '.64' 399 - '.64' 400 - ff64 401 - | 402 # 403 call.short nextRand, v3 404 sta v3 405 u32toi64 406 movi.64 v5, 32 407 shl2.64 v5 408 sta.64 v5 409 call.short nextRand, v3 410 sta v3 411 u32toi64 412 or2.64 v5 413 sta.64 v4 414 lda.64 v4 415 # Conver i64 to f64 to check f64 value passed to virtual function. 416 i64tof64 417 sta.64 v4 418 call.virt.short R.storeValue, v0, v4 419 ldobj.64 v0, R.ff64 420 fcmpg.64 v4 421 jnez exit_err 422 - values: 423 - f64[] 424 - '.obj' 425 - '.obj' 426 - faf64 427 - | 428 # Get next random number 429 call.short nextRand, v3 430 sta v3 431 andi 0xff 432 sta v4 433 newarr v4, v4, f64[] 434 # Store in object 435 call.virt.short R.storeValue, v0, v4 436 # Get object field 437 ldobj.obj v0, R.faf64 438 # Compare field value 439 jne.obj v4, exit_err 440 - values: 441 - panda.Object[] 442 - '.obj' 443 - '.obj' 444 - faPO 445 - | 446 # Get next random number 447 call.short nextRand, v3 448 sta v3 449 andi 0x7f 450 sta v4 451 newarr v4, v4, panda.Object[] 452 # Store in object 453 call.virt.short R.storeValue, v0, v4 454 # Get object field 455 ldobj.obj v0, R.faPO 456 # Compare field value 457 jne.obj v4, exit_err 458 - values: 459 - panda.String[] 460 - '.obj' 461 - '.obj' 462 - fstr 463 - | 464 # Get next random number 465 call.short nextRand, v3 466 sta v3 467 andi 0x7f 468 sta v4 469 newarr v4, v4, panda.String[] 470 # Store in object 471 472 call.virt.short R.storeValue, v0, v4 473 # Get object field 474 ldobj.obj v0, R.fstr 475 # Compare field value 476 jne.obj v4, exit_err 477 cases: 478 - values: 479 - "0xBADC0FFE" 480 - values: 481 - "0x12345678" 482 - values: 483 - "0xFEDCBA98" 484 - values: 485 - "1" 486 - values: 487 - "0xFFFFFFFF" 488 - values: 489 - "0x80000000" 490 - values: 491 - "0x7FFFFFFF" 492 493 - file-name: restore_register 494 isa: 495 instructions: 496 - sig: call.virt.short method_id, v1:in:top, v2:in:top 497 acc: out:top 498 format: [op_v1_4_v2_4_id_16] 499 header-template: [r_A] 500 description: > 501 Invoke virtual method and check if registers after calling is restored. 502 code-template: | 503 .function void A.foo(A a0) { 504 %s 505 lda.null 506 sta.obj v0 507 mov.obj v256, v0 508 return.void 509 } 510 511 .function i32 main() { 512 initobj.short A.constructor 513 sta.obj v0 514 %s 515 mov%s v256, %s 516 call.virt.short A.foo, v0 517 mov%s v100, v256 518 lda%s v100 519 %s 520 cases: 521 - values: 522 - 'movi v1, 123' 523 - 'movi v1, 321' 524 - '' 525 - 'v1' 526 - '' 527 - '' 528 - | 529 # 530 jne v1, set_failure 531 ldai 0 532 jmp done 533 set_failure: 534 ldai 1 535 done: 536 - values: 537 - 'movi.64 v8, 123' 538 - 'movi v8, 321' 539 - '' 540 - 'v8' 541 - '' 542 - '' 543 - | 544 # 545 jne v8, set_failure 546 ldai 0 547 jmp done 548 set_failure: 549 ldai 1 550 done: 551 - values: 552 - 'fmovi.64 v16, 123' 553 - 'movi v16, 321' 554 - '' 555 - 'v16' 556 - '' 557 - '' 558 - | 559 # 560 jne v16, set_failure 561 ldai 0 562 jmp done 563 set_failure: 564 ldai 1 565 done: 566 - values: 567 - 'mov.null v128' 568 - 'movi v128, 321' 569 - '' 570 - 'v128' 571 - '' 572 - '' 573 - | 574 # 575 jne v128, set_failure 576 ldai 0 577 jmp done 578 set_failure: 579 ldai 1 580 done: 581 - values: 582 - | 583 # 584 lda.str "123" 585 sta.obj v255 586 - 'movi v255, 321' 587 - '' 588 - 'v255' 589 - '' 590 - '' 591 - | 592 # 593 jne v255, set_failure 594 ldai 0 595 jmp done 596 set_failure: 597 ldai 1 598 done: 599 - values: ['movi v1, 123', 'movi.64 v1, 321', '.64', 'v1', '.64', '.64', 'cmp.64 v1'] 600 - values: ['movi.64 v8, 123', 'movi.64 v8, 321', '.64', 'v8', '.64', '.64', 'cmp.64 v8'] 601 - values: ['fmovi.64 v16, 123', 'movi.64 v16, 321', '.64', 'v16', '.64', '.64', 'cmp.64 v16'] 602 - values: ['mov.null v128', 'movi.64 v128, 321', '.64', 'v128', '.64', '.64', 'cmp.64 v128'] 603 - values: 604 - | 605 # 606 lda.str "123" 607 sta.obj v255 608 - 'movi.64 v255, 321' 609 - '.64' 610 - 'v255' 611 - '.64' 612 - '.64' 613 - 'cmp.64 v255' 614 - values: ['movi v1, 123', 'fmovi.64 v1, 321', '.64', 'v1', '.64', '.64', 'fcmpg.64 v1'] 615 - values: ['movi.64 v8, 123', 'fmovi.64 v8, 321', '.64', 'v8', '.64', '.64', 'fcmpg.64 v8'] 616 - values: ['fmovi.64 v16, 123', 'fmovi.64 v16, 321', '.64', 'v16', '.64', '.64', 'fcmpg.64 v16'] 617 - values: ['mov.null v128', 'fmovi.64 v128, 321', '.64', 'v128', '.64', '.64', 'fcmpg.64 v128'] 618 - values: 619 - | 620 # 621 lda.str "123" 622 sta.obj v255 623 - 'fmovi.64 v255, 321' 624 - '.64' 625 - 'v255' 626 - '.64' 627 - '.64' 628 - 'fcmpg.64 v255' 629 630 - file-name: regs 631 isa: 632 instructions: 633 - sig: call.virt.short method_id, v1:in:top, v2:in:top 634 acc: out:top 635 format: [op_v1_4_v2_4_id_16] 636 header-template: [r_A] 637 description: > 638 Check available registers number and registers width. 639 code-template: | 640 .function void A.foo(A a0%s) { 641 return.void 642 } 643 644 .function i32 main() { 645 call.virt.short A.foo, %s 646 } 647 check-type: empty 648 runner-options: [compile-only] 649 cases: 650 - values: ['', 'v0'] 651 - values: ['', 'v8'] 652 - values: ['', 'v15'] 653 - values: ['', 'v16'] 654 runner-options: [compile-failure] 655 - values: ['', '0'] 656 runner-options: [compile-failure] 657 - values: [',i32 a1', 'v0, v0'] 658 - values: [',i32 a1', 'v0, v8'] 659 - values: [',i32 a1', 'v0, v15'] 660 - values: [',i32 a1', 'v0, v16'] 661 runner-options: [compile-failure] 662 - values: [',i32 a1', 'v0, 0'] 663 runner-options: [compile-failure] 664 - values: [',i32 a1', 'v16, v0'] 665 runner-options: [compile-failure] 666 - values: [',i32 a1', 'v16, v8'] 667 runner-options: [compile-failure] 668 - values: [',i32 a1', 'v16, v15'] 669 runner-options: [compile-failure] 670 - values: [',i32 a1', 'v16, v16'] 671 runner-options: [compile-failure] 672 - values: [',i32 a1', 'v16, 0'] 673 runner-options: [compile-failure] 674 - values: [',i32 a1', 'v15, v15'] 675 - values: [',i32 a1', 'v15, v16'] 676 runner-options: [compile-failure] 677 - values: [',i32 a1', 'v15, 0'] 678 runner-options: [compile-failure] 679 - values: [',i32 a1', '0, 0'] 680 runner-options: [compile-failure] 681 - values: [',i32 a1, i32 a2', 'v0, v0, v0'] 682 runner-options: [compile-failure] 683 - values: [',i32 a1, i32 a2', 'v0, v0, v15'] 684 runner-options: [compile-failure] 685 - values: [',i32 a1, i32 a2', 'v0, v15, v16'] 686 runner-options: [compile-failure] 687 - values: [',i32 a1, i32 a2', 'v15, v16, v16'] 688 runner-options: [compile-failure] 689 - values: [',i32 a1, i32 a2', 'v16, v16, 0'] 690 runner-options: [compile-failure] 691 - values: [',i32 a1, i32 a2', 'v16, 0, 0'] 692 runner-options: [compile-failure] 693 - values: [',i32 a1, i32 a2', '0, 0, 0'] 694 runner-options: [compile-failure] 695 696 - file-name: panda_npe 697 isa: 698 instructions: 699 - sig: call.virt.short method_id, v1:in:top, v2:in:top 700 acc: out:top 701 format: [op_v1_4_v2_4_id_16] 702 exceptions: 703 - x_null 704 header-template: [NPE] 705 description: > 706 Check incorrect usage of `call.virt.short` instruction. 707 Null reference usage causes to panda.NullPointerException. Method_id points to virtual method of base class. Use PandaAssembly language context. 708 code-template: | 709 %s 710 .record B {} 711 712 .function void B.constructor(B a0) <ctor> { 713 return.void 714 } 715 716 .function i32 B.func(B a0%s) <noimpl> 717 718 .function i32 main() { 719 mov.null v0 720 %s 721 begin: 722 call.virt.short B.func, v0%s 723 end: 724 ldai 1 725 return 726 727 catch_NPE: 728 ldai 0 # Expected panda.NullPointerException 729 return 730 731 catch_all: 732 ldai 2 # Unexpected exception, test failed 733 return 734 735 .catch panda.NullPointerException, begin, end, catch_NPE 736 .catchall begin, end, catch_all 737 738 check-type: none 739 cases: 740 - values: 741 - '' 742 - '' 743 - '' 744 - '' 745 - values: 746 - '' 747 - ', i32 a1' 748 - 'movi v1, 0' 749 - ', v1' 750 - values: 751 - '' 752 - ', i64 a1' 753 - 'movi.64 v1, 0' 754 - ', v1' 755 - values: 756 - '' 757 - ', f64 a1' 758 - 'fmovi.64 v1, 0' 759 - ', v1' 760 - values: 761 - '' 762 - ', B a1' 763 - | 764 initobj B.constructor 765 sta.obj v1 766 - ', v1' 767 - values: 768 - '.record panda.String <external>' 769 - ', panda.String a1' 770 - | 771 lda.str "some string" 772 sta.obj v1 773 - ', v1' 774 775 - values: 776 - '.record panda.Class <external>' 777 - ', panda.Class a1' 778 - | 779 # 780 lda.type B 781 sta.obj v1 782 - ', v1' 783 784 - file-name: panda_ame 785 isa: 786 instructions: 787 - sig: call.virt.short method_id, v1:in:top, v2:in:top 788 acc: out:top 789 format: [op_v1_4_v2_4_id_16] 790 exceptions: 791 - x_abstract 792 header-template: [AME] 793 description: > 794 Check incorrect usage of `call.virt.short` instruction. Call of abstract method, check if panda.AbstractMethodError is thrown. 795 Use PandaAssembly language context. 796 tags: ['tsan'] 797 code-template: | 798 %s 799 .record B {} 800 801 .function void B.constructor(B a0) <ctor> { 802 return.void 803 } 804 805 .function i32 B.func(B a0%s) <noimpl> 806 807 .function i32 main() { 808 initobj.short B.constructor 809 sta.obj v0 810 %s 811 begin: 812 call.virt.short B.func, v0%s 813 end: 814 ldai 1 815 return 816 817 catch_AME: 818 ldai 0 # Expected panda.AbstractMethodError 819 return 820 821 catch_all: 822 ldai 2 # Unexpected exception, test failed 823 return 824 825 .catch panda.AbstractMethodError, begin, end, catch_AME 826 .catchall begin, end, catch_all 827 828 check-type: none 829 cases: 830 - values: 831 - '' 832 - '' 833 - '' 834 - '' 835 - values: 836 - '' 837 - ', i32 a1' 838 - 'movi v1, 0' 839 - ', v1' 840 - values: 841 - '' 842 - ', i64 a1' 843 - 'movi.64 v1, 0' 844 - ', v1' 845 - values: 846 - '' 847 - ', f64 a1' 848 - 'fmovi.64 v1, 0' 849 - ', v1' 850 - values: 851 - '' 852 - ', B a1' 853 - | 854 initobj.short B.constructor 855 sta.obj v1 856 - ', v1' 857 - values: 858 - '.record panda.String <external>' 859 - ', panda.String a1' 860 - | 861 lda.str "some string" 862 sta.obj v1 863 - ', v1' 864 865 - values: 866 - '' 867 - ', panda.Class a1' 868 - | 869 # 870 lda.type B 871 sta.obj v1 872 - ', v1' 873 874 - file-name: unused_regs 875 isa: 876 description: > 877 Unused register slot values will be discarded and corresponding registers will not be 878 passed to the callee). 879 header-template: [] 880 description: Verifier should ignore unused register slots. 881 code-template: | 882 .record A {} 883 .function void A.ctor(A a0) <ctor> { 884 return.void 885 } 886 .function i32 A.foo(A a0) { 887 ldai 0 888 return 889 } 890 .function i32 main() { 891 initobj A.ctor 892 sta.obj v5 893 call.virt.short A.foo, v5, v4 894 check-type: no-check 895