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