- Added a new "p0" style register reference, where p0 indicates the first parameter register, p1 the 2nd parameter register and so forth. This makes it less annoying when you are writing a method and have to add more registers, which would push the parameter registers back.

- Updated the the tests and examples with the new register format, where appropriate

git-svn-id: https://smali.googlecode.com/svn/trunk@89 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2009-06-04 06:44:10 +00:00
parent 468e5d0d1b
commit 5dc3a8d75a
6 changed files with 108 additions and 89 deletions

View File

@ -27,7 +27,7 @@
.method private constructor <init>(Ljava/lang/String;I)V .method private constructor <init>(Ljava/lang/String;I)V
.registers 3 .registers 3
invoke-direct {v0, v1, v2}, Ljava/lang/Enum;-><init>(Ljava/lang/String;I)V invoke-direct {p0, p1, p2}, Ljava/lang/Enum;-><init>(Ljava/lang/String;I)V
return-void return-void
.end method .end method
@ -35,7 +35,7 @@
.registers 2 .registers 2
const-class v0, LEnum; const-class v0, LEnum;
invoke-static {v0, v1}, Ljava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; invoke-static {v0, p0}, Ljava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
move-result-object v1 move-result-object v1
check-cast v1, LEnum; check-cast v1, LEnum;
return-object v1 return-object v1

View File

