Element dexInstruction= null;
String opname= instruction.getOpcode().getName();
if (opname.equals("instance-of") || opname.equals("const-class"))
{
CstInsn isaInsn= (CstInsn) instruction;
addReference(referencedTypes, isaInsn.getConstant().toHuman(), ReferenceKind.USAGE);
}
RegisterSpecList registers= instruction.getRegisters();
for (int i= 0; i < registers.size(); ++i)
{
RegisterSpec register= registers.get(i);
String descriptor= register.getType().getDescriptor();
String registerType= register.getType().toHuman();
// Sometimes a register type name starts with some info about the
// register. We need to cut this out.
if (descriptor.startsWith("N"))
{
addReference(referencedTypes, registerType.substring(registerType.indexOf('L') + 1), ReferenceKind.USAGE);
}
else
{
addReference(referencedTypes, registerType, ReferenceKind.USAGE);
}
}
if (instruction instanceof CodeAddress)
{
// We put debug information about source code positions into the
// code so that we can control the debugger.
SourcePosition sourcePosition= instruction.getPosition();
CstUtf8 sourceFile= sourcePosition.getSourceFile();
int sourceLine= sourcePosition.getLine();
if (sourceFile != null && !sourceLinesAlreadyPut.contains(sourceLine))
{
dexInstruction= new Element("source-position", NS_XMLVM);
dexInstruction.setAttribute("file", sourceFile.toHuman());
dexInstruction.setAttribute("line", String.valueOf(sourceLine));
sourceLinesAlreadyPut.add(sourceLine);
}
}
else if (instruction instanceof LocalSnapshot)
{
// Ignore.
}
else if (instruction instanceof OddSpacer)
{
// Ignore NOPs.
}
else if (instruction instanceof SwitchData)
{
// Ignore here because we already processes these and they were
// given to this method as an argument.
}
else if (instruction instanceof LocalStart)
{
// As we extract the locals information up-front we don't need to
// handle local-start.
}
else if (instruction instanceof ArrayData)
{
// Ignore here because we already processed these and they were
// given to this method as an argument.
}
else if (instruction instanceof SimpleInsn)
{
SimpleInsn simpleInsn= (SimpleInsn) instruction;
String instructionName= simpleInsn.getOpcode().getName();
// If this is a move-result instruction, we don't add it
// explicitly, but instead add the result register to the previous
// invoke instruction's return.
if (instructionName.startsWith("move-result"))
{
// Sanity Check
if (simpleInsn.getRegisters().size() != 1)
{
Log.error(TAG, "DEXmlvmOutputProcess: Register Size doesn't fit 'move-result'.");
System.exit(-1);
}
Element moveInstruction= new Element("move-result", NS_DEX);
addRegistersAsAttributes(registers, moveInstruction);
lastDexInstruction.addContent(moveInstruction);
}
else
{
dexInstruction= new Element(sanitizeInstructionName(instructionName), NS_DEX);
addRegistersAsAttributes(registers, dexInstruction);
// For simple instructions with only one register, we also add
// the type of the register. This includes the return
// instructions.
if (registers.size() == 1)
{
String classType= registers.get(0).getType().toHuman();
dexInstruction.setAttribute("class-type", classType);
// Mark throw instruction for a red type exception with
// isRedType="true"
if (instructionName.startsWith("throw"))
{
if (isRedType(classType))
{
dexInstruction.setAttribute("isRedType", "true");
}
}
}
}
}
else if (instruction instanceof CstInsn)
{
CstInsn cstInsn= (CstInsn) instruction;
if (isInvokeInstruction(cstInsn))
{
dexInstruction= processInvokeInstruction(cstInsn, referencedTypes);
}
else
{
dexInstruction= new Element(sanitizeInstructionName(cstInsn.getOpcode().getName()), NS_DEX);
Constant constant= cstInsn.getConstant();
// TODO hack
String type= constant.typeName();
String name= "kind";
if (!type.equals("field") && !type.equals("known-null") && !type.equals("type") && !type.equals("string"))
{
name= "type";
}
dexInstruction.setAttribute(name, constant.typeName());
if (constant instanceof CstMemberRef)
{
CstMemberRef memberRef= (CstMemberRef) constant;
String definingClassType= memberRef.getDefiningClass().getClassType().toHuman();
dexInstruction.setAttribute("class-type", definingClassType);
addReference(referencedTypes, definingClassType, ReferenceKind.USAGE);
CstNat nameAndType= memberRef.getNat();
String memberType= nameAndType.getFieldType().getType().toHuman();
dexInstruction.setAttribute("member-type", memberType);
addReference(referencedTypes, memberType, ReferenceKind.USAGE);
String memberName= nameAndType.getName().toHuman();
dexInstruction.setAttribute("member-name", memberName);
// if this is a member access to a red class, we need to
// eliminate it.
if (isRedType(definingClassType))
{
// Just accessing the memberType does not require to
// initialize its class.
// Therefore we can relax the rule of issuing a red
// class exception.
dexInstruction= createAssertElement(definingClassType + "," + memberType, memberName);
}
else if (isRedType(memberType))
{
// If the member-type is a red class replace it with a
// generic RedTypeMarker
dexInstruction.setAttribute("member-type", "org.xmlvm.runtime.RedTypeMarker");
}
}
else if (constant instanceof CstString)
{
CstString cstString= (CstString) constant;
String value= cstString.getString().getString();
encodeString(dexInstruction, value);
}
else
{
// These are CstInsn instructions that we need to remove, if
// their constant is a red type.
List<String> instructionsToCheck= Arrays.asList(new String[] { "new-instance", "instance-of", "check-cast", "const-class", "new-array" });
if (instructionsToCheck.contains(opname) && isRedType(constant.toHuman()))
{
dexInstruction= createAssertElement(constant.toHuman(), opname);
}
else
{
dexInstruction.setAttribute("value", constant.toHuman());
}
}
if (cstInsn.getOpcode().getName().startsWith("filled-new-array"))
{
addRegistersAsChildren(cstInsn.getRegisters(), dexInstruction);
}
else
{
addRegistersAsAttributes(cstInsn.getRegisters(), dexInstruction);
}
}
}
else if (instruction instanceof TargetInsn)
{