1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2010 Ben Gruver
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 *    derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28tree grammar smaliTreeWalker;
29
30options {
31  tokenVocab=smaliParser;
32  ASTLabelType=CommonTree;
33}
34
35@header {
36package com.android.tools.smali.smali;
37
38import com.google.common.collect.ImmutableSet;
39import com.google.common.collect.Iterables;
40import com.google.common.collect.Lists;
41import com.google.common.collect.Maps;
42import org.antlr.runtime.BitSet;
43import org.antlr.runtime.*;
44import org.antlr.runtime.tree.CommonTree;
45import org.antlr.runtime.tree.TreeNodeStream;
46import org.antlr.runtime.tree.TreeParser;
47import org.antlr.runtime.tree.TreeRuleReturnScope;
48import com.android.tools.smali.dexlib2.*;
49import com.android.tools.smali.dexlib2.builder.Label;
50import com.android.tools.smali.dexlib2.builder.MethodImplementationBuilder;
51import com.android.tools.smali.dexlib2.builder.SwitchLabelElement;
52import com.android.tools.smali.dexlib2.builder.instruction.*;
53import com.android.tools.smali.dexlib2.iface.Annotation;
54import com.android.tools.smali.dexlib2.iface.AnnotationElement;
55import com.android.tools.smali.dexlib2.iface.ClassDef;
56import com.android.tools.smali.dexlib2.iface.MethodImplementation;
57import com.android.tools.smali.dexlib2.iface.reference.FieldReference;
58import com.android.tools.smali.dexlib2.iface.reference.MethodReference;
59import com.android.tools.smali.dexlib2.iface.value.EncodedValue;
60import com.android.tools.smali.dexlib2.immutable.ImmutableAnnotation;
61import com.android.tools.smali.dexlib2.immutable.ImmutableAnnotationElement;
62import com.android.tools.smali.dexlib2.immutable.reference.ImmutableCallSiteReference;
63import com.android.tools.smali.dexlib2.immutable.reference.ImmutableFieldReference;
64import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodHandleReference;
65import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference;
66import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodProtoReference;
67import com.android.tools.smali.dexlib2.immutable.reference.ImmutableReference;
68import com.android.tools.smali.dexlib2.immutable.reference.ImmutableTypeReference;
69import com.android.tools.smali.dexlib2.immutable.value.*;
70import com.android.tools.smali.dexlib2.util.MethodUtil;
71import com.android.tools.smali.dexlib2.writer.InstructionFactory;
72import com.android.tools.smali.dexlib2.writer.builder.*;
73import com.android.tools.smali.util.LinearSearch;
74
75import java.util.*;
76}
77
78@members {
79  public String classType;
80  private boolean verboseErrors = false;
81  private int apiLevel = 15;
82  private Opcodes opcodes = Opcodes.forApi(apiLevel);
83  private DexBuilder dexBuilder;
84  private int callSiteNameIndex = 0;
85
86  public void setDexBuilder(DexBuilder dexBuilder) {
87      this.dexBuilder = dexBuilder;
88  }
89
90  public void setApiLevel(int apiLevel) {
91      this.opcodes = Opcodes.forApi(apiLevel);
92      this.apiLevel = apiLevel;
93  }
94
95  public void setVerboseErrors(boolean verboseErrors) {
96    this.verboseErrors = verboseErrors;
97  }
98
99  private byte parseRegister_nibble(String register)
100      throws SemanticException {
101    int totalMethodRegisters = method_stack.peek().totalMethodRegisters;
102    int methodParameterRegisters = method_stack.peek().methodParameterRegisters;
103
104    //register should be in the format "v12"
105    int val = Byte.parseByte(register.substring(1));
106    if (register.charAt(0) == 'p') {
107      val = totalMethodRegisters - methodParameterRegisters + val;
108    }
109    if (val >= 2<<4) {
110      throw new SemanticException(input, "The maximum allowed register in this context is list of registers is v15");
111    }
112    //the parser wouldn't have accepted a negative register, i.e. v-1, so we don't have to check for val<0;
113    return (byte)val;
114  }
115
116  //return a short, because java's byte is signed
117  private short parseRegister_byte(String register)
118      throws SemanticException {
119    int totalMethodRegisters = method_stack.peek().totalMethodRegisters;
120    int methodParameterRegisters = method_stack.peek().methodParameterRegisters;
121    //register should be in the format "v123"
122    int val = Short.parseShort(register.substring(1));
123    if (register.charAt(0) == 'p') {
124      val = totalMethodRegisters - methodParameterRegisters + val;
125    }
126    if (val >= 2<<8) {
127      throw new SemanticException(input, "The maximum allowed register in this context is v255");
128    }
129    return (short)val;
130  }
131
132  //return an int because java's short is signed
133  private int parseRegister_short(String register)
134      throws SemanticException {
135    int totalMethodRegisters = method_stack.peek().totalMethodRegisters;
136    int methodParameterRegisters = method_stack.peek().methodParameterRegisters;
137    //register should be in the format "v12345"
138    int val = Integer.parseInt(register.substring(1));
139    if (register.charAt(0) == 'p') {
140      val = totalMethodRegisters - methodParameterRegisters + val;
141    }
142    if (val >= 2<<16) {
143      throw new SemanticException(input, "The maximum allowed register in this context is v65535");
144    }
145    //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0;
146    return val;
147  }
148
149  public String getErrorMessage(RecognitionException e, String[] tokenNames) {
150    if ( e instanceof SemanticException ) {
151      return e.getMessage();
152    } else {
153      return super.getErrorMessage(e, tokenNames);
154    }
155  }
156
157  public String getErrorHeader(RecognitionException e) {
158    return getSourceName()+"["+ e.line+","+e.charPositionInLine+"]";
159  }
160}
161
162smali_file returns[ClassDef classDef]
163  : ^(I_CLASS_DEF header methods fields annotations)
164  {
165    $classDef = dexBuilder.internClassDef($header.classType, $header.accessFlags, $header.superType,
166            $header.implementsList, $header.sourceSpec, $annotations.annotations, $fields.fields, $methods.methods);
167  };
168  catch [Exception ex] {
169    if (verboseErrors) {
170      ex.printStackTrace(System.err);
171    }
172    reportError(new SemanticException(input, ex));
173  }
174
175
176header returns[String classType, int accessFlags, String superType, List<String> implementsList, String sourceSpec]
177: class_spec super_spec? implements_list source_spec
178  {
179    classType = $class_spec.type;
180    $classType = classType;
181    $accessFlags = $class_spec.accessFlags;
182    $superType = $super_spec.type;
183    $implementsList = $implements_list.implementsList;
184    $sourceSpec = $source_spec.source;
185  };
186
187
188class_spec returns[String type, int accessFlags]
189  : CLASS_DESCRIPTOR access_list
190  {
191    $type = $CLASS_DESCRIPTOR.text;
192    $accessFlags = $access_list.value;
193  };
194
195super_spec returns[String type]
196  : ^(I_SUPER CLASS_DESCRIPTOR)
197  {
198    $type = $CLASS_DESCRIPTOR.text;
199  };
200
201
202implements_spec returns[String type]
203  : ^(I_IMPLEMENTS CLASS_DESCRIPTOR)
204  {
205    $type = $CLASS_DESCRIPTOR.text;
206  };
207
208implements_list returns[List<String> implementsList]
209@init { List<String> typeList; }
210  : {typeList = Lists.newArrayList();}
211    (implements_spec {typeList.add($implements_spec.type);} )*
212  {
213    if (typeList.size() > 0) {
214      $implementsList = typeList;
215    } else {
216      $implementsList = null;
217    }
218  };
219
220source_spec returns[String source]
221  : {$source = null;}
222    ^(I_SOURCE string_literal {$source = $string_literal.value;})
223  | /*epsilon*/;
224
225access_list returns[int value]
226  @init
227  {
228    $value = 0;
229  }
230  : ^(I_ACCESS_LIST
231      (
232        ACCESS_SPEC
233        {
234          $value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue();
235        }
236      )*);
237
238access_or_restriction_list returns[int value, Set<HiddenApiRestriction> hiddenApiRestrictions]
239  @init
240  {
241    $value = 0;
242    HiddenApiRestriction hiddenApiRestriction = null;
243    List<HiddenApiRestriction> domainSpecificApiRestrictions = new ArrayList<>();
244  }
245  : ^(I_ACCESS_OR_RESTRICTION_LIST
246      (
247        ACCESS_SPEC
248        {
249          $value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue();
250        }
251        |
252        HIDDENAPI_RESTRICTION
253        {
254          if (opcodes.api < 29) {
255              throw new SemanticException(input, $HIDDENAPI_RESTRICTION, "Hidden API restrictions are only supported on api 29 and above.");
256          }
257
258          HiddenApiRestriction restriction = HiddenApiRestriction.forName($HIDDENAPI_RESTRICTION.getText());
259          if (restriction.isDomainSpecificApiFlag()) {
260             domainSpecificApiRestrictions.add(restriction);
261          } else {
262            if (hiddenApiRestriction != null) {
263              throw new SemanticException(input, $HIDDENAPI_RESTRICTION, "Only one hidden api restriction may be specified.");
264            }
265            hiddenApiRestriction = restriction;
266          }
267        }
268      )*)
269      {
270        ImmutableSet.Builder builder = ImmutableSet.builder();
271        if (hiddenApiRestriction != null) {
272          builder.add(hiddenApiRestriction);
273        }
274        builder.addAll(domainSpecificApiRestrictions);
275        $hiddenApiRestrictions = builder.build();
276      };
277
278fields returns[List<BuilderField> fields]
279  @init {$fields = Lists.newArrayList();}
280  : ^(I_FIELDS
281      (field
282      {
283        $fields.add($field.field);
284      })*);
285
286methods returns[List<BuilderMethod> methods]
287  @init {$methods = Lists.newArrayList();}
288  : ^(I_METHODS
289      (method
290      {
291        $methods.add($method.ret);
292      })*);
293
294field returns [BuilderField field]
295  :^(I_FIELD SIMPLE_NAME access_or_restriction_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?)
296  {
297    int accessFlags = $access_or_restriction_list.value;
298    Set<HiddenApiRestriction> hiddenApiRestrictions = $access_or_restriction_list.hiddenApiRestrictions;
299
300    if (!AccessFlags.STATIC.isSet(accessFlags) && $field_initial_value.encodedValue != null) {
301        throw new SemanticException(input, "Initial field values can only be specified for static fields.");
302    }
303
304    $field = dexBuilder.internField(classType, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type, accessFlags,
305            $field_initial_value.encodedValue, $annotations.annotations, hiddenApiRestrictions);
306  };
307
308
309field_initial_value returns[EncodedValue encodedValue]
310  : ^(I_FIELD_INITIAL_VALUE literal) {$encodedValue = $literal.encodedValue;}
311  | /*epsilon*/;
312
313literal returns[ImmutableEncodedValue encodedValue]
314  : integer_literal { $encodedValue = new ImmutableIntEncodedValue($integer_literal.value); }
315  | long_literal { $encodedValue = new ImmutableLongEncodedValue($long_literal.value); }
316  | short_literal { $encodedValue = new ImmutableShortEncodedValue($short_literal.value); }
317  | byte_literal { $encodedValue = new ImmutableByteEncodedValue($byte_literal.value); }
318  | float_literal { $encodedValue = new ImmutableFloatEncodedValue($float_literal.value); }
319  | double_literal { $encodedValue = new ImmutableDoubleEncodedValue($double_literal.value); }
320  | char_literal { $encodedValue = new ImmutableCharEncodedValue($char_literal.value); }
321  | string_literal { $encodedValue = new ImmutableStringEncodedValue($string_literal.value); }
322  | bool_literal { $encodedValue = ImmutableBooleanEncodedValue.forBoolean($bool_literal.value); }
323  | NULL_LITERAL { $encodedValue = ImmutableNullEncodedValue.INSTANCE; }
324  | type_descriptor { $encodedValue = new ImmutableTypeEncodedValue($type_descriptor.type); }
325  | array_literal { $encodedValue = new ImmutableArrayEncodedValue($array_literal.elements); }
326  | subannotation { $encodedValue = new ImmutableAnnotationEncodedValue($subannotation.annotationType, $subannotation.elements); }
327  | field_literal { $encodedValue = new ImmutableFieldEncodedValue($field_literal.value); }
328  | method_literal { $encodedValue = new ImmutableMethodEncodedValue($method_literal.value); }
329  | enum_literal { $encodedValue = new ImmutableEnumEncodedValue($enum_literal.value); }
330  | method_handle_literal { $encodedValue = new ImmutableMethodHandleEncodedValue($method_handle_literal.value); }
331  | method_prototype { $encodedValue = new ImmutableMethodTypeEncodedValue($method_prototype.proto); };
332
333//everything but string
334fixed_64bit_literal_number returns[Number value]
335  : integer_literal { $value = $integer_literal.value; }
336  | long_literal { $value = $long_literal.value; }
337  | short_literal { $value = $short_literal.value; }
338  | byte_literal { $value = $byte_literal.value; }
339  | float_literal { $value = Float.floatToRawIntBits($float_literal.value); }
340  | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); }
341  | char_literal { $value = (int)$char_literal.value; }
342  | bool_literal { $value = $bool_literal.value?1:0; };
343
344fixed_64bit_literal returns[long value]
345  : integer_literal { $value = $integer_literal.value; }
346  | long_literal { $value = $long_literal.value; }
347  | short_literal { $value = $short_literal.value; }
348  | byte_literal { $value = $byte_literal.value; }
349  | float_literal { $value = Float.floatToRawIntBits($float_literal.value); }
350  | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); }
351  | char_literal { $value = $char_literal.value; }
352  | bool_literal { $value = $bool_literal.value?1:0; };
353
354//everything but string and double
355//long is allowed, but it must fit into an int
356fixed_32bit_literal returns[int value]
357  : integer_literal { $value = $integer_literal.value; }
358  | long_literal { LiteralTools.checkInt($long_literal.value); $value = (int)$long_literal.value; }
359  | short_literal { $value = $short_literal.value; }
360  | byte_literal { $value = $byte_literal.value; }
361  | float_literal { $value = Float.floatToRawIntBits($float_literal.value); }
362  | char_literal { $value = $char_literal.value; }
363  | bool_literal { $value = $bool_literal.value?1:0; };
364
365array_elements returns[List<Number> elements]
366  : {$elements = Lists.newArrayList();}
367    ^(I_ARRAY_ELEMENTS
368      (fixed_64bit_literal_number
369      {
370        $elements.add($fixed_64bit_literal_number.value);
371      })*);
372
373packed_switch_elements returns[List<Label> elements]
374  @init {$elements = Lists.newArrayList();}
375  :
376    ^(I_PACKED_SWITCH_ELEMENTS
377      (label_ref { $elements.add($label_ref.label); })*
378    );
379
380sparse_switch_elements returns[List<SwitchLabelElement> elements]
381  @init {$elements = Lists.newArrayList();}
382  :
383    ^(I_SPARSE_SWITCH_ELEMENTS
384       (fixed_32bit_literal label_ref
385       {
386         $elements.add(new SwitchLabelElement($fixed_32bit_literal.value, $label_ref.label));
387       })*
388    );
389
390method returns[BuilderMethod ret]
391  scope
392  {
393    boolean isStatic;
394    int totalMethodRegisters;
395    int methodParameterRegisters;
396    MethodImplementationBuilder methodBuilder;
397  }
398  @init
399  {
400    $method::totalMethodRegisters = 0;
401    $method::methodParameterRegisters = 0;
402    int accessFlags = 0;
403    $method::isStatic = false;
404    Set<HiddenApiRestriction> hiddenApiRestrictions = null;
405  }
406  :
407    ^(I_METHOD
408      method_name_and_prototype
409      access_or_restriction_list
410      {
411        accessFlags = $access_or_restriction_list.value;
412        hiddenApiRestrictions = $access_or_restriction_list.hiddenApiRestrictions;
413        $method::isStatic = AccessFlags.STATIC.isSet(accessFlags);
414        $method::methodParameterRegisters =
415                MethodUtil.getParameterRegisterCount($method_name_and_prototype.parameters, $method::isStatic);
416      }
417      (
418        (registers_directive
419        {
420          if ($registers_directive.isLocalsDirective) {
421            $method::totalMethodRegisters = $registers_directive.registers + $method::methodParameterRegisters;
422          } else {
423            $method::totalMethodRegisters = $registers_directive.registers;
424          }
425
426          $method::methodBuilder = new MethodImplementationBuilder($method::totalMethodRegisters);
427
428        })
429        |
430        /* epsilon */
431        {
432          $method::methodBuilder = new MethodImplementationBuilder(0);
433        }
434      )
435      ordered_method_items
436      catches
437      parameters[$method_name_and_prototype.parameters]
438      annotations
439    )
440  {
441    MethodImplementation methodImplementation = null;
442    List<BuilderTryBlock> tryBlocks = $catches.tryBlocks;
443
444    boolean isAbstract = false;
445    boolean isNative = false;
446
447    if ((accessFlags & AccessFlags.ABSTRACT.getValue()) != 0) {
448      isAbstract = true;
449    } else if ((accessFlags & AccessFlags.NATIVE.getValue()) != 0) {
450      isNative = true;
451    }
452
453    methodImplementation = $method::methodBuilder.getMethodImplementation();
454
455    if (Iterables.isEmpty(methodImplementation.getInstructions())) {
456      if (!isAbstract && !isNative) {
457        throw new SemanticException(input, $I_METHOD, "A non-abstract/non-native method must have at least 1 instruction");
458      }
459
460      String methodType;
461      if (isAbstract) {
462        methodType = "an abstract";
463      } else {
464        methodType = "a native";
465      }
466
467      if ($registers_directive.start != null) {
468        if ($registers_directive.isLocalsDirective) {
469          throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType);
470        } else {
471          throw new SemanticException(input, $registers_directive.start, "A .registers directive is not valid in \%s method", methodType);
472        }
473      }
474
475      if (methodImplementation.getTryBlocks().size() > 0) {
476        throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType);
477      }
478
479      if (!Iterables.isEmpty(methodImplementation.getDebugItems())) {
480        throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType);
481      }
482
483      methodImplementation = null;
484    } else {
485      if (isAbstract) {
486        throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions");
487      }
488      if (isNative) {
489        throw new SemanticException(input, $I_METHOD, "A native method cannot have any instructions");
490      }
491
492      if ($registers_directive.start == null) {
493        throw new SemanticException(input, $I_METHOD, "A .registers or .locals directive must be present for a non-abstract/non-final method");
494      }
495
496      if ($method::totalMethodRegisters < $method::methodParameterRegisters) {
497        throw new SemanticException(input, $registers_directive.start, "This method requires at least " +
498                Integer.toString($method::methodParameterRegisters) +
499                " registers, for the method parameters");
500      }
501    }
502
503    $ret = dexBuilder.internMethod(
504            classType,
505            $method_name_and_prototype.name,
506            $method_name_and_prototype.parameters,
507            $method_name_and_prototype.returnType,
508            accessFlags,
509            $annotations.annotations,
510            hiddenApiRestrictions,
511            methodImplementation);
512  };
513
514method_prototype returns[ImmutableMethodProtoReference proto]
515  : ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) method_type_list)
516  {
517    String returnType = $type_descriptor.type;
518    List<String> parameters = $method_type_list.types;
519    $proto = new ImmutableMethodProtoReference(parameters, returnType);
520  };
521
522method_name_and_prototype returns[String name, List<SmaliMethodParameter> parameters, String returnType]
523  : SIMPLE_NAME method_prototype
524  {
525    $name = $SIMPLE_NAME.text;
526    $parameters = Lists.newArrayList();
527
528    int paramRegister = 0;
529    for (CharSequence type: $method_prototype.proto.getParameterTypes()) {
530        $parameters.add(new SmaliMethodParameter(paramRegister++, type.toString()));
531        char c = type.charAt(0);
532        if (c == 'D' || c == 'J') {
533            paramRegister++;
534        }
535    }
536    $returnType = $method_prototype.proto.getReturnType();
537  };
538
539method_type_list returns[List<String> types]
540  @init
541  {
542    $types = Lists.newArrayList();
543  }
544  : (
545      nonvoid_type_descriptor
546      {
547        $types.add($nonvoid_type_descriptor.type);
548      }
549    )*;
550
551call_site_reference returns[ImmutableCallSiteReference callSiteReference]
552  :
553  ^(I_CALL_SITE_REFERENCE call_site_name=SIMPLE_NAME method_name=string_literal method_prototype
554        call_site_extra_arguments method_reference)
555    {
556        String callSiteName = $call_site_name.text;
557        ImmutableMethodHandleReference methodHandleReference =
558            new ImmutableMethodHandleReference(MethodHandleType.INVOKE_STATIC,
559                $method_reference.methodReference);
560        $callSiteReference = new ImmutableCallSiteReference(
561            callSiteName, methodHandleReference, $method_name.value, $method_prototype.proto,
562            $call_site_extra_arguments.extraArguments);
563    };
564
565method_handle_type returns[int methodHandleType]
566  : (METHOD_HANDLE_TYPE_FIELD | METHOD_HANDLE_TYPE_METHOD | INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE) {
567    $methodHandleType = MethodHandleType.getMethodHandleType($text);
568  };
569
570method_handle_reference returns[ImmutableMethodHandleReference methodHandle]
571  : method_handle_type (field_reference | method_reference) {
572    ImmutableReference reference;
573    if ($field_reference.text != null) {
574        reference = $field_reference.fieldReference;
575    } else {
576        reference = $method_reference.methodReference;
577    }
578    $methodHandle = new ImmutableMethodHandleReference($method_handle_type.methodHandleType, reference);
579  };
580
581method_handle_literal returns[ImmutableMethodHandleReference value]
582  : ^(I_ENCODED_METHOD_HANDLE method_handle_reference) {
583    $value = $method_handle_reference.methodHandle;
584  };
585
586method_reference returns[ImmutableMethodReference methodReference]
587  : reference_type_descriptor? SIMPLE_NAME method_prototype
588  {
589    String type;
590    if ($reference_type_descriptor.type == null) {
591        type = classType;
592    } else {
593        type = $reference_type_descriptor.type;
594    }
595    $methodReference = new ImmutableMethodReference(type, $SIMPLE_NAME.text,
596             $method_prototype.proto.getParameterTypes(), $method_prototype.proto.getReturnType());
597  };
598
599field_reference returns[ImmutableFieldReference fieldReference]
600  : reference_type_descriptor? SIMPLE_NAME nonvoid_type_descriptor
601  {
602    String type;
603    if ($reference_type_descriptor.type == null) {
604        type = classType;
605    } else {
606        type = $reference_type_descriptor.type;
607    }
608    $fieldReference = new ImmutableFieldReference(type, $SIMPLE_NAME.text,
609            $nonvoid_type_descriptor.type);
610  };
611
612registers_directive returns[boolean isLocalsDirective, int registers]
613  : {$registers = 0;}
614    ^(( I_REGISTERS {$isLocalsDirective = false;}
615      | I_LOCALS {$isLocalsDirective = true;}
616      )
617      short_integral_literal {$registers = $short_integral_literal.value & 0xFFFF;}
618     );
619
620label_def
621  : ^(I_LABEL SIMPLE_NAME)
622  {
623    $method::methodBuilder.addLabel($SIMPLE_NAME.text);
624  };
625
626catches returns[List<BuilderTryBlock> tryBlocks]
627  @init {tryBlocks = Lists.newArrayList();}
628  : ^(I_CATCHES catch_directive* catchall_directive*);
629
630catch_directive
631  : ^(I_CATCH nonvoid_type_descriptor from=label_ref to=label_ref using=label_ref)
632  {
633    $method::methodBuilder.addCatch(dexBuilder.internTypeReference($nonvoid_type_descriptor.type),
634        $from.label, $to.label, $using.label);
635  };
636
637catchall_directive
638  : ^(I_CATCHALL from=label_ref to=label_ref using=label_ref)
639  {
640    $method::methodBuilder.addCatch($from.label, $to.label, $using.label);
641  };
642
643parameters[List<SmaliMethodParameter> parameters]
644  : ^(I_PARAMETERS (parameter[parameters])*);
645
646parameter[List<SmaliMethodParameter> parameters]
647  : ^(I_PARAMETER REGISTER string_literal? annotations)
648    {
649        final int registerNumber = parseRegister_short($REGISTER.text);
650        int totalMethodRegisters = $method::totalMethodRegisters;
651        int methodParameterRegisters = $method::methodParameterRegisters;
652
653        if (registerNumber >= totalMethodRegisters) {
654            throw new SemanticException(input, $I_PARAMETER, "Register \%s is larger than the maximum register v\%d " +
655                    "for this method", $REGISTER.text, totalMethodRegisters-1);
656        }
657        final int indexGuess = registerNumber - (totalMethodRegisters - methodParameterRegisters) - ($method::isStatic?0:1);
658
659        if (indexGuess < 0) {
660            throw new SemanticException(input, $I_PARAMETER, "Register \%s is not a parameter register.",
661                    $REGISTER.text);
662        }
663
664        int parameterIndex = LinearSearch.linearSearch(parameters, SmaliMethodParameter.COMPARATOR,
665            new WithRegister() { public int getRegister() { return indexGuess; } },
666                indexGuess);
667
668        if (parameterIndex < 0) {
669            throw new SemanticException(input, $I_PARAMETER, "Register \%s is the second half of a wide parameter.",
670                                $REGISTER.text);
671        }
672
673        SmaliMethodParameter methodParameter = parameters.get(parameterIndex);
674        methodParameter.name = $string_literal.value;
675        if ($annotations.annotations != null && $annotations.annotations.size() > 0) {
676            methodParameter.annotations = $annotations.annotations;
677        }
678    };
679
680debug_directive
681  : line
682  | local
683  | end_local
684  | restart_local
685  | prologue
686  | epilogue
687  | source;
688
689line
690  : ^(I_LINE integral_literal)
691    {
692        $method::methodBuilder.addLineNumber($integral_literal.value);
693    };
694
695local
696  : ^(I_LOCAL REGISTER ((NULL_LITERAL | name=string_literal) nonvoid_type_descriptor? signature=string_literal?)?)
697    {
698      int registerNumber = parseRegister_short($REGISTER.text);
699      $method::methodBuilder.addStartLocal(registerNumber,
700              dexBuilder.internNullableStringReference($name.value),
701              dexBuilder.internNullableTypeReference($nonvoid_type_descriptor.type),
702              dexBuilder.internNullableStringReference($signature.value));
703    };
704
705end_local
706  : ^(I_END_LOCAL REGISTER)
707    {
708      int registerNumber = parseRegister_short($REGISTER.text);
709      $method::methodBuilder.addEndLocal(registerNumber);
710    };
711
712restart_local
713  : ^(I_RESTART_LOCAL REGISTER)
714    {
715      int registerNumber = parseRegister_short($REGISTER.text);
716      $method::methodBuilder.addRestartLocal(registerNumber);
717    };
718
719prologue
720  : I_PROLOGUE
721    {
722      $method::methodBuilder.addPrologue();
723    };
724
725epilogue
726  : I_EPILOGUE
727    {
728      $method::methodBuilder.addEpilogue();
729    };
730
731source
732  : ^(I_SOURCE string_literal?)
733    {
734      $method::methodBuilder.addSetSourceFile(dexBuilder.internNullableStringReference($string_literal.value));
735    };
736
737call_site_extra_arguments returns[List<ImmutableEncodedValue> extraArguments]
738  : { $extraArguments = Lists.newArrayList(); }
739  ^(I_CALL_SITE_EXTRA_ARGUMENTS (literal { $extraArguments.add($literal.encodedValue); })*);
740
741ordered_method_items
742  : ^(I_ORDERED_METHOD_ITEMS (label_def | instruction | debug_directive)*);
743
744label_ref returns[Label label]
745  : SIMPLE_NAME { $label = $method::methodBuilder.getLabel($SIMPLE_NAME.text); };
746
747register_list returns[byte[\] registers, byte registerCount]
748  @init
749  {
750    $registers = new byte[5];
751    $registerCount = 0;
752  }
753  : ^(I_REGISTER_LIST
754      (REGISTER
755      {
756        if ($registerCount == 5) {
757          throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 " +
758                  "registers. Use the <op>/range alternate opcode instead.");
759        }
760        $registers[$registerCount++] = parseRegister_nibble($REGISTER.text);
761      })*);
762
763register_range returns[int startRegister, int endRegister]
764  : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?)
765    {
766        if ($startReg == null) {
767            $startRegister = 0;
768            $endRegister = -1;
769        } else {
770                $startRegister  = parseRegister_short($startReg.text);
771                if ($endReg == null) {
772                    $endRegister = $startRegister;
773                } else {
774                    $endRegister = parseRegister_short($endReg.text);
775                }
776
777                int registerCount = $endRegister-$startRegister+1;
778                if (registerCount < 1) {
779                    throw new SemanticException(input, $I_REGISTER_RANGE, "A register range must have the lower register listed first");
780                }
781            }
782    };
783
784verification_error_reference returns[ImmutableReference reference]
785  : CLASS_DESCRIPTOR
786  {
787    $reference = new ImmutableTypeReference($CLASS_DESCRIPTOR.text);
788  }
789  | field_reference
790  {
791    $reference = $field_reference.fieldReference;
792  }
793  | method_reference
794  {
795    $reference = $method_reference.methodReference;
796  };
797
798verification_error_type returns[int verificationError]
799  : VERIFICATION_ERROR_TYPE
800  {
801    $verificationError = VerificationError.getVerificationError($VERIFICATION_ERROR_TYPE.text);
802  };
803
804instruction
805  : insn_format10t
806  | insn_format10x
807  | insn_format11n
808  | insn_format11x
809  | insn_format12x
810  | insn_format20bc
811  | insn_format20t
812  | insn_format21c_field
813  | insn_format21c_method_handle
814  | insn_format21c_method_type
815  | insn_format21c_string
816  | insn_format21c_type
817  | insn_format21ih
818  | insn_format21lh
819  | insn_format21s
820  | insn_format21t
821  | insn_format22b
822  | insn_format22c_field
823  | insn_format22c_type
824  | insn_format22s
825  | insn_format22t
826  | insn_format22x
827  | insn_format23x
828  | insn_format30t
829  | insn_format31c
830  | insn_format31i
831  | insn_format31t
832  | insn_format32x
833  | insn_format35c_call_site
834  | insn_format35c_method
835  | insn_format35c_type
836  | insn_format3rc_call_site
837  | insn_format3rc_method
838  | insn_format3rc_type
839  | insn_format45cc_method
840  | insn_format4rcc_method
841  | insn_format51l_type
842  | insn_array_data_directive
843  | insn_packed_switch_directive
844  | insn_sparse_switch_directive;
845  catch [Exception ex] {
846    reportError(new SemanticException(input, $start, ex.getMessage()));
847    recover(input, null);
848  }
849
850insn_format10t
851  : //e.g. goto endloop:
852    ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t label_ref)
853    {
854      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10t.text);
855      $method::methodBuilder.addInstruction(new BuilderInstruction10t(opcode, $label_ref.label));
856    };
857
858insn_format10x
859  : //e.g. return
860    ^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x)
861    {
862      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10x.text);
863      $method::methodBuilder.addInstruction(new BuilderInstruction10x(opcode));
864    };
865
866insn_format11n
867  : //e.g. const/4 v0, 5
868    ^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal)
869    {
870      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11n.text);
871      byte regA = parseRegister_nibble($REGISTER.text);
872
873      short litB = $short_integral_literal.value;
874      LiteralTools.checkNibble(litB);
875
876      $method::methodBuilder.addInstruction(new BuilderInstruction11n(opcode, regA, litB));
877    };
878
879insn_format11x
880  : //e.g. move-result-object v1
881    ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
882    {
883      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11x.text);
884      short regA = parseRegister_byte($REGISTER.text);
885
886      $method::methodBuilder.addInstruction(new BuilderInstruction11x(opcode, regA));
887    };
888
889insn_format12x
890  : //e.g. move v1 v2
891    ^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER)
892    {
893      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT12x.text);
894      byte regA = parseRegister_nibble($registerA.text);
895      byte regB = parseRegister_nibble($registerB.text);
896
897      $method::methodBuilder.addInstruction(new BuilderInstruction12x(opcode, regA, regB));
898    };
899
900insn_format20bc
901  : //e.g. throw-verification-error generic-error, Lsome/class;
902    ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference)
903    {
904      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT20bc.text);
905
906      int verificationError = $verification_error_type.verificationError;
907      ImmutableReference referencedItem = $verification_error_reference.reference;
908
909      $method::methodBuilder.addInstruction(new BuilderInstruction20bc(opcode, verificationError,
910              dexBuilder.internReference(referencedItem)));
911    };
912
913insn_format20t
914  : //e.g. goto/16 endloop:
915    ^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t label_ref)
916    {
917      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT20t.text);
918      $method::methodBuilder.addInstruction(new BuilderInstruction20t(opcode, $label_ref.label));
919    };
920
921insn_format21c_field
922  : //e.g. sget_object v0, java/lang/System/out LJava/io/PrintStream;
923    ^(I_STATEMENT_FORMAT21c_FIELD inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER field_reference)
924    {
925      Opcode opcode = opcodes.getOpcodeByName($inst.text);
926      short regA = parseRegister_byte($REGISTER.text);
927
928      ImmutableFieldReference fieldReference = $field_reference.fieldReference;
929
930      $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
931              dexBuilder.internFieldReference(fieldReference)));
932    };
933
934insn_format21c_method_handle
935  : //e.g. const-method-handle v0, invoke-static@Ljava/lang/Integer;->toString(I)Ljava/lang/String;
936    ^(I_STATEMENT_FORMAT21c_METHOD_HANDLE inst=(INSTRUCTION_FORMAT21c_METHOD_HANDLE) REGISTER method_handle_reference)
937    {
938      Opcode opcode = opcodes.getOpcodeByName($inst.text);
939      short regA = parseRegister_byte($REGISTER.text);
940
941      ImmutableMethodHandleReference methodHandleReference = $method_handle_reference.methodHandle;
942
943      $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
944              dexBuilder.internMethodHandle(methodHandleReference)));
945    };
946
947insn_format21c_method_type
948  : //e.g. const-method-type v0, (ILjava/lang/String;)Ljava/lang/String;
949    ^(I_STATEMENT_FORMAT21c_METHOD_TYPE inst=(INSTRUCTION_FORMAT21c_METHOD_TYPE) REGISTER method_prototype)
950    {
951        Opcode opcode = opcodes.getOpcodeByName($inst.text);
952        short regA = parseRegister_byte($REGISTER.text);
953
954        ImmutableMethodProtoReference methodProtoReference = $method_prototype.proto;
955
956        $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
957                dexBuilder.internMethodProtoReference(methodProtoReference)));
958    };
959
960insn_format21c_string
961  : //e.g. const-string v1, "Hello World!"
962    ^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal)
963    {
964      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text);
965      short regA = parseRegister_byte($REGISTER.text);
966
967      $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
968              dexBuilder.internStringReference($string_literal.value)));
969    };
970
971insn_format21c_type
972  : //e.g. const-class v2, com/android/tools/smali/HelloWorld2/HelloWorld2
973    ^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER nonvoid_type_descriptor)
974    {
975      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text);
976      short regA = parseRegister_byte($REGISTER.text);
977
978      $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA,
979              dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
980    };
981
982insn_format21ih
983  : //e.g. const/high16 v1, 1234
984    ^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal)
985    {
986      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21ih.text);
987      short regA = parseRegister_byte($REGISTER.text);
988
989      int litB = $fixed_32bit_literal.value;
990
991      $method::methodBuilder.addInstruction(new BuilderInstruction21ih(opcode, regA, litB));
992    };
993
994insn_format21lh
995  : //e.g. const-wide/high16 v1, 1234
996    ^(I_STATEMENT_FORMAT21lh INSTRUCTION_FORMAT21lh REGISTER fixed_64bit_literal)
997    {
998      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21lh.text);
999      short regA = parseRegister_byte($REGISTER.text);
1000
1001      long litB = $fixed_64bit_literal.value;
1002
1003      $method::methodBuilder.addInstruction(new BuilderInstruction21lh(opcode, regA, litB));
1004    };
1005
1006insn_format21s
1007  : //e.g. const/16 v1, 1234
1008    ^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal)
1009    {
1010      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21s.text);
1011      short regA = parseRegister_byte($REGISTER.text);
1012
1013      short litB = $short_integral_literal.value;
1014
1015      $method::methodBuilder.addInstruction(new BuilderInstruction21s(opcode, regA, litB));
1016    };
1017
1018insn_format21t
1019  : //e.g. if-eqz v0, endloop:
1020    ^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER label_ref)
1021    {
1022      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21t.text);
1023      short regA = parseRegister_byte($REGISTER.text);
1024
1025      $method::methodBuilder.addInstruction(new BuilderInstruction21t(opcode, regA, $label_ref.label));
1026    };
1027
1028insn_format22b
1029  : //e.g. add-int v0, v1, 123
1030    ^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal)
1031    {
1032      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22b.text);
1033      short regA = parseRegister_byte($registerA.text);
1034      short regB = parseRegister_byte($registerB.text);
1035
1036      short litC = $short_integral_literal.value;
1037      LiteralTools.checkByte(litC);
1038
1039      $method::methodBuilder.addInstruction(new BuilderInstruction22b(opcode, regA, regB, litC));
1040    };
1041
1042insn_format22c_field
1043  : //e.g. iput-object v1, v0, com/android/tools/smali/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String;
1044    ^(I_STATEMENT_FORMAT22c_FIELD inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER field_reference)
1045    {
1046      Opcode opcode = opcodes.getOpcodeByName($inst.text);
1047      byte regA = parseRegister_nibble($registerA.text);
1048      byte regB = parseRegister_nibble($registerB.text);
1049
1050      ImmutableFieldReference fieldReference = $field_reference.fieldReference;
1051
1052      $method::methodBuilder.addInstruction(new BuilderInstruction22c(opcode, regA, regB,
1053              dexBuilder.internFieldReference(fieldReference)));
1054    };
1055
1056insn_format22c_type
1057  : //e.g. instance-of v0, v1, Ljava/lang/String;
1058    ^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor)
1059    {
1060      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text);
1061      byte regA = parseRegister_nibble($registerA.text);
1062      byte regB = parseRegister_nibble($registerB.text);
1063
1064      $method::methodBuilder.addInstruction(new BuilderInstruction22c(opcode, regA, regB,
1065              dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
1066    };
1067
1068insn_format22s
1069  : //e.g. add-int/lit16 v0, v1, 12345
1070    ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal)
1071    {
1072      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22s.text);
1073      byte regA = parseRegister_nibble($registerA.text);
1074      byte regB = parseRegister_nibble($registerB.text);
1075
1076      short litC = $short_integral_literal.value;
1077
1078      $method::methodBuilder.addInstruction(new BuilderInstruction22s(opcode, regA, regB, litC));
1079    };
1080
1081insn_format22t
1082  : //e.g. if-eq v0, v1, endloop:
1083    ^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER label_ref)
1084    {
1085      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22t.text);
1086      byte regA = parseRegister_nibble($registerA.text);
1087      byte regB = parseRegister_nibble($registerB.text);
1088
1089      $method::methodBuilder.addInstruction(new BuilderInstruction22t(opcode, regA, regB, $label_ref.label));
1090    };
1091
1092insn_format22x
1093  : //e.g. move/from16 v1, v1234
1094    ^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER)
1095    {
1096      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22x.text);
1097      short regA = parseRegister_byte($registerA.text);
1098      int regB = parseRegister_short($registerB.text);
1099
1100      $method::methodBuilder.addInstruction(new BuilderInstruction22x(opcode, regA, regB));
1101    };
1102
1103insn_format23x
1104  : //e.g. add-int v1, v2, v3
1105    ^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER)
1106    {
1107      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT23x.text);
1108      short regA = parseRegister_byte($registerA.text);
1109      short regB = parseRegister_byte($registerB.text);
1110      short regC = parseRegister_byte($registerC.text);
1111
1112      $method::methodBuilder.addInstruction(new BuilderInstruction23x(opcode, regA, regB, regC));
1113    };
1114
1115insn_format30t
1116  : //e.g. goto/32 endloop:
1117    ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref)
1118    {
1119      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT30t.text);
1120
1121      $method::methodBuilder.addInstruction(new BuilderInstruction30t(opcode, $label_ref.label));
1122    };
1123
1124insn_format31c
1125  : //e.g. const-string/jumbo v1 "Hello World!"
1126    ^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal)
1127    {
1128      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31c.text);
1129      short regA = parseRegister_byte($REGISTER.text);
1130
1131      $method::methodBuilder.addInstruction(new BuilderInstruction31c(opcode, regA,
1132              dexBuilder.internStringReference($string_literal.value)));
1133    };
1134
1135insn_format31i
1136  : //e.g. const v0, 123456
1137    ^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
1138    {
1139      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31i.text);
1140      short regA = parseRegister_byte($REGISTER.text);
1141
1142      int litB = $fixed_32bit_literal.value;
1143
1144      $method::methodBuilder.addInstruction(new BuilderInstruction31i(opcode, regA, litB));
1145    };
1146
1147insn_format31t
1148  : //e.g. fill-array-data v0, ArrayData:
1149    ^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER label_ref)
1150    {
1151      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31t.text);
1152
1153      short regA = parseRegister_byte($REGISTER.text);
1154
1155      $method::methodBuilder.addInstruction(new BuilderInstruction31t(opcode, regA, $label_ref.label));
1156    };
1157
1158insn_format32x
1159  : //e.g. move/16 v5678, v1234
1160    ^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER)
1161    {
1162      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT32x.text);
1163      int regA = parseRegister_short($registerA.text);
1164      int regB = parseRegister_short($registerB.text);
1165
1166      $method::methodBuilder.addInstruction(new BuilderInstruction32x(opcode, regA, regB));
1167    };
1168
1169insn_format35c_call_site
1170  : //e.g. invoke-custom {v0, v1}, call_site_name
1171    // OR invoke-custom {v0, v1}, {"doSomething", (LCustom;Ljava/lang/String;)Ljava/lang/String;, "just testing"}, BootstrapLinker;->normalLink(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
1172    ^(I_STATEMENT_FORMAT35c_CALL_SITE INSTRUCTION_FORMAT35c_CALL_SITE register_list call_site_reference)
1173    {
1174        Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT35c_CALL_SITE.text);
1175
1176        //this depends on the fact that register_list returns a byte[5]
1177        byte[] registers = $register_list.registers;
1178        byte registerCount = $register_list.registerCount;
1179
1180        ImmutableCallSiteReference callSiteReference = $call_site_reference.callSiteReference;
1181
1182        $method::methodBuilder.addInstruction(new BuilderInstruction35c(opcode, registerCount, registers[0],
1183                registers[1], registers[2], registers[3], registers[4], dexBuilder.internCallSite(callSiteReference)));
1184    };
1185
1186insn_format35c_method
1187  : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
1188    ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list method_reference)
1189    {
1190      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text);
1191
1192      //this depends on the fact that register_list returns a byte[5]
1193      byte[] registers = $register_list.registers;
1194      byte registerCount = $register_list.registerCount;
1195
1196      ImmutableMethodReference methodReference = $method_reference.methodReference;
1197
1198      $method::methodBuilder.addInstruction(new BuilderInstruction35c(opcode, registerCount, registers[0], registers[1],
1199              registers[2], registers[3], registers[4], dexBuilder.internMethodReference(methodReference)));
1200    };
1201
1202insn_format35c_type
1203  : //e.g. filled-new-array {v0,v1}, I
1204    ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor)
1205    {
1206      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT35c_TYPE.text);
1207
1208      //this depends on the fact that register_list returns a byte[5]
1209      byte[] registers = $register_list.registers;
1210      byte registerCount = $register_list.registerCount;
1211
1212      $method::methodBuilder.addInstruction(new BuilderInstruction35c(opcode, registerCount, registers[0], registers[1],
1213              registers[2], registers[3], registers[4], dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
1214    };
1215
1216insn_format3rc_call_site
1217  : //e.g. invoke-custom/range {v0 .. v1}, call_site_name
1218    // OR invoke-custom/range {v0 .. v1}, {"doSomething", (LCustom;Ljava/lang/String;)Ljava/lang/String;, "just testing"}, BootstrapLinker;->normalLink(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
1219    ^(I_STATEMENT_FORMAT3rc_CALL_SITE INSTRUCTION_FORMAT3rc_CALL_SITE register_range call_site_reference)
1220    {
1221        Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT3rc_CALL_SITE.text);
1222        int startRegister = $register_range.startRegister;
1223        int endRegister = $register_range.endRegister;
1224
1225        int registerCount = endRegister - startRegister + 1;
1226
1227        ImmutableCallSiteReference callSiteReference = $call_site_reference.callSiteReference;
1228
1229        $method::methodBuilder.addInstruction(new BuilderInstruction3rc(opcode, startRegister, registerCount,
1230                dexBuilder.internCallSite(callSiteReference)));
1231    };
1232
1233insn_format3rc_method
1234  : //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
1235    ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range method_reference)
1236    {
1237      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text);
1238      int startRegister = $register_range.startRegister;
1239      int endRegister = $register_range.endRegister;
1240
1241      int registerCount = endRegister-startRegister+1;
1242
1243      ImmutableMethodReference methodReference = $method_reference.methodReference;
1244
1245      $method::methodBuilder.addInstruction(new BuilderInstruction3rc(opcode, startRegister, registerCount,
1246              dexBuilder.internMethodReference(methodReference)));
1247    };
1248
1249insn_format3rc_type
1250  : //e.g. filled-new-array/range {v0..v6} I
1251    ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor)
1252    {
1253      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT3rc_TYPE.text);
1254      int startRegister = $register_range.startRegister;
1255      int endRegister = $register_range.endRegister;
1256
1257      int registerCount = endRegister-startRegister+1;
1258
1259      $method::methodBuilder.addInstruction(new BuilderInstruction3rc(opcode, startRegister, registerCount,
1260              dexBuilder.internTypeReference($nonvoid_type_descriptor.type)));
1261    };
1262
1263insn_format45cc_method
1264  : //e.g. invoke-polymorphic {v0, v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
1265    ^(I_STATEMENT_FORMAT45cc_METHOD INSTRUCTION_FORMAT45cc_METHOD register_list method_reference method_prototype)
1266    {
1267      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT45cc_METHOD.text);
1268
1269      //this depends on the fact that register_list returns a byte[5]
1270      byte[] registers = $register_list.registers;
1271      byte registerCount = $register_list.registerCount;
1272
1273      ImmutableMethodReference methodReference = $method_reference.methodReference;
1274
1275      $method::methodBuilder.addInstruction(new BuilderInstruction45cc(opcode, registerCount, registers[0], registers[1],
1276              registers[2], registers[3], registers[4],
1277              dexBuilder.internMethodReference(methodReference),
1278              dexBuilder.internMethodProtoReference($method_prototype.proto)));
1279    };
1280
1281insn_format4rcc_method
1282  : //e.g. invoke-polymorphic {v0..v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J
1283    ^(I_STATEMENT_FORMAT4rcc_METHOD INSTRUCTION_FORMAT4rcc_METHOD register_range method_reference method_prototype)
1284    {
1285      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT4rcc_METHOD.text);
1286      int startRegister = $register_range.startRegister;
1287      int endRegister = $register_range.endRegister;
1288
1289      int registerCount = endRegister-startRegister+1;
1290
1291      ImmutableMethodReference methodReference = $method_reference.methodReference;
1292
1293      $method::methodBuilder.addInstruction(new BuilderInstruction4rcc(opcode, startRegister, registerCount,
1294              dexBuilder.internMethodReference(methodReference),
1295              dexBuilder.internMethodProtoReference($method_prototype.proto)));
1296    };
1297
1298insn_format51l_type
1299  : //e.g. const-wide v0, 5000000000L
1300    ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal)
1301    {
1302      Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT51l.text);
1303      short regA = parseRegister_byte($REGISTER.text);
1304
1305      long litB = $fixed_64bit_literal.value;
1306
1307      $method::methodBuilder.addInstruction(new BuilderInstruction51l(opcode, regA, litB));
1308    };
1309
1310insn_array_data_directive
1311  : //e.g. .array-data 4 1000000 .end array-data
1312    ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements)
1313    {
1314      int elementWidth = $short_integral_literal.value;
1315      List<Number> elements = $array_elements.elements;
1316
1317      $method::methodBuilder.addInstruction(new BuilderArrayPayload(elementWidth, $array_elements.elements));
1318    };
1319
1320insn_packed_switch_directive
1321  :
1322    ^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) packed_switch_elements)
1323      {
1324        int startKey = $fixed_32bit_literal.value;
1325        $method::methodBuilder.addInstruction(new BuilderPackedSwitchPayload(startKey,
1326            $packed_switch_elements.elements));
1327      };
1328
1329insn_sparse_switch_directive
1330  :
1331    ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_elements)
1332    {
1333      $method::methodBuilder.addInstruction(new BuilderSparseSwitchPayload($sparse_switch_elements.elements));
1334    };
1335
1336array_descriptor returns [String type]
1337  : ARRAY_TYPE_PREFIX ( PRIMITIVE_TYPE { $type = $ARRAY_TYPE_PREFIX.text + $PRIMITIVE_TYPE.text; }
1338                      | CLASS_DESCRIPTOR { $type = $ARRAY_TYPE_PREFIX.text + $CLASS_DESCRIPTOR.text; });
1339
1340nonvoid_type_descriptor returns [String type]
1341  : (PRIMITIVE_TYPE { $type = $text; }
1342  | CLASS_DESCRIPTOR { $type = $text; }
1343  | array_descriptor { $type = $array_descriptor.type; })
1344  ;
1345
1346reference_type_descriptor returns [String type]
1347  : (CLASS_DESCRIPTOR { $type = $text; }
1348  | array_descriptor { $type = $array_descriptor.type; })
1349  ;
1350
1351type_descriptor returns [String type]
1352  : VOID_TYPE {$type = "V";}
1353  | nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;}
1354  ;
1355
1356short_integral_literal returns[short value]
1357  : long_literal
1358    {
1359      LiteralTools.checkShort($long_literal.value);
1360      $value = (short)$long_literal.value;
1361    }
1362  | integer_literal
1363    {
1364      LiteralTools.checkShort($integer_literal.value);
1365      $value = (short)$integer_literal.value;
1366    }
1367  | short_literal {$value = $short_literal.value;}
1368  | char_literal {$value = (short)$char_literal.value;}
1369  | byte_literal {$value = $byte_literal.value;};
1370
1371integral_literal returns[int value]
1372  : long_literal
1373    {
1374      LiteralTools.checkInt($long_literal.value);
1375      $value = (int)$long_literal.value;
1376    }
1377  | integer_literal {$value = $integer_literal.value;}
1378  | short_literal {$value = $short_literal.value;}
1379  | byte_literal {$value = $byte_literal.value;};
1380
1381
1382integer_literal returns[int value]
1383  : INTEGER_LITERAL { $value = LiteralTools.parseInt($INTEGER_LITERAL.text); };
1384
1385long_literal returns[long value]
1386  : LONG_LITERAL { $value = LiteralTools.parseLong($LONG_LITERAL.text); };
1387
1388short_literal returns[short value]
1389  : SHORT_LITERAL { $value = LiteralTools.parseShort($SHORT_LITERAL.text); };
1390
1391byte_literal returns[byte value]
1392  : BYTE_LITERAL { $value = LiteralTools.parseByte($BYTE_LITERAL.text); };
1393
1394float_literal returns[float value]
1395  : FLOAT_LITERAL { $value = LiteralTools.parseFloat($FLOAT_LITERAL.text); };
1396
1397double_literal returns[double value]
1398  : DOUBLE_LITERAL { $value = LiteralTools.parseDouble($DOUBLE_LITERAL.text); };
1399
1400char_literal returns[char value]
1401  : CHAR_LITERAL { $value = $CHAR_LITERAL.text.charAt(1); };
1402
1403string_literal returns[String value]
1404  : STRING_LITERAL
1405    {
1406      $value = $STRING_LITERAL.text;
1407      $value = $value.substring(1,$value.length()-1);
1408    };
1409
1410bool_literal returns[boolean value]
1411  : BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); };
1412
1413array_literal returns[List<EncodedValue> elements]
1414  : {$elements = Lists.newArrayList();}
1415    ^(I_ENCODED_ARRAY (literal {$elements.add($literal.encodedValue);})*);
1416
1417annotations returns[Set<Annotation> annotations]
1418  : {HashMap<String, Annotation> annotationMap = Maps.newHashMap();}
1419    ^(I_ANNOTATIONS (annotation
1420    {
1421        Annotation anno = $annotation.annotation;
1422        Annotation old = annotationMap.put(anno.getType(), anno);
1423        if (old != null) {
1424            throw new SemanticException(input, "Multiple annotations of type \%s", anno.getType());
1425        }
1426    })*)
1427    {
1428        $annotations = ImmutableSet.copyOf(annotationMap.values());
1429    };
1430
1431annotation returns[Annotation annotation]
1432  : ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation)
1433    {
1434      int visibility = AnnotationVisibility.getVisibility($ANNOTATION_VISIBILITY.text);
1435      $annotation = new ImmutableAnnotation(visibility, $subannotation.annotationType, $subannotation.elements);
1436    };
1437
1438annotation_element returns[AnnotationElement element]
1439  : ^(I_ANNOTATION_ELEMENT SIMPLE_NAME literal)
1440    {
1441      $element = new ImmutableAnnotationElement($SIMPLE_NAME.text, $literal.encodedValue);
1442    };
1443
1444subannotation returns[String annotationType, List<AnnotationElement> elements]
1445  : {ArrayList<AnnotationElement> elements = Lists.newArrayList();}
1446    ^(I_SUBANNOTATION
1447        CLASS_DESCRIPTOR
1448        (annotation_element
1449        {
1450           elements.add($annotation_element.element);
1451        })*
1452     )
1453    {
1454      $annotationType = $CLASS_DESCRIPTOR.text;
1455      $elements = elements;
1456    };
1457
1458field_literal returns[ImmutableFieldReference value]
1459  : ^(I_ENCODED_FIELD field_reference)
1460    {
1461      $value = $field_reference.fieldReference;
1462    };
1463
1464method_literal returns[ImmutableMethodReference value]
1465  : ^(I_ENCODED_METHOD method_reference)
1466    {
1467      $value = $method_reference.methodReference;
1468    };
1469
1470enum_literal returns[ImmutableFieldReference value]
1471  : ^(I_ENCODED_ENUM field_reference)
1472    {
1473      $value = $field_reference.fieldReference;
1474    };
1475