@ -50,14 +50,14 @@
.method private constructor <init>(Ljava/lang/String;I)V .method private constructor <init>(Ljava/lang/String;I)V
.registers 3 .registers 3
invoke-direct {v0, v1, v2}, Ljava/lang/Enum;-><init>(Ljava/lang/String;I)V invoke-direct {p0, p1, p2}, Ljava/lang/Enum;-><init>(Ljava/lang/String;I)V
return-void return-void
.end method .end method
.method public static valueof(Ljava/lang/String;)LEnum; .method public static valueof(Ljava/lang/String;)LEnum;
.registers 2 .registers 2
const-class v0, LEnum; const-class v0, LEnum;
invoke-static {v0, v1}, Ljava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; invoke-static {v0, p0}, Ljava/lang/Enum;->valueOf(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
move-result-object v1 move-result-object v1
check-cast v1, LEnum; check-cast v1, LEnum;
return-object v1 return-object v1

View File

@ -641,7 +641,7 @@ fragment EPILOGUE_DIRECTIVE
fragment REGISTER_EMIT fragment REGISTER_EMIT
: REGISTER {emit($REGISTER, REGISTER);}; : REGISTER {emit($REGISTER, REGISTER);};
fragment REGISTER fragment REGISTER
: 'v' ('0'..'9')+; : ('v' | 'p') ('0'..'9')+;
fragment REGISTER_LIST_EMITCHILDREN fragment REGISTER_LIST_EMITCHILDREN
: OPEN_BRACKET_EMIT : OPEN_BRACKET_EMIT

View File

@ -50,32 +50,41 @@ import org.JesusFreke.dexlib.code.Format.*;
public ClassDefItem classDefItem; public ClassDefItem classDefItem;
public ClassDataItem classDataItem; public ClassDataItem classDataItem;
private static byte parseRegister_nibble(String register) { private static byte parseRegister_nibble(String register, int totalMethodRegisters, int methodParameterRegisters) {
//register should be in the format "v12" //register should be in the format "v12"
byte val = Byte.parseByte(register.substring(1)); int val = Byte.parseByte(register.substring(1));
if (register.charAt(0) == 'p') {
val = totalMethodRegisters - methodParameterRegisters + val;
}
if (val >= 2<<4) { if (val >= 2<<4) {
//TODO: throw correct exception type //TODO: throw correct exception type
throw new RuntimeException("The maximum allowed register in this context is list of registers is v15"); throw new RuntimeException("The maximum allowed register in this context is list of registers is v15");
} }
//the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0; //the parser wouldn't accept a negative register, i.e. v-1, so we don't have to check for val<0;
return val; return (byte)val;
} }
//return a short, because java's byte is signed //return a short, because java's byte is signed
private static short parseRegister_byte(String register) { private static short parseRegister_byte(String register, int totalMethodRegisters, int methodParameterRegisters) {
//register should be in the format "v123" //register should be in the format "v123"
short val = Short.parseShort(register.substring(1)); int val = Short.parseShort(register.substring(1));
if (register.charAt(0) == 'p') {
val = totalMethodRegisters - methodParameterRegisters + val;
}
if (val >= 2<<8) { if (val >= 2<<8) {
//TODO: throw correct exception type //TODO: throw correct exception type
throw new RuntimeException("The maximum allowed register in this context is v255"); throw new RuntimeException("The maximum allowed register in this context is v255");
} }
return val; return (short)val;
} }
//return an int because java's short is signed //return an int because java's short is signed
private static int parseRegister_short(String register) { private static int parseRegister_short(String register, int totalMethodRegisters, int methodParameterRegisters) {
//register should be in the format "v12345" //register should be in the format "v12345"
int val = Integer.parseInt(register.substring(1)); int val = Integer.parseInt(register.substring(1));
if (register.charAt(0) == 'p') {
val = totalMethodRegisters - methodParameterRegisters + val;
}
if (val >= 2<<16) { if (val >= 2<<16) {
//TODO: throw correct exception type //TODO: throw correct exception type
throw new RuntimeException("The maximum allowed register in this context is v65535"); throw new RuntimeException("The maximum allowed register in this context is v65535");
@ -342,6 +351,14 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
int currentAddress; int currentAddress;
DebugInfoBuilder debugInfo; DebugInfoBuilder debugInfo;
} }
@init
{
MethodIdItem methodIdItem = null;
int totalMethodRegisters = 0;
int methodParameterRegisters = 0;
int accessFlags = 0;
boolean isStatic = false;
}
: { : {
$method::labels = new HashMap<String, Integer>(); $method::labels = new HashMap<String, Integer>();
$method::tryList = new TryListBuilder(); $method::tryList = new TryListBuilder();
@ -351,20 +368,24 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
^( I_METHOD ^( I_METHOD
method_name_and_prototype method_name_and_prototype
access_list access_list
{
methodIdItem = $method_name_and_prototype.methodIdItem;
accessFlags = $access_list.value;
isStatic = (accessFlags & AccessFlags.STATIC) != 0;
methodParameterRegisters = methodIdItem.getParameterRegisterCount(isStatic);
}
registers_directive registers_directive
{
totalMethodRegisters = $registers_directive.registers;
}
labels labels
statements statements[totalMethodRegisters, methodParameterRegisters]
catches catches
parameters parameters
ordered_debug_directives ordered_debug_directives[totalMethodRegisters, methodParameterRegisters]
annotations annotations
) )
{ {
MethodIdItem methodIdItem = $method_name_and_prototype.methodIdItem;
int access = $access_list.value;
boolean isStatic = (access & AccessFlags.STATIC) != 0;
int registers = $registers_directive.registers;
ArrayList<Instruction> instructions = $statements.instructions; ArrayList<Instruction> instructions = $statements.instructions;
Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> temp = $method::tryList.encodeTries(dexFile); Pair<List<CodeItem.TryItem>, List<CodeItem.EncodedCatchHandler>> temp = $method::tryList.encodeTries(dexFile);
@ -376,7 +397,7 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
CodeItem codeItem; CodeItem codeItem;
if (registers == 0 && if (totalMethodRegisters == 0 &&
instructions.size() == 0 && instructions.size() == 0 &&
$method::labels.size()== 0 && $method::labels.size()== 0 &&
(tries == null || tries.size() == 0) && (tries == null || tries.size() == 0) &&
@ -386,12 +407,10 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
codeItem = null; codeItem = null;
} else { } else {
int minRegisters = methodIdItem.getParameterRegisterCount((access & AccessFlags.STATIC) != 0); if (totalMethodRegisters < methodParameterRegisters) {
if (registers < minRegisters) {
//TODO: throw the correct exception type //TODO: throw the correct exception type
throw new RuntimeException( "This method requires at least " + throw new RuntimeException( "This method requires at least " +
Integer.toString(minRegisters) + Integer.toString(methodParameterRegisters) +
" registers, for the method parameters"); " registers, for the method parameters");
} }
@ -404,7 +423,7 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
} }
codeItem = new CodeItem(dexFile, codeItem = new CodeItem(dexFile,
registers, totalMethodRegisters,
methodIdItem.getParameterRegisterCount(isStatic), methodIdItem.getParameterRegisterCount(isStatic),
instructions, instructions,
debugInfoItem, debugInfoItem,
@ -412,7 +431,7 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod,
handlers); handlers);
} }
$encodedMethod = new ClassDataItem.EncodedMethod(dexFile, methodIdItem, access, codeItem); $encodedMethod = new ClassDataItem.EncodedMethod(dexFile, methodIdItem, accessFlags, codeItem);
if ($annotations.annotationSetItem != null) { if ($annotations.annotationSetItem != null) {
$methodAnnotationSet = new AnnotationDirectoryItem.MethodAnnotation(dexFile, methodIdItem, $annotations.annotationSetItem); $methodAnnotationSet = new AnnotationDirectoryItem.MethodAnnotation(dexFile, methodIdItem, $annotations.annotationSetItem);
@ -547,11 +566,11 @@ parameter returns[AnnotationSetItem parameterAnnotationSet]
annotations {$parameterAnnotationSet = $annotations.annotationSetItem;} annotations {$parameterAnnotationSet = $annotations.annotationSetItem;}
); );
ordered_debug_directives ordered_debug_directives[int totalMethodRegisters, int methodParameterRegisters]
: ^(I_ORDERED_DEBUG_DIRECTIVES ( line : ^(I_ORDERED_DEBUG_DIRECTIVES ( line
| local | local[$totalMethodRegisters, $methodParameterRegisters]
| end_local | end_local[$totalMethodRegisters, $methodParameterRegisters]
| restart_local | restart_local[$totalMethodRegisters, $methodParameterRegisters]
| prologue | prologue
| epilogue | epilogue
| source | source
@ -563,10 +582,10 @@ line
$method::debugInfo.addLine($address.address, $integral_literal.value); $method::debugInfo.addLine($address.address, $integral_literal.value);
}; };
local local[int totalMethodRegisters, int methodParameterRegisters]
: ^(I_LOCAL REGISTER SIMPLE_NAME nonvoid_type_descriptor string_literal? address) : ^(I_LOCAL REGISTER SIMPLE_NAME nonvoid_type_descriptor string_literal? address)
{ {
int registerNumber = parseRegister_short($REGISTER.text); int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
if ($string_literal.value != null) { if ($string_literal.value != null) {
$method::debugInfo.addLocalExtended($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor(), $string_literal.value); $method::debugInfo.addLocalExtended($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor(), $string_literal.value);
@ -575,18 +594,18 @@ local
} }
}; };
end_local end_local[int totalMethodRegisters, int methodParameterRegisters]
: ^(I_END_LOCAL REGISTER address) : ^(I_END_LOCAL REGISTER address)
{ {
int registerNumber = parseRegister_short($REGISTER.text); int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
$method::debugInfo.addEndLocal($address.address, registerNumber); $method::debugInfo.addEndLocal($address.address, registerNumber);
}; };
restart_local restart_local[int totalMethodRegisters, int methodParameterRegisters]
: ^(I_RESTART_LOCAL REGISTER address) : ^(I_RESTART_LOCAL REGISTER address)
{ {
int registerNumber = parseRegister_short($REGISTER.text); int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
$method::debugInfo.addRestartLocal($address.address, registerNumber); $method::debugInfo.addRestartLocal($address.address, registerNumber);
}; };
@ -609,12 +628,12 @@ source
$method::debugInfo.addSetFile($address.address, $string_literal.value); $method::debugInfo.addSetFile($address.address, $string_literal.value);
}; };
statements returns[ArrayList<Instruction> instructions] statements[int totalMethodRegisters, int methodParameterRegisters] returns[ArrayList<Instruction> instructions]
@init @init
{ {
$instructions = new ArrayList<Instruction>(); $instructions = new ArrayList<Instruction>();
} }
: ^(I_STATEMENTS (instruction : ^(I_STATEMENTS (instruction[$totalMethodRegisters, $methodParameterRegisters]
{ {
$instructions.add($instruction.instruction); $instructions.add($instruction.instruction);
$method::currentAddress += $instruction.instruction.getBytes().length/2; $method::currentAddress += $instruction.instruction.getBytes().length/2;
@ -658,7 +677,7 @@ offset_or_label returns[int offsetValue]
: offset {$offsetValue = $offset.offsetValue;} : offset {$offsetValue = $offset.offsetValue;}
| label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;}; | label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;};
instruction returns[Instruction instruction] instruction[int totalMethodRegisters, int methodParameterRegisters] returns[Instruction instruction]
: //e.g. goto endloop: : //e.g. goto endloop:
^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label) ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label)
{ {
@ -683,7 +702,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal) ^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11n.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11n.text);
byte regA = parseRegister_nibble($REGISTER.text); byte regA = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
short litB = $short_integral_literal.value; short litB = $short_integral_literal.value;
literalTools.checkNibble(litB); literalTools.checkNibble(litB);
@ -694,7 +713,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER) ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
$instruction = Format11x.Format.make(dexFile, opcode.value, regA); $instruction = Format11x.Format.make(dexFile, opcode.value, regA);
} }
@ -702,8 +721,8 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER) ^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT12x.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT12x.text);
byte regA = parseRegister_nibble($registerA.text); byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
byte regB = parseRegister_nibble($registerB.text); byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
$instruction = Format12x.Format.make(dexFile, opcode.value, regA, regB); $instruction = Format12x.Format.make(dexFile, opcode.value, regA, regB);
} }
@ -725,7 +744,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT21c_FIELD INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field) ^(I_STATEMENT_FORMAT21c_FIELD INSTRUCTION_FORMAT21c_FIELD REGISTER fully_qualified_field)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_FIELD.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_FIELD.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
@ -735,7 +754,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal) ^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
StringIdItem stringIdItem = new StringIdItem(dexFile, $string_literal.value); StringIdItem stringIdItem = new StringIdItem(dexFile, $string_literal.value);
@ -745,7 +764,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor) ^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
TypeIdItem typeIdItem = $reference_type_descriptor.type; TypeIdItem typeIdItem = $reference_type_descriptor.type;
@ -755,7 +774,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal) ^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21h.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21h.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
short litB = $short_integral_literal.value; short litB = $short_integral_literal.value;
@ -765,7 +784,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal) ^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21s.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21s.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
short litB = $short_integral_literal.value; short litB = $short_integral_literal.value;
@ -775,7 +794,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label) ^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21t.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21t.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
int addressOffset = $offset_or_label.offsetValue; int addressOffset = $offset_or_label.offsetValue;
@ -790,8 +809,8 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal) ^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22b.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22b.text);
short regA = parseRegister_byte($registerA.text); short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
short regB = parseRegister_byte($registerB.text); short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
short litC = $short_integral_literal.value; short litC = $short_integral_literal.value;
literalTools.checkByte(litC); literalTools.checkByte(litC);
@ -802,8 +821,8 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT22c_FIELD INSTRUCTION_FORMAT22c_FIELD registerA=REGISTER registerB=REGISTER fully_qualified_field) ^(I_STATEMENT_FORMAT22c_FIELD INSTRUCTION_FORMAT22c_FIELD registerA=REGISTER registerB=REGISTER fully_qualified_field)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_FIELD.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_FIELD.text);
byte regA = parseRegister_nibble($registerA.text); byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
byte regB = parseRegister_nibble($registerB.text); byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem;
@ -813,8 +832,8 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor) ^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text);
byte regA = parseRegister_nibble($registerA.text); byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
byte regB = parseRegister_nibble($registerB.text); byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; TypeIdItem typeIdItem = $nonvoid_type_descriptor.type;
@ -824,8 +843,8 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal) ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22s.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22s.text);
byte regA = parseRegister_nibble($registerA.text); byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
byte regB = parseRegister_nibble($registerB.text); byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
short litC = $short_integral_literal.value; short litC = $short_integral_literal.value;
@ -835,8 +854,8 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label) ^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22t.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22t.text);
byte regA = parseRegister_nibble($registerA.text); byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
byte regB = parseRegister_nibble($registerB.text); byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
int addressOffset = $offset_or_label.offsetValue; int addressOffset = $offset_or_label.offsetValue;
@ -851,8 +870,8 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER) ^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22x.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22x.text);
short regA = parseRegister_byte($registerA.text); short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
int regB = parseRegister_short($registerB.text); int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
$instruction = Format22x.Format.make(dexFile, opcode.value, regA, regB); $instruction = Format22x.Format.make(dexFile, opcode.value, regA, regB);
} }
@ -860,9 +879,9 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER) ^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT23x.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT23x.text);
short regA = parseRegister_byte($registerA.text); short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
short regB = parseRegister_byte($registerB.text); short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
short regC = parseRegister_byte($registerC.text); short regC = parseRegister_byte($registerC.text, $totalMethodRegisters, $methodParameterRegisters);
$instruction = Format23x.Format.make(dexFile, opcode.value, regA, regB, regC); $instruction = Format23x.Format.make(dexFile, opcode.value, regA, regB, regC);
} }
@ -879,7 +898,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal) ^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31c.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31c.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
StringIdItem stringIdItem = new StringIdItem(dexFile, $string_literal.value); StringIdItem stringIdItem = new StringIdItem(dexFile, $string_literal.value);
@ -889,7 +908,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal) ^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31i.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31i.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
int litB = $fixed_32bit_literal.value; int litB = $fixed_32bit_literal.value;
@ -900,7 +919,7 @@ instruction returns[Instruction instruction]
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31t.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31t.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
int addressOffset = $offset_or_label.offsetValue; int addressOffset = $offset_or_label.offsetValue;
if (($method::currentAddress + addressOffset) \% 2 != 0) { if (($method::currentAddress + addressOffset) \% 2 != 0) {
@ -913,13 +932,13 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER) ^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT32x.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT32x.text);
int regA = parseRegister_short($registerA.text); int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters);
int regB = parseRegister_short($registerB.text); int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters);
$instruction = Format32x.Format.make(dexFile, opcode.value, regA, regB); $instruction = Format32x.Format.make(dexFile, opcode.value, regA, regB);
} }
| //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V | //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method) ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text);
@ -932,7 +951,7 @@ instruction returns[Instruction instruction]
$instruction = Format35c.Format.make(dexFile, opcode.value, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem); $instruction = Format35c.Format.make(dexFile, opcode.value, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem);
} }
| //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; | //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range fully_qualified_method) ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text);
int startRegister = $register_range.startRegister; int startRegister = $register_range.startRegister;
@ -957,7 +976,7 @@ instruction returns[Instruction instruction]
^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal) ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal)
{ {
Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT51l.text); Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT51l.text);
short regA = parseRegister_byte($REGISTER.text); short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
long litB = $fixed_64bit_literal.value; long litB = $fixed_64bit_literal.value;
@ -991,7 +1010,7 @@ instruction returns[Instruction instruction]
; ;
register_list returns[byte[\] registers, byte registerCount] register_list[int totalMethodRegisters, int methodParameterRegisters] returns[byte[\] registers, byte registerCount]
@init @init
{ {
$registers = new byte[5]; $registers = new byte[5];
@ -1004,17 +1023,17 @@ register_list returns[byte[\] registers, byte registerCount]
//TODO: throw the correct type of exception //TODO: throw the correct type of exception
throw new RuntimeException("A list of registers can only have a maximum of 5 registers. Use the <op>/range alternate opcode instead."); throw new RuntimeException("A list of registers can only have a maximum of 5 registers. Use the <op>/range alternate opcode instead.");
} }
$registers[$registerCount++] = parseRegister_nibble($REGISTER.text); $registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters);
})*); })*);
register_range returns[int startRegister, int endRegister] register_range[int totalMethodRegisters, int methodParameterRegisters] returns[int startRegister, int endRegister]
: ^(I_REGISTER_RANGE startReg=REGISTER endReg=REGISTER?) : ^(I_REGISTER_RANGE startReg=REGISTER endReg=REGISTER?)
{ {
$startRegister = parseRegister_short($startReg.text); $startRegister = parseRegister_short($startReg.text, $totalMethodRegisters, $methodParameterRegisters);
if ($endReg == null) { if ($endReg == null) {
$endRegister = $startRegister; $endRegister = $startRegister;
} else { } else {
$endRegister = parseRegister_short($endReg.text); $endRegister = parseRegister_short($endReg.text, $totalMethodRegisters, $methodParameterRegisters);
} }
} }
; ;

