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