Search in sources :

Example 41 with SootMethod

use of soot.SootMethod in project robovm by robovm.

the class ObjCMemberPlugin method getMsgSendSuperMethod.

@SuppressWarnings("unchecked")
private SootMethod getMsgSendSuperMethod(String selectorName, SootMethod method) {
    List<Type> paramTypes = new ArrayList<>();
    paramTypes.add(org_robovm_objc_ObjCSuper.getType());
    paramTypes.add(org_robovm_objc_Selector.getType());
    paramTypes.addAll(method.getParameterTypes());
    SootMethod m = new SootMethod("$m$super$" + selectorName.replace(':', '$'), paramTypes, method.getReturnType(), STATIC | PRIVATE | NATIVE);
    copyAnnotations(method, m, false);
    createGenericSignatureForMsgSend(method, m, paramTypes, false);
    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)

Example 42 with SootMethod

use of soot.SootMethod in project robovm by robovm.

the class ObjCMemberPlugin method beforeClass.

@Override
public void beforeClass(Config config, Clazz clazz, ModuleBuilder moduleBuilder) {
    init(config);
    SootClass sootClass = clazz.getSootClass();
    boolean extensions = false;
    if (!sootClass.isInterface() && (isObjCObject(sootClass) || (extensions = isObjCExtensions(sootClass)))) {
        Set<String> selectors = new TreeSet<>();
        Set<String> overridables = new HashSet<>();
        for (SootMethod method : sootClass.getMethods()) {
            if (!"<clinit>".equals(method.getName()) && !"<init>".equals(method.getName())) {
                transformMethod(config, clazz, sootClass, method, selectors, overridables, extensions);
            }
        }
        addBindCall(sootClass);
        if (!extensions) {
            addObjCClassField(sootClass);
        }
        registerSelectors(sootClass, selectors);
    }
}
Also used : TreeSet(java.util.TreeSet) SootMethod(soot.SootMethod) SootClass(soot.SootClass) HashSet(java.util.HashSet)

Example 43 with SootMethod

use of soot.SootMethod in project robovm by robovm.

the class ObjCMemberPlugin method findStrongRefGetter.

private SootMethod findStrongRefGetter(SootClass sootClass, final SootMethod method, boolean extensions) {
    AnnotationTag annotation = getAnnotation(method, PROPERTY);
    if (annotation == null) {
        annotation = getAnnotation(method, IBOUTLET);
    }
    if (annotation == null) {
        annotation = getAnnotation(method, IBOUTLETCOLLECTION);
    }
    String setterPropName = readStringElem(annotation, "name", "").trim();
    if (setterPropName.length() == 0) {
        String methodName = method.getName();
        if (!methodName.startsWith("set") || methodName.length() == 3) {
            throw new CompilerException("Failed to determine the property " + "name from the @Property method " + method + ". Either specify the name explicitly in the @Property " + "annotation or rename the method according to the Java " + "beans property setter method naming convention.");
        }
        setterPropName = methodName.substring(3);
        setterPropName = setterPropName.substring(0, 1).toLowerCase() + setterPropName.substring(1);
    }
    int paramCount = extensions ? 1 : 0;
    Type propType = method.getParameterType(extensions ? 1 : 0);
    for (SootMethod m : sootClass.getMethods()) {
        if (m != method && method.isStatic() == m.isStatic() && m.getParameterCount() == paramCount && m.getReturnType().equals(propType)) {
            AnnotationTag propertyAnno = getAnnotation(m, PROPERTY);
            if (propertyAnno != null) {
                String getterPropName = readStringElem(propertyAnno, "name", "").trim();
                if (getterPropName.length() == 0) {
                    String methodName = m.getName();
                    if (!methodName.startsWith("get") || methodName.length() == 3) {
                        // style getter
                        continue;
                    }
                    getterPropName = methodName.substring(3);
                    getterPropName = getterPropName.substring(0, 1).toLowerCase() + getterPropName.substring(1);
                }
                if (setterPropName.equals(getterPropName)) {
                    return m;
                }
            }
        }
    }
    throw new CompilerException("Failed to determine the getter method " + "corresponding to the strong ref @Property setter method " + method + ". The getter must either specify the name explicitly in the @Property " + "annotation or be named according to the Java " + "beans property getter method naming convention.");
}
Also used : AnnotationTag(soot.tagkit.AnnotationTag) 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) CompilerException(org.robovm.compiler.CompilerException) SootMethod(soot.SootMethod)

