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