Search in sources :

Example 1 with LdcClass

use of org.robovm.compiler.trampoline.LdcClass in project robovm by robovm.

the class MethodCompiler method immediate.

private Value immediate(Unit unit, Immediate v) {
    // v is either a soot.Local or a soot.jimple.Constant
    if (v instanceof soot.Local) {
        Local local = (Local) v;
        Type type = getLocalType(v.getType());
        VariableRef var = new VariableRef(local.getName(), new PointerType(type));
        Variable tmp = function.newVariable(type);
        function.add(new Load(tmp, var, !sootMethod.getActiveBody().getTraps().isEmpty())).attach(unit);
        return new VariableRef(tmp);
    } else if (v instanceof soot.jimple.IntConstant) {
        return new IntegerConstant(((soot.jimple.IntConstant) v).value);
    } else if (v instanceof soot.jimple.LongConstant) {
        return new IntegerConstant(((soot.jimple.LongConstant) v).value);
    } else if (v instanceof soot.jimple.FloatConstant) {
        return new FloatingPointConstant(((soot.jimple.FloatConstant) v).value);
    } else if (v instanceof soot.jimple.DoubleConstant) {
        return new FloatingPointConstant(((soot.jimple.DoubleConstant) v).value);
    } else if (v instanceof soot.jimple.NullConstant) {
        return new NullConstant(OBJECT_PTR);
    } else if (v instanceof soot.jimple.StringConstant) {
        String s = ((soot.jimple.StringConstant) v).value;
        return call(unit, ldcString(s), env);
    } else if (v instanceof soot.jimple.ClassConstant) {
        // ClassConstant is either the internal name of a class or the descriptor of an array
        String targetClassName = ((soot.jimple.ClassConstant) v).getValue();
        if (isArray(targetClassName) && isPrimitiveComponentType(targetClassName)) {
            String primitiveDesc = targetClassName.substring(1);
            Variable result = function.newVariable(OBJECT_PTR);
            function.add(new Load(result, new ConstantBitcast(new GlobalRef("array_" + primitiveDesc, CLASS_PTR), new PointerType(OBJECT_PTR)))).attach(unit);
            return result.ref();
        } else {
            FunctionRef fn = null;
            if (targetClassName.equals(this.className)) {
                fn = FunctionBuilder.ldcInternal(sootMethod.getDeclaringClass()).ref();
            } else {
                Trampoline trampoline = new LdcClass(className, ((soot.jimple.ClassConstant) v).getValue());
                trampolines.add(trampoline);
                fn = trampoline.getFunctionRef();
            }
            return call(unit, fn, env);
        }
    }
    throw new IllegalArgumentException("Unknown Immediate type: " + v.getClass());
}
Also used : GlobalRef(org.robovm.compiler.llvm.GlobalRef) VariableRef(org.robovm.compiler.llvm.VariableRef) Variable(org.robovm.compiler.llvm.Variable) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) PointerType(org.robovm.compiler.llvm.PointerType) FunctionRef(org.robovm.compiler.llvm.FunctionRef) Load(org.robovm.compiler.llvm.Load) FloatingPointConstant(org.robovm.compiler.llvm.FloatingPointConstant) Trampoline(org.robovm.compiler.trampoline.Trampoline) Local(soot.Local) NullConstant(org.robovm.compiler.llvm.NullConstant) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) FloatingPointType(org.robovm.compiler.llvm.FloatingPointType) IntegerType(org.robovm.compiler.llvm.IntegerType) PointerType(org.robovm.compiler.llvm.PointerType) NullType(soot.NullType) FunctionType(org.robovm.compiler.llvm.FunctionType) ArrayType(org.robovm.compiler.llvm.ArrayType) CharType(soot.CharType) RefLikeType(soot.RefLikeType) Type(org.robovm.compiler.llvm.Type) PrimType(soot.PrimType) LdcClass(org.robovm.compiler.trampoline.LdcClass)

Example 2 with LdcClass

use of org.robovm.compiler.trampoline.LdcClass in project robovm by robovm.

the class BroMethodCompiler method ldcClass.

protected Value ldcClass(Function fn, String name, Value env) {
    if (isArray(name) && isPrimitiveBaseType(name)) {
        String primitiveDesc = name.substring(name.length() - 1);
        Variable result = fn.newVariable(OBJECT_PTR);
        fn.add(new Load(result, new ConstantBitcast(new GlobalRef("array_" + primitiveDesc, CLASS_PTR), new PointerType(OBJECT_PTR))));
        return result.ref();
    } else {
        FunctionRef ldcClassFn = null;
        if (name.equals(this.className)) {
            ldcClassFn = FunctionBuilder.ldcInternal(this.className).ref();
        } else {
            Trampoline trampoline = new LdcClass(this.className, name);
            trampolines.add(trampoline);
            ldcClassFn = trampoline.getFunctionRef();
        }
        return call(fn, ldcClassFn, env);
    }
}
Also used : GlobalRef(org.robovm.compiler.llvm.GlobalRef) Load(org.robovm.compiler.llvm.Load) Variable(org.robovm.compiler.llvm.Variable) Trampoline(org.robovm.compiler.trampoline.Trampoline) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) LdcClass(org.robovm.compiler.trampoline.LdcClass) PointerType(org.robovm.compiler.llvm.PointerType) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Example 3 with LdcClass

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

FunctionRef (org.robovm.compiler.llvm.FunctionRef)3 LdcClass (org.robovm.compiler.trampoline.LdcClass)3 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)2 GlobalRef (org.robovm.compiler.llvm.GlobalRef)2 Load (org.robovm.compiler.llvm.Load)2 PointerType (org.robovm.compiler.llvm.PointerType)2 Variable (org.robovm.compiler.llvm.Variable)2 Trampoline (org.robovm.compiler.trampoline.Trampoline)2 ImmutableTriple (org.apache.commons.lang3.tuple.ImmutableTriple)1 Clazz (org.robovm.compiler.clazz.Clazz)1 ArrayType (org.robovm.compiler.llvm.ArrayType)1 FloatingPointConstant (org.robovm.compiler.llvm.FloatingPointConstant)1 FloatingPointType (org.robovm.compiler.llvm.FloatingPointType)1 Function (org.robovm.compiler.llvm.Function)1 FunctionType (org.robovm.compiler.llvm.FunctionType)1 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)1 IntegerType (org.robovm.compiler.llvm.IntegerType)1 NullConstant (org.robovm.compiler.llvm.NullConstant)1 Type (org.robovm.compiler.llvm.Type)1 Unreachable (org.robovm.compiler.llvm.Unreachable)1