Search in sources :

Example 6 with SootMethod

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);
                }
            }
        }
    }
}
Also used : HashMap(java.util.HashMap) SootMethod(soot.SootMethod) SootClass(soot.SootClass)

Example 7 with SootMethod

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);
    }
}
Also used : RefType(soot.RefType) ShortType(soot.ShortType) BooleanType(soot.BooleanType) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) WildcardType(org.robovm.compiler.util.generic.WildcardType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) SootClassType(org.robovm.compiler.util.generic.SootClassType) ByteType(soot.ByteType) Type(org.robovm.compiler.util.generic.Type) DoubleType(soot.DoubleType) GenericArrayType(org.robovm.compiler.util.generic.GenericArrayType) FloatType(soot.FloatType) IntType(soot.IntType) ImplForType(org.robovm.compiler.util.generic.ImplForType) CharType(soot.CharType) LongType(soot.LongType) ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) PrimType(soot.PrimType) VoidType(soot.VoidType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) SootMethod(soot.SootMethod)

Example 8 with SootMethod

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);
}
Also used : RefType(soot.RefType) CompilerException(org.robovm.compiler.CompilerException) SootMethod(soot.SootMethod) SootClass(soot.SootClass)

Example 9 with SootMethod

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());
}
Also used : StaticInvokeExpr(soot.jimple.StaticInvokeExpr) InvokeStmt(soot.jimple.InvokeStmt) SootMethodRef(soot.SootMethodRef) SootMethod(soot.SootMethod) Jimple(soot.jimple.Jimple) Unit(soot.Unit) Body(soot.Body) ClassConstant(soot.jimple.ClassConstant)

Example 10 with SootMethod

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;
}
Also used : RefType(soot.RefType) BooleanType(soot.BooleanType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) Type(soot.Type) DoubleType(soot.DoubleType) FloatType(soot.FloatType) LongType(soot.LongType) RefLikeType(soot.RefLikeType) PrimType(soot.PrimType) VoidType(soot.VoidType) ArrayList(java.util.ArrayList) SootMethod(soot.SootMethod)

Aggregations

SootMethod (soot.SootMethod)82 Test (org.junit.Test)34 SootClass (soot.SootClass)30 MarshalSite (org.robovm.compiler.MarshalerLookup.MarshalSite)21 PrimType (soot.PrimType)15 RefType (soot.RefType)14 VoidType (soot.VoidType)13 SootMethodType (org.robovm.compiler.util.generic.SootMethodType)11 DoubleType (soot.DoubleType)11 FloatType (soot.FloatType)11 LongType (soot.LongType)11 ArrayList (java.util.ArrayList)9 BooleanType (soot.BooleanType)9 SootField (soot.SootField)8 Type (soot.Type)8 Body (soot.Body)7 RefLikeType (soot.RefLikeType)7 CompilerException (org.robovm.compiler.CompilerException)6 Unit (soot.Unit)6 MethodVisitor (org.objectweb.asm.MethodVisitor)5