Example 44 with SootMethod

use of soot.SootMethod in project robovm by robovm.

the class TrampolineCompiler method compile.

public void compile(ModuleBuilder mb, Clazz currentClass, Trampoline t, Set<String> dependencies, Set<Triple<String, String, String>> methodDependencies) {
    this.mb = mb;
    addDependencyIfNeeded(dependencies, currentClass, t);
    /*
         * Check if the target class exists and is accessible. Also check that
         * field accesses and method calls are compatible with the target 
         * field/method and that the field/method is accessible to the caller.
         * If any of the tests fail the weak trampoline function created by the
         * ClassCompiler will be overridden with a function which throws an
         * appropriate exception.
         */
    Function errorFn = new FunctionBuilder(t).linkage(external).build();
    if (!checkClassExists(errorFn, t) || !checkClassAccessible(errorFn, t)) {
        mb.addFunction(errorFn);
        return;
    }
    if (t instanceof New) {
        SootClass target = config.getClazzes().load(t.getTarget()).getSootClass();
        if (target.isAbstract() || target.isInterface()) {
            call(errorFn, BC_THROW_INSTANTIATION_ERROR, errorFn.getParameterRef(0), mb.getString(t.getTarget().replace('/', '.')));
            errorFn.add(new Unreachable());
            mb.addFunction(errorFn);
            return;
        }
        String fnName = Symbols.clinitWrapperSymbol(Symbols.allocatorSymbol(t.getTarget()));
        alias(t, fnName);
    } else if (t instanceof Instanceof) {
        if (isArray(t.getTarget())) {
            FunctionRef fnRef = createInstanceofArray((Instanceof) t);
            alias(t, fnRef.getName());
        } else {
            String fnName = Symbols.instanceofSymbol(t.getTarget());
            alias(t, fnName);
        }
    } else if (t instanceof Checkcast) {
        if (isArray(t.getTarget())) {
            FunctionRef fnRef = createCheckcastArray((Checkcast) t);
            alias(t, fnRef.getName());
        } else {
            String fnName = Symbols.checkcastSymbol(t.getTarget());
            alias(t, fnName);
        }
    } else if (t instanceof LdcClass) {
        if (isArray(t.getTarget())) {
            FunctionRef fnRef = createLdcArray((LdcClass) t);
            alias(t, fnRef.getName());
        } else {
            String fnName = Symbols.ldcExternalSymbol(t.getTarget());
            alias(t, fnName);
        }
    } else if (t instanceof Anewarray) {
        FunctionRef fnRef = createAnewarray((Anewarray) t);
        alias(t, fnRef.getName());
    } else if (t instanceof Multianewarray) {
        FunctionRef fnRef = createMultianewarray((Multianewarray) t);
        alias(t, fnRef.getName());
    } else if (t instanceof FieldAccessor) {
        SootField field = resolveField(errorFn, (FieldAccessor) t);
        if (field != null) {
            dependencies.add(getInternalName(field.getDeclaringClass()));
        }
        if (field == null || !checkMemberAccessible(errorFn, t, field)) {
            mb.addFunction(errorFn);
            return;
        }
        Clazz caller = config.getClazzes().load(t.getCallingClass());
        Clazz target = config.getClazzes().load(t.getTarget());
        if (!((FieldAccessor) t).isGetter() && field.isFinal() && caller != target) {
            // Only the class declaring a final field may write to it.
            // (Actually only <init>/<clinit> methods may write to it but we 
            // don't know which method is accessing the field at this point)
            throwIllegalAccessError(errorFn, ATTEMPT_TO_WRITE_TO_FINAL_FIELD, target, field.getName(), caller);
            mb.addFunction(errorFn);
            return;
        }
        if (!field.isStatic()) {
            createInlinedAccessorForInstanceField((FieldAccessor) t, field);
        } else {
            createTrampolineAliasForField((FieldAccessor) t, field);
        }
    } else if (t instanceof Invokeinterface) {
        SootMethod rm = resolveInterfaceMethod(errorFn, (Invokeinterface) t);
        if (rm != null) {
            methodDependencies.add(new ImmutableTriple<String, String, String>(getInternalName(rm.getDeclaringClass()), rm.getName(), getDescriptor(rm)));
        }
        if (rm == null || !checkMemberAccessible(errorFn, t, rm)) {
            mb.addFunction(errorFn);
            return;
        }
        createTrampolineAliasForMethod((Invoke) t, rm);
    } else if (t instanceof Invoke) {
        SootMethod method = resolveMethod(errorFn, (Invoke) t);
        if (method != null) {
            methodDependencies.add(new ImmutableTriple<String, String, String>(getInternalName(method.getDeclaringClass()), method.getName(), getDescriptor(method)));
        }
        if (method == null || !checkMemberAccessible(errorFn, t, method)) {
            mb.addFunction(errorFn);
            return;
        }
        if (t instanceof Invokespecial && method.isAbstract()) {
            call(errorFn, BC_THROW_ABSTRACT_METHOD_ERROR, errorFn.getParameterRef(0), mb.getString(String.format(NO_SUCH_METHOD_ERROR, method.getDeclaringClass(), method.getName(), getDescriptor(method))));
            errorFn.add(new Unreachable());
            mb.addFunction(errorFn);
            return;
        }
        createTrampolineAliasForMethod((Invoke) t, method);
    }
}
Also used : New(org.robovm.compiler.trampoline.New) ImmutableTriple(org.apache.commons.lang3.tuple.ImmutableTriple) Anewarray(org.robovm.compiler.trampoline.Anewarray) Multianewarray(org.robovm.compiler.trampoline.Multianewarray) SootClass(soot.SootClass) FieldAccessor(org.robovm.compiler.trampoline.FieldAccessor) Invokeinterface(org.robovm.compiler.trampoline.Invokeinterface) Invoke(org.robovm.compiler.trampoline.Invoke) Invokespecial(org.robovm.compiler.trampoline.Invokespecial) Function(org.robovm.compiler.llvm.Function) Unreachable(org.robovm.compiler.llvm.Unreachable) LdcClass(org.robovm.compiler.trampoline.LdcClass) Instanceof(org.robovm.compiler.trampoline.Instanceof) SootMethod(soot.SootMethod) SootField(soot.SootField) Clazz(org.robovm.compiler.clazz.Clazz) Checkcast(org.robovm.compiler.trampoline.Checkcast) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Example 45 with SootMethod