View File

@ -6,16 +6,16 @@
.method public constructor <init>()V .method public constructor <init>()V
.registers 4 .registers 4
invoke-direct {v3}, Ljava/lang/Object;-><init>()V invoke-direct {p0}, Ljava/lang/Object;-><init>()V
const-string v0, "publicStringFieldValue" const-string v0, "publicStringFieldValue"
iput-object v0, v3, LFieldTest;->publicStringField:Ljava/lang/String; iput-object v0, p0, LFieldTest;->publicStringField:Ljava/lang/String;
const v0, 23 const v0, 23
iput v0, v3, LFieldTest;->publicIntegerField:I iput v0, p0, LFieldTest;->publicIntegerField:I
const-string v0, "publicObjectFieldValue" const-string v0, "publicObjectFieldValue"
iput-object v0, v3, LFieldTest;->publicObjectField:Ljava/lang/Object; iput-object v0, p0, LFieldTest;->publicObjectField:Ljava/lang/Object;
const/4 v0, 3 const/4 v0, 3
new-array v0, v0, [Ljava/lang/String; new-array v0, v0, [Ljava/lang/String;
@ -32,10 +32,10 @@
const/4 v2, 2 const/4 v2, 2
aput-object v1, v0, v2 aput-object v1, v0, v2
iput-object v0, v3, LFieldTest;->publicStringArrayField:[Ljava/lang/String; iput-object v0, p0, LFieldTest;->publicStringArrayField:[Ljava/lang/String;
const-string v0, "privateStringFieldValue" const-string v0, "privateStringFieldValue"
iput-object v0, v3, LFieldTest;->privateStringField:Ljava/lang/String; iput-object v0, p0, LFieldTest;->privateStringField:Ljava/lang/String;
const-string v0, "publicStaticStringFieldValue" const-string v0, "publicStaticStringFieldValue"
sput-object v0, LFieldTest;->publicStaticStringField:Ljava/lang/String; sput-object v0, LFieldTest;->publicStaticStringField:Ljava/lang/String;
@ -61,7 +61,7 @@
.end annotation .end annotation
.line 1 .line 1
iget-object v0, v4, LFieldTest;->publicStringField:Ljava/lang/String; iget-object v0, p0, LFieldTest;->publicStringField:Ljava/lang/String;
const-string v1, "publicStringFieldValue" const-string v1, "publicStringFieldValue"
invoke-static {v0, v1}, Lorg/junit/Assert;->assertEquals(Ljava/lang/Object;Ljava/lang/Object;)V invoke-static {v0, v1}, Lorg/junit/Assert;->assertEquals(Ljava/lang/Object;Ljava/lang/Object;)V
@ -72,7 +72,7 @@
invoke-static {v0, v1, v2, v3}, Lorg/junit/Assert;->assertEquals(JJ)V invoke-static {v0, v1, v2, v3}, Lorg/junit/Assert;->assertEquals(JJ)V
.line 3 .line 3
iget-object v0, v4, LFieldTest;->publicObjectField:Ljava/lang/Object; iget-object v0, p0, LFieldTest;->publicObjectField:Ljava/lang/Object;
const-string v1, "publicObjectFieldValue" const-string v1, "publicObjectFieldValue"
invoke-static {v0, v1}, Lorg/junit/Assert;->assertEquals(Ljava/lang/Object;Ljava/lang/Object;)V invoke-static {v0, v1}, Lorg/junit/Assert;->assertEquals(Ljava/lang/Object;Ljava/lang/Object;)V
@ -92,11 +92,11 @@
const/4 v2, 2 const/4 v2, 2
aput-object v1, v0, v2 aput-object v1, v0, v2
iget-object v1, v4, LFieldTest;->publicStringArrayField:[Ljava/lang/String; iget-object v1, p0, LFieldTest;->publicStringArrayField:[Ljava/lang/String;
invoke-static {v0, v1}, Lorg/junit/Assert;->assertEquals([Ljava/lang/Object;[Ljava/lang/Object;)V invoke-static {v0, v1}, Lorg/junit/Assert;->assertEquals([Ljava/lang/Object;[Ljava/lang/Object;)V
.line 5 .line 5
iget-object v0, v4, LFieldTest;->privateStringField:Ljava/lang/String; iget-object v0, p0, LFieldTest;->privateStringField:Ljava/lang/String;
const-string v1, "privateStringFieldValue" const-string v1, "privateStringFieldValue"
invoke-static {v0, v1}, Lorg/junit/Assert;->assertEquals(Ljava/lang/Object;Ljava/lang/Object;)V invoke-static {v0, v1}, Lorg/junit/Assert;->assertEquals(Ljava/lang/Object;Ljava/lang/Object;)V

View File

@ -4,7 +4,7 @@
.method public constructor <init>()V .method public constructor <init>()V
.registers 1 .registers 1
invoke-direct {v0}, Ljava/lang/Object;-><init>()V invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void return-void
.end method .end method