private void verifyReturnVoid(AnalyzedInstruction analyzedInstruction) { TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType(); if (returnType.getTypeDescriptor().charAt(0) != 'V') { //TODO: could add which return-* variation should be used instead throw new ValidationException("Cannot use return-void with a non-void return type (" + returnType.getTypeDescriptor() + ")"); } }
validCategories); TypeIdItem returnType = encodedMethod.method.getPrototype().getReturnType(); if (returnType.getTypeDescriptor().charAt(0) == 'V') { throw new ValidationException("Cannot use return with a void return type. Use return-void instead");
private void verifyMoveResult(AnalyzedInstruction analyzedInstruction, EnumSet<RegisterType.Category> allowedCategories) { if (analyzedInstruction.instructionIndex == 0) { throw new ValidationException(analyzedInstruction.instruction.opcode.name + " cannot be the first " + "instruction in a method. It must occur after an invoke-*/fill-new-array instruction"); } AnalyzedInstruction previousInstruction = instructions.valueAt(analyzedInstruction.instructionIndex-1); if (!previousInstruction.instruction.opcode.setsResult()) { throw new ValidationException(analyzedInstruction.instruction.opcode.name + " must occur after an " + "invoke-*/fill-new-array instruction"); } //TODO: does dalvik allow a move-result after an invoke with a void return type? RegisterType resultRegisterType; InstructionWithReference invokeInstruction = (InstructionWithReference)previousInstruction.getInstruction(); Item item = invokeInstruction.getReferencedItem(); if (item instanceof MethodIdItem) { resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem( ((MethodIdItem)item).getPrototype().getReturnType()); } else { assert item instanceof TypeIdItem; resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); } if (!allowedCategories.contains(resultRegisterType.category)) { throw new ValidationException(String.format("Wrong move-result* instruction for return value %s", resultRegisterType.toString())); } }
private void analyzeMoveResult(AnalyzedInstruction analyzedInstruction) { AnalyzedInstruction previousInstruction = instructions.valueAt(analyzedInstruction.instructionIndex-1); if (!previousInstruction.instruction.opcode.setsResult()) { throw new ValidationException(analyzedInstruction.instruction.opcode.name + " must occur after an " + "invoke-*/fill-new-array instruction"); } RegisterType resultRegisterType; InstructionWithReference invokeInstruction = (InstructionWithReference)previousInstruction.instruction; Item item = invokeInstruction.getReferencedItem(); if (item.getItemType() == ItemType.TYPE_METHOD_ID_ITEM) { resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem( ((MethodIdItem)item).getPrototype().getReturnType()); } else { assert item.getItemType() == ItemType.TYPE_TYPE_ID_ITEM; resultRegisterType = RegisterType.getRegisterTypeForTypeIdItem((TypeIdItem)item); } setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, resultRegisterType); }