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: polymorphic-hdr
16    template: |
17      #
18      .language PandaAssembly
19      .record panda.Class <external>
20      .record panda.Object <external>
21      .record panda.Integer <external>
22      .record panda.Long <external>
23      .record panda.Short <external>
24      .record panda.String <external>
25      .record panda.invoke.MethodHandles <external>
26      .record panda.invoke.MethodHandles$Lookup <external>
27      .record panda.invoke.MethodHandle <external>
28      .record panda.invoke.VarHandle <external>
29      .record panda.invoke.MethodType <external>
30      .record panda.NullPointerException <external>
31      .record panda.reflect.Field <external>
32      .function panda.Object panda.reflect.Field.get(panda.reflect.Field a0, panda.Object a1) <external>
33      .function panda.reflect.Field panda.Class.getField(panda.Class a0, panda.String a1) <external>
34      .function panda.Class panda.Class.forName(panda.String a0) <external>
35      .function panda.invoke.MethodHandles$Lookup panda.invoke.MethodHandles.lookup() <external, static>
36      .function panda.invoke.MethodHandle panda.invoke.MethodHandles$Lookup.findStatic(panda.invoke.MethodHandles$Lookup a0, panda.Class a1, panda.String a2, panda.invoke.MethodType a3) <external>
37      .function panda.invoke.MethodHandle panda.invoke.MethodHandles$Lookup.findVirtual(panda.invoke.MethodHandles$Lookup a0, panda.Class a1, panda.String a2, panda.invoke.MethodType a3) <external>
38      .function panda.invoke.VarHandle panda.invoke.MethodHandles$Lookup.findVarHandle(panda.invoke.MethodHandles$Lookup a0, panda.Class a1, panda.String a2, panda.Class a3) <external>
39      .record W <panda.access = public> {}
40      .record R <panda.access = public, panda.extends = W> {
41        u1          f_boolean <panda.access = public>
42        i8          f_byte    <panda.access = public>
43        u16         f_char    <panda.access = public>
44        i16         f_short   <panda.access = public>
45        i32         f_int     <panda.access = public>
46        i64         f_long    <panda.access = public>
47        f32         f_float   <panda.access = protected>
48        f64         f_double  <panda.access = private>
49      }
50      .record Q <panda.access = public, panda.extends = R> {}
51      # returns int.class for panda.Integer, can be replaced with panda.Integer.TYPE
52      .function panda.Class R.getPrimitiveType(panda.String a0) <static, panda.access=public> {
53          call.short panda.Class.forName, a0
54          sta.obj v1
55          lda.str "TYPE"
56          call.virt.acc.short panda.Class.getField, v1, 1
57          mov.null v0
58          call.virt.acc.short panda.reflect.Field.get, v0, 0
59          return.obj
60      }
61      .function i32 main() {
62          call.short R.test
63          return
64      }
65
66tests:
67  - file-name: 'calle.polymorphic'
68    isa:
69      title: Polymorphic calls
70      description: >
71        TODO
72
73    commands:
74      - file-name: 'syntax'
75        isa:
76          instructions:
77            - sig: calle.polymorphic method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
78              prefix: PandaAssembly
79              acc: out:top
80              format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16]
81        description: Check calle.polymorphic syntax.
82        runner-options: [use-pa, compile-failure, ]
83        tags: ['irtoc_ignore']
84        header-template: [polymorphic-hdr]
85        code-template: |
86          .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, R a1, R a2, R a3) <external>
87          .function i32 R.test() <static, panda.access = public> {
88              calle.polymorphic %s
89        check-type: exit-positive
90        cases:
91          - values:
92            - 'panda.invoke.MethodHandle.invokeExact, v16, v2, v3, v4'
93          - values:
94            - 'panda.invoke.MethodHandle.invokeExact, v1, v16, v3, v4'
95          - values:
96            - 'panda.invoke.MethodHandle.invokeExact, v1, v2, v16, v4'
97          - values:
98            - 'panda.invoke.MethodHandle.invokeExact, v1, v2, v3, v16'
99          - values:
100            - 'panda.invoke.MethodHandle.invokeExact, v1, v2, v3, v4'
101            runner-options: [use-pa, compile-only, ]
102
103      - file-name: 'uninitialized_regs'
104        isa:
105          instructions:
106            - sig: calle.polymorphic method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
107              prefix: PandaAssembly
108              acc: out:top
109              format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16]
110        description: Check that verifier reports an error on unitialized registers.
111        runner-options: [use-pa, verifier-failure, verifier-config, ]
112        tags: ['verifier', 'irtoc_ignore']
113        header-template: [polymorphic-hdr]
114        code-template: |
115          .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, R a1, R a2, R a3) <external>
116          .function i32 R.test() <static, panda.access = public> {
117              %s
118              calle.polymorphic panda.invoke.MethodHandle.invokeExact, v1, v2, v3, v4
119        check-type: exit-positive
120        cases:
121          - values:
122            - ''
123            bugid: ['7636']
124            ignore: true
125          - values:
126            - |
127              #
128                  newobj v1, R
129                  newobj v2, R
130                  newobj v3, R
131            bugid: ['7636']
132            ignore: true
133          - values:
134            - |
135              #
136                  newobj v1, R
137                  newobj v2, R
138                  newobj v3, R
139                  newobj v4, R
140            runner-options: [use-pa, verifier-only, verifier-config, ]
141
142      - file-name: 'npe'
143        isa:
144          exceptions: [x_null]
145        description: Check that NullPointerException is thrown if v1 is null.
146        runner-options: [use-pa, ]
147        tags: ['irtoc_ignore']
148        bugid: ['7637']
149        ignore: true
150        header-template: [polymorphic-hdr]
151        code-template: |
152          .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, R a1) <external>
153          .function i32 R.test() <static, panda.access = public> {
154              mov.null v4
155              newobj v5, R
156            try_begin:
157              calle.polymorphic panda.invoke.MethodHandle.invokeExact, v4, v5
158              ldai 4
159              return
160            try_end:
161            catch_begin:
162              ldai 0
163              return
164            catch_end:
165            .catch panda.NullPointerException, try_begin, try_end, catch_begin, catch_end
166          }
167        check-type: empty
168
169      - file-name: 'call_1s'
170        isa:
171          instructions:
172            - sig: calle.polymorphic method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
173              prefix: PandaAssembly
174              acc: out:top
175              format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16]
176        description: Check that polymorphic call is performed for static function with one argument.
177        runner-options: [use-pa, ]
178        tags: ['irtoc_ignore']
179        bugid: ['7634']
180        header-template: [polymorphic-hdr]
181        code-template: |
182          .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class a1) <external, static>
183          %s
184          .function i32 R.inc32(i32 a0) {
185              inci a0, 1
186              lda a0
187              return
188          }
189          .function i32 R.inc64(i64 a0) {
190              ldai.64 2
191              add2.64 a0
192              i64toi32
193              return
194          }
195          .function i32 R.inc16(i16 a0) {
196              inci a0, 3
197              lda a0
198              return
199          }
200          .function i32 R.test() <static, panda.access = public> {
201              call.short panda.invoke.MethodHandles.lookup
202              sta.obj v0   # MethodHandles.Lookup object
203
204              lda.str "panda.Integer"
205              sta.obj v1
206              call.short R.getPrimitiveType, v1
207              sta.obj v1
208              lda.str "%s"
209              sta.obj v2
210              call.short R.getPrimitiveType, v2
211              sta.obj v2
212              call.short panda.invoke.MethodType.methodType, v1, v2
213              sta.obj v1   # MethodType object for (i32)i32
214
215              lda.type R
216              sta.obj v2
217              lda.str "%s"
218              sta.obj v3
219              call.virt panda.invoke.MethodHandles$Lookup.findStatic, v0, v2, v3, v1
220              sta.obj v4    # MethodHandle object
221
222              %s
223              calle.polymorphic panda.invoke.MethodHandle.invokeExact, v4, v6
224              movi v1, 42
225              jeq v1, ok
226              ldai 1
227              return
228          ok:
229              ldai 0
230              return
231          }
232        check-type: empty
233        cases:
234          - values:
235              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, i32 a1) <external>
236              - panda.Integer
237              - inc32
238              - movi v6, 41
239          - values:
240              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, i64 a1) <external>
241              - panda.Long
242              - inc64
243              - movi.64 v6, 40
244          - values:
245              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, i16 a1) <external>
246              - panda.Short
247              - inc16
248              - movi v6, 39
249
250      - file-name: 'call_3s'
251        isa:
252          instructions:
253            - sig: calle.polymorphic method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
254              prefix: PandaAssembly
255              acc: out:top
256              format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16]
257        description: Check that polymorphic call is performed for static function with three arguments.
258        runner-options: [use-pa, ]
259        tags: ['irtoc_ignore']
260        bugid: ['7634']
261        header-template: [polymorphic-hdr]
262        code-template: |
263          .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class[] a1) <external, static>
264          %s
265          .function i32 R.sum32(i32 a0, i32 a1, i32 a2) {
266              add a0, a1
267              add2 a2
268              return
269          }
270          .function i32 R.sum64(i64 a0, i64 a1, i64 a2) {
271              lda.64 a0
272              add2.64 a1
273              add2.64 a2
274              i64toi32
275              return
276          }
277          .function i32 R.sum16(i16 a0, i16 a1, i16 a2) {
278              add a0, a1
279              add2 a2
280              return
281          }
282          .function i32 R.test() <static, panda.access = public> {
283              call.short panda.invoke.MethodHandles.lookup
284              sta.obj v0   # MethodHandles.Lookup object
285
286              lda.str "panda.Integer"
287              sta.obj v1
288              call.short R.getPrimitiveType, v1
289              sta.obj v1
290              lda.str "%s"
291              sta.obj v2
292              call.short R.getPrimitiveType, v2
293              movi v3, 3  # 3 arguments
294              newarr v2, v3, panda.Class[]
295              movi v4, 0
296              starr.obj v2, v4
297              inci v4, 1
298              starr.obj v2, v4
299              inci v4, 1
300              starr.obj v2, v4
301              call panda.invoke.MethodType.methodType, v1, v2
302              sta.obj v1   # MethodType object for (i32, i32, i32)i32
303
304              lda.type R
305              sta.obj v2
306              lda.str "%s"
307              sta.obj v3
308              call.virt panda.invoke.MethodHandles$Lookup.findStatic, v0, v2, v3, v1
309              sta.obj v4    # MethodHandle object
310
311              %s
312              calle.polymorphic panda.invoke.MethodHandle.invokeExact, v4, v6, v7, v8
313              movi v1, 42
314              jeq v1, ok
315              ldai 1
316              return
317          ok:
318              ldai 0
319              return
320          }
321        check-type: empty
322        cases:
323          - values:
324              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, i32 a1, i32 a2, i32 a3) <external>
325              - panda.Integer
326              - sum32
327              - |
328                #
329                    movi v6, 22
330                    movi v7, 15
331                    movi v8, 5
332          - values:
333              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, i64 a1, i64 a2, i64 a3) <external>
334              - panda.Long
335              - sum64
336              - |
337                #
338                    movi.64 v6, -500
339                    movi.64 v7, 1042
340                    movi.64 v8, -500
341          - values:
342              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, i16 a1, i16 a2, i16 a3) <external>
343              - panda.Short
344              - sum16
345              - |
346                #
347                    movi v6, 1
348                    movi v7, 2
349                    movi v8, 39
350
351      - file-name: 'call_1v'
352        isa:
353          instructions:
354            - sig: calle.polymorphic method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
355              prefix: PandaAssembly
356              acc: out:top
357              format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16]
358        description: Check that polymorphic call is performed for virtual function with one argument.
359        runner-options: [use-pa, ]
360        tags: ['irtoc_ignore']
361        bugid: ['7634']
362        header-template: [polymorphic-hdr]
363        code-template: |
364          .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class a1) <external, static>
365          %s
366          .function i32 R.inc32(R a0, i32 a1) {
367              inci a1, 1
368              lda a1
369              return
370          }
371          .function i32 R.inc64(R a0, i64 a1) {
372              ldai.64 2
373              add2.64 a1
374              i64toi32
375              return
376          }
377          .function i32 R.inc16(R a0, i16 a1) {
378              inci a1, 3
379              lda a1
380              return
381          }
382          .function i32 R.test() <static, panda.access = public> {
383              call.short panda.invoke.MethodHandles.lookup
384              sta.obj v0   # MethodHandles.Lookup object
385
386              lda.str "panda.Integer"
387              sta.obj v1
388              call.short R.getPrimitiveType, v1
389              sta.obj v1
390              lda.str "%s"
391              sta.obj v2
392              call.short R.getPrimitiveType, v2
393              sta.obj v2
394              call.short panda.invoke.MethodType.methodType, v1, v2
395              sta.obj v1   # MethodType object for (i32)i32
396
397              lda.type R
398              sta.obj v2
399              lda.str "%s"
400              sta.obj v3
401              call.virt panda.invoke.MethodHandles$Lookup.findVirtual, v0, v2, v3, v1
402              sta.obj v4    # MethodHandle object
403
404              newobj v5, R
405              %s
406              calle.polymorphic panda.invoke.MethodHandle.invokeExact, v4, v5, v6
407              movi v1, 42
408              jeq v1, ok
409              ldai 1
410              return
411          ok:
412              ldai 0
413              return
414          }
415        check-type: empty
416        cases:
417          - values:
418              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, R a1, i32 a2) <external>
419              - panda.Integer
420              - inc32
421              - movi v6, 41
422          - values:
423              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, R a1, i64 a2) <external>
424              - panda.Long
425              - inc64
426              - movi.64 v6, 40
427          - values:
428              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, R a1, i16 a2) <external>
429              - panda.Short
430              - inc16
431              - movi v6, 39
432
433      - file-name: 'call_2v'
434        isa:
435          instructions:
436            - sig: calle.polymorphic method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
437              prefix: PandaAssembly
438              acc: out:top
439              format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16]
440        description: Check that polymorphic call is performed for virtual function with two arguments.
441        runner-options: [use-pa, ]
442        tags: ['irtoc_ignore']
443        bugid: ['7634']
444        header-template: [polymorphic-hdr]
445        code-template: |
446          .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class[] a1) <external, static>
447          %s
448          .function i32 R.sum32(R a0, i32 a1, i32 a2) {
449              add a1, a2
450              return
451          }
452          .function i32 R.sum64(R a0, i64 a1, i64 a2) {
453              lda.64 a1
454              add2.64 a2
455              i64toi32
456              return
457          }
458          .function i32 R.sum16(R a0, i16 a1, i16 a2) {
459              add a1, a2
460              return
461          }
462          .function i32 R.test() <static, panda.access = public> {
463              call.short panda.invoke.MethodHandles.lookup
464              sta.obj v0   # MethodHandles.Lookup object
465
466              lda.str "panda.Integer"
467              sta.obj v1
468              call.short R.getPrimitiveType, v1
469              sta.obj v1
470              lda.str "%s"
471              sta.obj v2
472              call.short R.getPrimitiveType, v2
473              movi v3, 2  # 2 arguments
474              newarr v2, v3, panda.Class[]
475              movi v4, 0
476              starr.obj v2, v4
477              inci v4, 1
478              starr.obj v2, v4
479              call.short panda.invoke.MethodType.methodType, v1, v2
480              sta.obj v1   # MethodType object for (i32, i32)i32
481
482              lda.type R
483              sta.obj v2
484              lda.str "%s"
485              sta.obj v3
486              call.virt panda.invoke.MethodHandles$Lookup.findVirtual, v0, v2, v3, v1
487              sta.obj v4    # MethodHandle object
488
489              newobj v5, R
490              %s
491              calle.polymorphic panda.invoke.MethodHandle.invokeExact, v4, v5, v6, v7
492              movi v1, 42
493              jeq v1, ok
494              ldai 1
495              return
496          ok:
497              ldai 0
498              return
499          }
500        check-type: empty
501        cases:
502          - values:
503              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, R a1, i32 a2, i32 a3) <external>
504              - panda.Integer
505              - sum32
506              - |
507                #
508                    movi v6, 0x800000000039
509                    movi v7, 0x7ffffffffff1
510          - values:
511              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, R a1, i64 a2, i64 a3) <external>
512              - panda.Long
513              - sum64
514              - |
515                #
516                    movi.64 v6, 0x800000000000002b
517                    movi.64 v7, 0x7fffffffffffffff
518          - values:
519              - .function i32 panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, R a1, i16 a2, i16 a3) <external>
520              - panda.Short
521              - sum16
522              - |
523                #
524                    movi v6, 0
525                    movi v7, 42
526
527      - file-name: 'call_obj'
528        isa:
529          exceptions: [x_call]
530        description: Check that polymorphic call throws right exception on invalid arguments.
531        runner-options: [use-pa, ]
532        tags: ['irtoc_ignore']
533        bugid: ['7634']
534        header-template: [polymorphic-hdr]
535        code-template: |
536          .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class a1) <external, static>
537          .function R panda.invoke.MethodHandle.invokeExact(panda.invoke.MethodHandle a0, %s a1) <external>
538          .record panda.Exception <external>
539          .record E <panda.extends = panda.Exception, panda.access = public> {}
540          .record panda.invoke.WrongMethodTypeException <external>
541          .function R R.throwE(R a0) <static> {
542              newobj v0, E
543              throw v0
544              lda.obj a0
545              return.obj
546          }
547          .function i32 R.test() <static, panda.access = public> {
548              call.short panda.invoke.MethodHandles.lookup
549              sta.obj v0   # MethodHandles.Lookup object
550
551              lda.type R
552              sta.obj v1
553              call.short panda.invoke.MethodType.methodType, v1, v1
554              sta.obj v1   # MethodType object for (R)R
555
556              lda.type R
557              sta.obj v2
558              lda.str "throwE"
559              sta.obj v3
560              call.virt panda.invoke.MethodHandles$Lookup.findStatic, v0, v2, v3, v1
561              sta.obj v4    # MethodHandle object
562
563              newobj v6, %s
564          try_begin:
565              calle.polymorphic panda.invoke.MethodHandle.invokeExact, v4, v6
566              ldai 1
567              return
568          try_end:
569          catch_begin:
570              ldai 0
571              return
572          catch_end:
573          %s
574          }
575        check-type: empty
576        cases:
577          - values:
578            - E
579            - E
580            - .catch panda.invoke.WrongMethodTypeException, try_begin, try_end, catch_begin, catch_end
581          - values:
582            - W
583            - W
584            - .catch panda.invoke.WrongMethodTypeException, try_begin, try_end, catch_begin, catch_end
585          - values:
586            - R
587            - R
588            - .catch E, try_begin, try_end, catch_begin, catch_end
589          - values:
590            - Q
591            - Q
592            - .catch panda.invoke.WrongMethodTypeException, try_begin, try_end, catch_begin, catch_end
593
594      - file-name: 'call_vh'
595        isa:
596          instructions:
597            - sig: calle.polymorphic method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
598              prefix: PandaAssembly
599              acc: out:top
600              format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16]
601        description: Check that polymorphic call is performed for field access.
602        runner-options: [use-pa, ]
603        tags: ['irtoc_ignore']
604        bugid: ['7634']
605        header-template: [polymorphic-hdr]
606        code-template: |
607          %s
608          .function i32 R.test() <static, panda.access = public> {
609              call.short panda.invoke.MethodHandles.lookup
610              sta.obj v0   # MethodHandles.Lookup object
611
612              lda.type R
613              sta.obj v2
614              lda.str "%s"
615              sta.obj v3
616              lda.str "%s"
617              sta.obj v4
618              call.short R.getPrimitiveType, v4
619              sta.obj v4
620              call.virt panda.invoke.MethodHandles$Lookup.findVarHandle, v0, v2, v3, v4
621              sta.obj v5    # VarHandle object
622
623              %s
624              ldai 0
625              return
626          fail:
627              ldai 1
628              return
629          }
630        check-type: empty
631        cases:
632          - values:
633            - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R a1, i32 a2) <external>
634            - f_int
635            - panda.Integer
636            - |
637              #
638                  newobj v6, R
639                  movi v7, 42
640                  calle.polymorphic panda.invoke.VarHandle.set, v5, v6, v7
641                  lda.null
642                  ldobj v6, R.f_int
643                  jne v7, fail
644          - values:
645            - .function i32 panda.invoke.VarHandle.get(panda.invoke.VarHandle a0, R a1) <external>
646            - f_int
647            - panda.Integer
648            - |
649              #
650                  newobj v6, R
651                  movi v7, 42
652                  lda v7
653                  stobj v6, R.f_int
654                  lda.null
655                  calle.polymorphic panda.invoke.VarHandle.get, v5, v6
656                  jne v7, fail
657          - values:
658            - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R a1, f64 a2) <external>
659            - f_double
660            - panda.Double
661            - |
662              #
663                  newobj v6, R
664                  fmovi.64 v7, 42.4242
665                  calle.polymorphic panda.invoke.VarHandle.set, v5, v6, v7
666                  lda.null
667                  ldobj.64 v6, R.f_double
668                  fcmpg.64 v7
669                  jnez fail
670          - values:
671            - .function f64 panda.invoke.VarHandle.get(panda.invoke.VarHandle a0, R a1) <external>
672            - f_double
673            - panda.Double
674            - |
675              #
676                  newobj v6, R
677                  fmovi.64 v7, 42.4242
678                  lda.64 v7
679                  stobj.64 v6, R.f_double
680                  lda.null
681                  calle.polymorphic panda.invoke.VarHandle.get, v5, v6
682                  fcmpg.64 v7
683                  jnez fail
684          - values:
685            - .function f32 panda.invoke.VarHandle.getAndSet(panda.invoke.VarHandle a0, R a1, f32 a2) <external>
686            - f_float
687            - panda.Float
688            - |
689              #
690                  newobj v6, R
691                  fmovi v7, 3.141593    # initial value
692                  lda v7
693                  stobj v6, R.f_float
694                  fmovi v8, 2.718282    # value to set by getAndSet
695                  lda.null
696                  calle.polymorphic panda.invoke.VarHandle.getAndSet, v5, v6, v8
697                  fcmpg v7
698                  jnez fail
699                  ldobj v6, R.f_float
700                  fcmpg v8
701                  jnez fail
702          - values:
703            - .function i64 panda.invoke.VarHandle.getAndAdd(panda.invoke.VarHandle a0, R a1, i64 a2) <external>
704            - f_long
705            - panda.Long
706            - |
707              #
708                  newobj v6, R
709                  movi.64 v7, 0x7ffffffffffffffe    # initial value
710                  lda.64 v7
711                  stobj.64 v6, R.f_long
712                  movi.64 v8, 1                     # value to add by getAndAdd
713                  lda.null
714                  calle.polymorphic panda.invoke.VarHandle.getAndAdd, v5, v6, v8
715                  cmp.64 v7
716                  jnez fail
717                  ldobj.64 v6, R.f_long
718                  sub2.64 v8
719                  cmp.64 v7
720                  jnez fail
721          - values:
722            - .function i32 panda.invoke.VarHandle.getAndBitwiseOr(panda.invoke.VarHandle a0, R a1, i32 a2) <external>
723            - f_int
724            - panda.Integer
725            - |
726              #
727                  newobj v6, R
728                  movi v7, 0xf0f0f0f0    # initial value
729                  lda v7
730                  stobj v6, R.f_int
731                  movi v8, 0xa5a5a5a5    # value to OR by getAndBitwiseOr
732                  lda.null
733                  calle.polymorphic panda.invoke.VarHandle.getAndBitwiseOr, v5, v6, v8
734                  jne v7, fail
735                  or2 v8
736                  sta v9
737                  ldobj v6, R.f_int
738                  jne v9, fail
739          - values:
740            - .function i16 panda.invoke.VarHandle.getAndBitwiseAnd(panda.invoke.VarHandle a0, R a1, i16 a2) <external>
741            - f_short
742            - panda.Short
743            - |
744              #
745                  newobj v6, R
746                  movi v7, 0x5a5a    # initial value
747                  lda v7
748                  stobj v6, R.f_short
749                  movi v8, 0x0f0f    # value to AND by getAndBitwiseAnd
750                  lda.null
751                  calle.polymorphic panda.invoke.VarHandle.getAndBitwiseAnd, v5, v6, v8
752                  jne v7, fail
753                  and2 v8
754                  sta v9
755                  ldobj v6, R.f_short
756                  jne v9, fail
757          - values:
758            - .function i8 panda.invoke.VarHandle.getAndBitwiseXor(panda.invoke.VarHandle a0, R a1, i8 a2) <external>
759            - f_byte
760            - panda.Byte
761            - |
762              #
763                  newobj v6, R
764                  ldai 0x35        # initial value
765                  i32toi8
766                  sta v7
767                  stobj v6, R.f_byte
768                  ldai 0x1f        # value to XOR by getAndBitwiseXor
769                  i32toi8
770                  sta v8
771                  lda.null
772                  calle.polymorphic panda.invoke.VarHandle.getAndBitwiseXor, v5, v6, v8
773                  jne v7, fail
774                  xor2 v8
775                  sta v9
776                  ldobj v6, R.f_byte
777                  jne v9, fail
778
779      - file-name: 'call_vh_exc'
780        isa:
781          instructions:
782            - sig: calle.polymorphic method_id, v1:in:top, v2:in:top, v3:in:top, v4:in:top
783              prefix: PandaAssembly
784              acc: out:top
785              format: [pref_op_v1_4_v2_4_v3_4_v4_4_id_16]
786        description: Check that polymorphic call of VarHandle is throwing exceptions as expected.
787        runner-options: [use-pa, ]
788        tags: ['irtoc_ignore']
789        bugid: ['7634']
790        header-template: [polymorphic-hdr]
791        code-template: |
792          %s
793          .function panda.invoke.VarHandle panda.invoke.MethodHandles.arrayElementVarHandle(panda.Class a0) <external>
794          .function i32 R.test() <static, panda.access = public> {
795              lda.type R[]
796              sta.obj v1
797              call.short panda.invoke.MethodHandles.arrayElementVarHandle, v1
798              sta.obj v1 # VarHandle object
799
800              movi v3, 3         # array size
801              newarr v2, v3, R[]
802              movi v3, 1         # element index
803              newobj v4, R       # object to set in R[1]
804          try_begin:
805              %s
806          try_end:
807              ldai 1
808              return
809          catch_begin:
810              ldai 0
811              return
812          catch_end:
813          }
814          %s
815        check-type: empty
816        cases:
817          - values:
818              # no exceptions case, set R into R[]
819              - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) <external>
820              - |
821                #
822                    calle.polymorphic panda.invoke.VarHandle.set, v1, v2, v3, v4
823                    ldai 0
824                    ldarr.obj v2
825                    jnez.obj try_end
826                    ldai 1
827                    ldarr.obj v2
828                    jeqz.obj try_end
829                    isinstance R
830                    jeqz try_end
831                    ldai 2
832                    ldarr.obj v2
833                    jeqz.obj catch_begin
834              - ''
835          - values:
836              # no exceptions case. set Q into R[], Q extends R
837              - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) <external>
838              - |
839                #
840                    newobj v4, Q
841                    calle.polymorphic panda.invoke.VarHandle.set, v1, v2, v3, v4
842                    ldai 0
843                    ldarr.obj v2
844                    jnez.obj try_end
845                    ldai 1
846                    ldarr.obj v2
847                    jeqz.obj try_end
848                    isinstance R
849                    jeqz try_end
850                    ldai 2
851                    ldarr.obj v2
852                    jeqz.obj catch_begin
853              - ''
854          - values:
855              # ClassCastException is expected, set W into R[], W is not R
856              - |
857                .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, W a3) <external>
858                .record panda.ClassCastException <external>
859              - |
860                #
861                    newobj v4, W
862                    calle.polymorphic panda.invoke.VarHandle.set, v1, v2, v3, v4
863              - .catch panda.ClassCastException, try_begin, try_end, catch_begin, catch_end
864          - values:
865              # NPE is expected, VarHandle ref is null
866              - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) <external>
867              - |
868                #
869                    mov.null v1
870                    calle.polymorphic panda.invoke.VarHandle.set, v1, v2, v3, v4
871              - .catch panda.NullPointerException, try_begin, try_end, catch_begin, catch_end
872          - values:
873              # NPE is expected, target array is null
874              - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) <external>
875              - |
876                #
877                    mov.null v2
878                    calle.polymorphic panda.invoke.VarHandle.set, v1, v2, v3, v4
879              - .catch panda.NullPointerException, try_begin, try_end, catch_begin, catch_end
880          - values:
881              # WrongMethodTypeException is expected
882              - |
883                .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2) <external>
884                .record panda.invoke.WrongMethodTypeException <external>
885              - |
886                #
887                    calle.polymorphic panda.invoke.VarHandle.set, v1, v2, v3, v4
888              - .catch panda.invoke.WrongMethodTypeException, try_begin, try_end, catch_begin, catch_end
889          - values:
890              # ArrayIndexOutOfBoundsException is expected
891              - |
892                .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) <external>
893                .record panda.ArrayIndexOutOfBoundsException <external>
894              - |
895                #
896                    movi v3, 100
897                    calle.polymorphic panda.invoke.VarHandle.set, v1, v2, v3, v4
898              - .catch panda.ArrayIndexOutOfBoundsException, try_begin, try_end, catch_begin, catch_end
899          - values:
900              # UnsupportedOperationException is expected
901              - |
902                .function void panda.invoke.VarHandle.getAndBitwiseAnd(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) <external>
903                .record panda.UnsupportedOperationException <external>
904              - |
905                #
906                    calle.polymorphic panda.invoke.VarHandle.getAndBitwiseAnd, v1, v2, v3, v4
907              - .catch panda.UnsupportedOperationException, try_begin, try_end, catch_begin, catch_end
908