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