use of soot.SootMethod in project robovm by robovm.
the class ObjCBlockPlugin method beforeClass.
@Override
public void beforeClass(Config config, Clazz clazz, ModuleBuilder moduleBuilder) throws IOException {
init();
SootClass sootClass = clazz.getSootClass();
if (!sootClass.isInterface()) {
Map<String, Integer> blockTypeIds = new HashMap<>();
for (SootMethod method : sootClass.getMethods()) {
if (method.isNative() && hasBridgeAnnotation(method) || hasCallbackAnnotation(method)) {
int[] indexes = getBlockParameterIndexes(method);
if (indexes != null || hasAnnotation(method, BLOCK)) {
transformMethod(config, clazz, method, indexes, blockTypeIds);
}
}
}
}
}
use of soot.SootMethod in project robovm by robovm.
the class ObjCBlockPlugin method transformMethod.
private void transformMethod(Config config, Clazz clazz, SootMethod blockMethod, int[] blockParamIndexes, Map<String, Integer> blockTypeIds) throws IOException {
SootMethodType blockMethodType = new SootMethodType(blockMethod);
if (blockParamIndexes != null) {
Type[] genericParameterTypes = blockMethodType.getGenericParameterTypes();
for (int i = 0; i < blockParamIndexes.length; i++) {
int idx = blockParamIndexes[i];
if (idx == -1) {
break;
}
SootMethod targetMethod = getBlockTargetMethod(blockMethod, idx);
Type[] actualGenericTypes = resolveTargetMethodSignature(blockMethod, targetMethod, genericParameterTypes[idx]);
soot.Type[] actualRawTypes = toRawTypes(actualGenericTypes);
soot.Type[] unboxedTypes = unboxTypes(actualRawTypes);
String[][] targetMethodAnnotations = parseTargetMethodAnnotations(targetMethod, readStringElem(getParameterAnnotation(blockMethod, idx, BLOCK), "value", ""));
// Create the marshaler class associated with this block type
String marshaler = createBlockMarshaler(config, clazz, targetMethod, actualGenericTypes, actualRawTypes, unboxedTypes, blockTypeIds, targetMethodAnnotations);
addMarshalerAnnotation(blockMethod, idx, marshaler);
}
}
if (hasAnnotation(blockMethod, BLOCK)) {
SootMethod targetMethod = getBlockTargetMethod(blockMethod);
Type[] actualGenericTypes = resolveTargetMethodSignature(blockMethod, targetMethod, blockMethodType.getGenericReturnType());
soot.Type[] actualRawTypes = toRawTypes(actualGenericTypes);
soot.Type[] unboxedTypes = unboxTypes(actualRawTypes);
String[][] targetMethodAnnotations = parseTargetMethodAnnotations(targetMethod, readStringElem(getAnnotation(blockMethod, BLOCK), "value", ""));
String marshaler = createBlockMarshaler(config, clazz, targetMethod, actualGenericTypes, actualRawTypes, unboxedTypes, blockTypeIds, targetMethodAnnotations);
addMarshalerAnnotation(blockMethod, marshaler);
}
}
use of soot.SootMethod in project robovm by robovm.
the class ObjCBlockPlugin method getBlockTargetMethod.
protected static SootMethod getBlockTargetMethod(SootMethod method, int paramIndex) {
soot.Type type = method.getParameterType(paramIndex);
if (!(type instanceof RefType)) {
throw new CompilerException("@Block annotated parameter " + (paramIndex + 1) + " of method " + method + " must be of interface type");
}
SootClass blockType = ((RefType) type).getSootClass();
if (!blockType.isInterface()) {
throw new CompilerException("@Block annotated parameter " + (paramIndex + 1) + " of method " + method + " must be of interface type");
}
List<SootMethod> allMethods = collectAbstractMethods(blockType);
if (allMethods.isEmpty()) {
throw new CompilerException("No abstract method found in interface " + blockType + " used in @Block annotated parameter " + (paramIndex + 1) + " of method " + method);
}
if (allMethods.size() > 1) {
throw new CompilerException("More than 1 abstract method found in interface " + blockType + " used in @Block annotated parameter " + (paramIndex + 1) + " of method " + method);
}
return allMethods.get(0);
}
use of soot.SootMethod in project robovm by robovm.
the class ObjCMemberPlugin method addBindCall.
private void addBindCall(SootClass sootClass) {
Jimple j = Jimple.v();
SootMethod clinit = getOrCreateStaticInitializer(sootClass);
Body body = clinit.retrieveActiveBody();
String internalName = sootClass.getName().replace('.', '/');
ClassConstant c = ClassConstant.v(internalName);
Chain<Unit> units = body.getUnits();
// Don't call bind if there's already a call in the static initializer
for (Unit unit : units) {
if (unit instanceof InvokeStmt) {
InvokeStmt stmt = (InvokeStmt) unit;
if (stmt.getInvokeExpr() instanceof StaticInvokeExpr) {
StaticInvokeExpr expr = (StaticInvokeExpr) stmt.getInvokeExpr();
SootMethodRef ref = expr.getMethodRef();
if (ref.isStatic() && ref.declaringClass().equals(org_robovm_objc_ObjCRuntime) && ref.name().equals("bind")) {
if (ref.parameterTypes().isEmpty() || expr.getArg(0).equals(c)) {
return;
}
}
}
}
}
// Call ObjCRuntime.bind(<class>)
units.insertBefore(j.newInvokeStmt(j.newStaticInvokeExpr(org_robovm_objc_ObjCRuntime_bind, ClassConstant.v(internalName))), units.getLast());
}
use of soot.SootMethod in project robovm by robovm.
the class ObjCMemberPlugin method getMsgSendMethod.
@SuppressWarnings("unchecked")
private SootMethod getMsgSendMethod(String selectorName, SootMethod method, SootMethod annotatedMethod, boolean isCallback, Type receiverType, boolean extensions) {
List<Type> paramTypes = new ArrayList<>();
if (extensions) {
paramTypes.add(method.getParameterType(0));
} else if (method.isStatic()) {
paramTypes.add(org_robovm_objc_ObjCClass.getType());
} else {
paramTypes.add(receiverType == null ? method.getDeclaringClass().getType() : receiverType);
}
paramTypes.add(org_robovm_objc_Selector.getType());
if (extensions) {
paramTypes.addAll(method.getParameterTypes().subList(1, method.getParameterTypes().size()));
} else {
paramTypes.addAll(method.getParameterTypes());
}
SootMethod m = new SootMethod((isCallback ? "$cb$" : "$m$") + selectorName.replace(':', '$'), paramTypes, method.getReturnType(), STATIC | PRIVATE | (isCallback ? 0 : NATIVE));
copyAnnotations(annotatedMethod, m, extensions);
createGenericSignatureForMsgSend(annotatedMethod, m, paramTypes, extensions);
return m;
}
Aggregations