use of soot.SootMethod in project robovm by robovm.

the class AnnotationImplPlugin method generateSlowEqualsMethod.

private void generateSlowEqualsMethod(Clazz clazz, ClassWriter cw) {
    String implName = clazz.getInternalName() + IMPL_CLASS_NAME_SUFFIX;
    // boolean slowEquals(Object that);
    // that is known to be an instance of the same interface but not an instance of our impl class.
    MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "slowEquals", "(Ljava/lang/Object;)Z", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 1);
    mv.visitTypeInsn(CHECKCAST, clazz.getInternalName());
    mv.visitVarInsn(ASTORE, 1);
    Label l1 = new Label();
    for (SootMethod method : clazz.getSootClass().getMethods()) {
        String fieldName = getFieldName(method);
        soot.Type type = method.getReturnType();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(DUP);
        mv.visitFieldInsn(GETFIELD, implName, fieldName, "Ljava/lang/Object;");
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEINTERFACE, clazz.getInternalName(), method.getName(), "()" + Types.getDescriptor(type));
        boxIfNeeded(mv, type);
        mv.visitMethodInsn(INVOKESPECIAL, BASE_CLASS, "memberEquals", "(Ljava/lang/Object;Ljava/lang/Object;)Z");
        mv.visitJumpInsn(IFEQ, l1);
    }
    // return true;
    mv.visitInsn(ICONST_1);
    mv.visitInsn(IRETURN);
    // return false
    mv.visitLabel(l1);
    mv.visitInsn(ICONST_0);
    mv.visitInsn(IRETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}
Also used : Label(org.objectweb.asm.Label) SootMethod(soot.SootMethod) MethodVisitor(org.objectweb.asm.MethodVisitor)

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