Search in sources :

Example 1 with FieldAccessor

use of org.robovm.compiler.trampoline.FieldAccessor 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)

Aggregations

ImmutableTriple (org.apache.commons.lang3.tuple.ImmutableTriple)1 Clazz (org.robovm.compiler.clazz.Clazz)1 Function (org.robovm.compiler.llvm.Function)1 FunctionRef (org.robovm.compiler.llvm.FunctionRef)1 Unreachable (org.robovm.compiler.llvm.Unreachable)1 Anewarray (org.robovm.compiler.trampoline.Anewarray)1 Checkcast (org.robovm.compiler.trampoline.Checkcast)1 FieldAccessor (org.robovm.compiler.trampoline.FieldAccessor)1 Instanceof (org.robovm.compiler.trampoline.Instanceof)1 Invoke (org.robovm.compiler.trampoline.Invoke)1 Invokeinterface (org.robovm.compiler.trampoline.Invokeinterface)1 Invokespecial (org.robovm.compiler.trampoline.Invokespecial)1 LdcClass (org.robovm.compiler.trampoline.LdcClass)1 Multianewarray (org.robovm.compiler.trampoline.Multianewarray)1 New (org.robovm.compiler.trampoline.New)1 SootClass (soot.SootClass)1 SootField (soot.SootField)1 SootMethod (soot.SootMethod)1