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_B 26 template: | 27 .record B {} 28 29 .function void B.constructor(B a0) <ctor> { 30 return.void 31 } 32tests: 33 - file-name: call.virt.short.negative 34 isa: 35 instructions: 36 - sig: call.virt.short method_id, v1:in:top, v2:in:top 37 acc: out:top 38 format: [op_v1_4_v2_4_id_16] 39 title: Object calls 40 description: > 41 Call indicated object method, i.e. create new frame, pass values of arguments and 42 continue execution from the first instruction of a method. 43 Callee should treat accumulator value as undefined and cannot use it until accumulator 44 definition in the new frame. 45 Result (if any) is returned in accumulator (see 'Calling sequence' chapter for more details). 46 Method, its class and the number of argument is resolved by given method_id in runtime 47 constant-pool based on object reference using language-specific semantics (currently only Java 48 virtual methods are supported, further extensions are TBD). 49 Object reference is passed in the first source register, arguments are passed starting from 50 the second source register in the same order as in method signature. 51 Non-range instructions can be used to pass up to 4 arguments (including object reference). 52 Unused register slot values will be discarded and corresponding registers will not be 53 passed to the callee). 54 For methods with more arguments range kinds of instruction are to be used, which takes 55 the needed number of arguments starting from 'vs' register (including object reference). 56 verification: 57 - method_id_non_static 58 - compatible_arguments 59 - method_id_accessible 60 exceptions: 61 - x_null 62 - x_abstract 63 commands: 64 65 - file-name: wrong_object_1 66 bugid: ['2287', '5271'] 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 verification: 73 - compatible_arguments 74 header-template: [r_A, r_B] 75 description: Check incorrect usage of `call.virt.short` instruction. First argument is of incorrect type instead of object reference. 76 runner-options: ['verifier-failure', 'verifier-debug-config'] 77 tags: ['verifier'] 78 code-template: | 79 .function i32 A.foo(A a0%s) { 80 ldai 1 81 return 82 } 83 84 .function i32 main() { 85 %s 86 call.virt.short A.foo%s 87 # check object is equal to original 88 movi v0, 1 89 jne v0, exit_failure 90 ldai 0 91 return 92 exit_failure: 93 ldai 1 94 return 95 check-type: none 96 cases: 97 - values: 98 - '' 99 - '' 100 - ',' 101 runner-options: [compile-failure] 102 bugid: ['1855'] 103 - values: 104 - '' 105 - 'movi v0, 0' 106 - ', v0' 107 - values: 108 - '' 109 - | 110 # 111 lda.type A 112 sta.obj v0 113 - ', v0' 114 bugid: ['2256'] 115 - values: 116 - '' 117 - | 118 # 119 lda.type B 120 sta.obj v0 121 - ', v0' 122 - values: 123 - '' 124 - 'movi.64 v0, 0' 125 - ', v0' 126 - values: 127 - '' 128 - 'fmovi.64 v0, 0' 129 - ', v0' 130 - values: 131 - '' 132 - | 133 # 134 lda.str "some string" 135 sta.obj v0 136 - ', v0' 137 - values: 138 - '' 139 - | 140 # 141 lda.str "some string" 142 sta.obj v0 143 movi v1, 1 144 - ', v0, v1' 145 - values: 146 - '' 147 - | 148 # 149 lda.str "some string" 150 sta.obj v0 151 movi.64 v1, 1 152 - ', v0, v1' 153 - values: 154 - '' 155 - | 156 # 157 lda.str "some string" 158 sta.obj v0 159 fmovi.64 v1, 1 160 - ', v0, v1' 161 - values: 162 - ', i32 a1' 163 - | 164 # 165 movi v0, 0 166 movi v1, 1 167 - ', v0, v1' 168 - values: 169 - ', i64 a1' 170 - | 171 # 172 movi v0, 0 173 movi.64 v1, 1 174 - ', v0, v1' 175 - values: 176 - ', f64 a1' 177 - | 178 # 179 movi v0, 0 180 fmovi.64 v1, 1.1 181 - ', v0, v1' 182 183 - values: 184 - ', i32 a1' 185 - | 186 # 187 movi.64 v0, 0 188 movi v1, 1 189 - ', v0, v1' 190 - values: 191 - ', i64 a1' 192 - | 193 # 194 movi.64 v0, 0 195 movi.64 v1, 1 196 - ', v0, v1' 197 - values: 198 - ', f64 a1' 199 - | 200 # 201 movi.64 v0, 0 202 fmovi.64 v1, 1.1 203 - ', v0, v1' 204 205 - values: 206 - ', i32 a1' 207 - | 208 # 209 fmovi.64 v0, 0.0 210 movi v1, 1 211 - ', v0, v1' 212 - values: 213 - ', i64 a1' 214 - | 215 # 216 fmovi.64 v0, 0 217 movi.64 v1, 1 218 - ', v0, v1' 219 - values: 220 - ', f64 a1' 221 - | 222 # 223 fmovi.64 v0, 0 224 fmovi.64 v1, 1.1 225 - ', v0, v1' 226 227 - file-name: p_wrong_object_2 228 isa: 229 instructions: 230 - sig: call.virt.short method_id, v1:in:top, v2:in:top 231 acc: out:top 232 format: [op_v1_4_v2_4_id_16] 233 verification: 234 - compatible_arguments 235 header-template: [r_A, r_B] 236 description: > 237 Check incorrect usage of `call.virt.short` instruction. First argument is a reference to object of incompatible type. 238 Use PandaAssembly language context. 239 runner-options: ['verifier-failure', 'verifier-debug-config'] 240 tags: [verifier] 241 bugid: ['1324'] 242 template-cases: 243 - values: 244 - | 245 %s 246 .function i32 A.foo(A a0%s) { 247 ldai 1 248 return 249 } 250 - values: 251 - | 252 %s 253 ##- %s 254 .function i32 A.foo(A a0) { 255 ldai 1 256 return 257 } 258 code-template: | 259 %s 260 261 .function i32 main() { 262 initobj.short B.constructor 263 sta.obj v0 264 *s 265 call.virt.short A.foo, v0*s 266 267 check-type: exit-positive 268 cases: 269 - values: 270 - '' 271 - '' 272 - '' 273 - '' 274 - values: 275 - '' 276 - ',i32 a1' 277 - 'movi v1, 0' 278 - ', v1' 279 - values: 280 - '' 281 - ',i32 a1' 282 - 'movi v1, 1' 283 - ', v1' 284 - values: 285 - '' 286 - ', i64 a1' 287 - 'movi.64 v1, 0' 288 - ', v1' 289 - values: 290 - '' 291 - ', i64 a1' 292 - 'movi.64 v1, 0x100000000' 293 - ', v1' 294 - values: 295 - '' 296 - ', f64 a1' 297 - 'fmovi.64 v1, 0' 298 - ', v1' 299 - values: 300 - '' 301 - ', f64 a1' 302 - 'fmovi.64 v1, 1.1' 303 - ', v1' 304 - values: 305 - '.record panda.String <external>' 306 - ', panda.String a1' 307 - | 308 # 309 lda.str "some string" 310 sta.obj v1 311 - ', v1' 312 313 - file-name: arg_types 314 isa: 315 instructions: 316 - sig: call.virt.short method_id, v1:in:top, v2:in:top 317 acc: out:top 318 format: [op_v1_4_v2_4_id_16] 319 verification: 320 - compatible_arguments 321 header-template: [r_A] 322 description: > 323 Verifier should report when register type does not match function argument type. 324 code-template: | 325 .record panda.Object <external> 326 .record panda.String <external> 327 .function void A.func(A a0, %s) { 328 return.void 329 } 330 331 .function i32 main() { 332 initobj A.constructor 333 sta.obj v0 334 *s 335 call.virt.short A.func, v0, v1 336 template-cases: 337 - values: 338 - 'i32 a1' 339 exclude: [i32] 340 - values: 341 - 'i64 a1' 342 exclude: [i64] 343 - values: 344 - 'f64 a1' 345 exclude: [f64] 346 - values: 347 - 'i32[] a1' 348 exclude: [i32arr] 349 - values: 350 - 'i64[] a1' 351 exclude: [i64arr] 352 - values: 353 - 'f64[] a1' 354 exclude: [f64arr] 355 - values: 356 - 'panda.String a1' 357 exclude: [str] 358 - values: 359 - 'panda.String[] a1' 360 exclude: [strarr] 361 - values: 362 - 'panda.Object a1' 363 exclude: [obj, objarr, i32arr, i64arr, f64arr, str, strarr] 364 - values: 365 - 'panda.Object[] a1' 366 exclude: [objarr, strarr] 367 368 check-type: exit-positive 369 bugid: ['1324'] 370 tags: [verifier] 371 runner-options: ['verifier-failure', 'verifier-debug-config'] 372 cases: 373 - values: 374 - | 375 # 376 movi v1, 0 377 id: i32 378 - values: 379 - | 380 # 381 movi v1, 1 382 id: i32 383 - values: 384 - | 385 # 386 movi.64 v1, 0 387 id: i64 388 - values: 389 - | 390 # 391 movi.64 v1, 1 392 id: i64 393 - values: 394 - | 395 # 396 fmovi.64 v1, 0 397 id: f64 398 - values: 399 - | 400 # 401 fmovi.64 v1, 3.1415926535 402 id: f64 403 - values: 404 - | 405 # 406 movi v1, 123 407 newarr v1, v1, i32[] 408 id: i32arr 409 - values: 410 - | 411 # 412 movi v1, 123 413 newarr v1, v1, i64[] 414 id: i64arr 415 - values: 416 - | 417 # 418 movi v1, 123 419 newarr v1, v1, f64[] 420 id: f64arr 421 - values: 422 - | 423 # 424 lda.str "some string" 425 sta.obj v1 426 id: str 427 - values: 428 - | 429 # 430 movi v1, 123 431 newarr v1, v1, panda.String[] 432 id: strarr 433 - values: 434 - | 435 # 436 newobj v1, panda.Object 437 id: obj 438 - values: 439 - | 440 # 441 movi v1, 123 442 newarr v1, v1, panda.Object[] 443 id: objarr 444 445 - file-name: acc_uninitialized 446 isa: 447 instructions: 448 - sig: call.virt.short method_id, v1:in:top, v2:in:top 449 acc: out:top 450 format: [op_v1_4_v2_4_id_16] 451 header-template: [r_A] 452 description: > 453 Verifier should report that uninitialized accumulator is used in function. 454 check-type: exit-positive 455 bugid: ['1324'] 456 tags: [verifier] 457 runner-options: ['verifier-failure', 'verifier-debug-config'] 458 code-template: | 459 .function void A.func(A a0) { 460 %s 461 return.void 462 } 463 464 .function i32 main() { 465 initobj A.constructor 466 sta.obj v0 467 call.virt.short A.func, v0 468 cases: 469 - values: 470 - sta v0 471 - values: 472 - sta.64 v0 473 - values: 474 - sta.obj v0 475 476 - file-name: reg_uninitialized 477 isa: 478 instructions: 479 - sig: call.virt.short method_id, v1:in:top, v2:in:top 480 acc: out:top 481 format: [op_v1_4_v2_4_id_16] 482 header-template: [r_A] 483 description: > 484 Verifier should report that uninitialized register is used in function. 485 check-type: exit-positive 486 bugid: ['1324'] 487 tags: [verifier] 488 runner-options: ['verifier-failure', 'verifier-debug-config'] 489 code-template: | 490 .function void A.func(A a0) { 491 %s 492 return.void 493 } 494 495 .function i32 main() { 496 initobj A.constructor 497 sta.obj v0 498 call.virt.short A.func, v0 499 template-cases: 500 - values: 501 - lda %s 502 exclude: [r16] 503 - values: 504 - lda.64 %s 505 exclude: [r16] 506 - values: 507 - lda.obj %s 508 exclude: [r16] 509 - values: 510 - mov v0, %s 511 cases: 512 - values: [v0] 513 - values: [v1] 514 - values: [v128] 515 - values: [v255] 516 - values: [v256] 517 id: r16 518 - values: [v32768] 519 id: r16 520 - values: [v65535] 521 id: r16 522 523 - file-name: p_method_id_accessible 524 isa: 525 instructions: 526 - sig: call.virt.short method_id, v1:in:top, v2:in:top 527 acc: out:top 528 format: [op_v1_4_v2_4_id_16] 529 verification: 530 - method_id_accessible 531 header-template: [r_A] 532 description: > 533 Verifier should report that method is not accessible if method_id is not resolved to existing method. Use PandaAssembly language context. 534 check-type: exit-positive 535 tags: [verifier] 536 runner-options: ['verifier-failure', 'verifier-debug-config'] 537 code-template: | 538 .function %s A.func(A a0, *s a1) <external> 539 540 .function i32 main() { 541 initobj A.constructor 542 sta.obj v0 543 *s 544 call.virt.short A.func, v0, v1 545 template-cases: 546 - values: 547 - 'void' 548 549 - values: 550 - 'i32' 551 exclude: [void] 552 - values: 553 - 'i64' 554 exclude: [void] 555 - values: 556 - 'f64' 557 exclude: [void] 558 - values: 559 - 'i32[]' 560 exclude: [void] 561 - values: 562 - 'i64[]' 563 exclude: [void] 564 - values: 565 - 'f64[]' 566 exclude: [void] 567 - values: 568 - 'A' 569 exclude: [void] 570 - values: 571 - 'A[]' 572 exclude: [void] 573 cases: 574 - case-template: | 575 .function void A.func(A a0) <external> 576 577 .function i32 main() { 578 initobj A.constructor 579 sta.obj v0 580 call.virt.short A.func, v0 581 id: void 582 - values: ['i32', 'movi v1, 12345678'] 583 - values: ['i64', 'movi.64 v1, 0x123456789ABCDEF'] 584 - values: ['f64', 'fmovi.64 v1, 3.1415926535'] 585 - values: 586 - 'i32[]' 587 - | 588 # 589 movi v1, 123 590 newarr v1, v1, i32[] 591 - values: 592 - 'i64[]' 593 - | 594 # 595 movi v1, 123 596 newarr v1, v1, i64[] 597 - values: 598 - 'f64[]' 599 - | 600 # 601 movi v1, 123 602 newarr v1, v1, f64[] 603 - values: 604 - 'A' 605 - | 606 # 607 initobj A.constructor 608 sta.obj v1 609 - values: 610 - 'A[]' 611 - | 612 # 613 movi v1, 123 614 newarr v1, v1, A[] 615 616 - file-name: p_method_id_non_static 617 bugid: ["1324"] 618 isa: 619 instructions: 620 - sig: call.virt.short method_id, v1:in:top, v2:in:top 621 acc: out:top 622 format: [op_v1_4_v2_4_id_16] 623 verification: 624 - method_id_non_static 625 header-template: [r_A] 626 description: > 627 Verifier should report that method is not accessible if method_id is not resolved to existing method. Use PandaAssembly language context. 628 check-type: exit-positive 629 tags: [verifier] 630 runner-options: ['verifier-failure', 'verifier-debug-config'] 631 code-template: | 632 .function %s A.func(A a0, *s a1) <static> { 633 %s 634 } 635 636 .function i32 main() { 637 initobj A.constructor 638 sta.obj v0 639 *s 640 call.virt.short A.func, v0, v1 641 template-cases: 642 - values: 643 - 'void' 644 - 'return.void' 645 - values: 646 - 'i32' 647 - | 648 # 649 ldai 1 650 return 651 exclude: [void] 652 - values: 653 - 'i64' 654 - | 655 # 656 ldai.64 1 657 return.64 658 exclude: [void] 659 - values: 660 - 'f64' 661 - | 662 # 663 fldai.64 3.1415926535 664 return.64 665 exclude: [void] 666 - values: 667 - 'i32[]' 668 - | 669 # 670 movi v1, 123 671 newarr v1, v1, i32[] 672 lda.obj v1 673 return.obj 674 exclude: [void] 675 - values: 676 - 'i64[]' 677 - | 678 # 679 movi v1, 123 680 newarr v1, v1, i64[] 681 lda.obj v1 682 return.obj 683 exclude: [void] 684 - values: 685 - 'f64[]' 686 - | 687 # 688 movi v1, 123 689 newarr v1, v1, f64[] 690 lda.obj v1 691 return.obj 692 exclude: [void] 693 - values: 694 - 'A' 695 - | 696 # 697 initobj A.constructor 698 sta.obj v1 699 return.obj 700 - values: 701 - 'A[]' 702 - | 703 # 704 movi v1, 123 705 newarr v1, v1, A[] 706 lda.obj v1 707 return.obj 708 cases: 709 - case-template: | 710 .function void A.func(A a0) <static> { 711 return.void 712 } 713 714 .function i32 main() { 715 initobj A.constructor 716 sta.obj v0 717 call.virt.short A.func, v0 718 id: void 719 - values: ['i32', 'movi v1, 12345678'] 720 - values: ['i64', 'movi.64 v1, 0x123456789ABCDEF'] 721 - values: ['f64', 'fmovi.64 v1, 3.1415926535'] 722 - values: 723 - 'i32[]' 724 - | 725 # 726 movi v1, 123 727 newarr v1, v1, i32[] 728 - values: 729 - 'i64[]' 730 - | 731 # 732 movi v1, 123 733 newarr v1, v1, i64[] 734 - values: 735 - 'f64[]' 736 - | 737 # 738 movi v1, 123 739 newarr v1, v1, f64[] 740 - values: 741 - 'A' 742 - | 743 # 744 initobj A.constructor 745 sta.obj v1 746 - values: 747 - 'A[]' 748 - | 749 # 750 movi v1, 123 751 newarr v1, v1, A[] 752 753 - file-name: match_parameters_amount 754 isa: 755 instructions: 756 - sig: call.virt.short method_id, v1:in:top, v2:in:top 757 acc: out:top 758 format: [op_v1_4_v2_4_id_16] 759 header-template: [r_A] 760 description: > 761 Compiler should check amount of function parameters with corresponding call.virt.short 762 check-type: none 763 runner-options: [compile-failure] 764 code-template: | 765 766 .function void A.func(A a0, i32 a1%s) <external> 767 768 .function i32 main() { 769 call.virt.short A.func, v0%s 770 cases: 771 - values: ['', ''] 772 - values: [', i32 a2', ', v1'] 773 - values: [', i32 a2, i32 a3', ', v1'] 774 - values: [', i32 a2, i32 a3, i32 a4', ', v1'] 775