Search in sources :

Example 21 with Function

use of org.robovm.compiler.llvm.Function in project robovm by robovm.

the class StructMemberMethodCompiler method structMember.

private Function structMember(ModuleBuilder moduleBuilder, SootMethod method) {
    Function function = createMethodFunction(method);
    moduleBuilder.addFunction(function);
    // Get the value of the handle field in the Struct base class and cast it to a <structType>*
    Variable handleI64 = function.newVariable(I64);
    function.add(new Load(handleI64, getFieldPtr(function, function.getParameterRef(1), offsetof(new StructureType(DATA_OBJECT, new StructureType(I64)), 1, 0), I64)));
    Variable handlePtr = function.newVariable(new PointerType(structType));
    function.add(new Inttoptr(handlePtr, handleI64.ref(), handlePtr.getType()));
    // Add 1 since the first type in structType is the superclass type or {}.      
    int offset = getStructMemberOffset(method) + 1;
    Type memberType = getStructMemberType(method);
    Variable memberPtr = function.newVariable(new PointerType(memberType));
    if (memberType != structType.getTypeAt(offset)) {
        // Several @StructMembers of different types have this offset (union)
        Variable tmp = function.newVariable(new PointerType(structType.getTypeAt(offset)));
        function.add(new Getelementptr(tmp, handlePtr.ref(), 0, offset));
        function.add(new Bitcast(memberPtr, tmp.ref(), memberPtr.getType()));
    } else {
        function.add(new Getelementptr(memberPtr, handlePtr.ref(), 0, offset));
    }
    VariableRef env = function.getParameterRef(0);
    if (method.getParameterCount() == 0) {
        // Getter
        Value result = loadValueForGetter(method, function, memberType, memberPtr.ref(), function.getParameterRef(0), true, MarshalerFlags.CALL_TYPE_STRUCT_MEMBER);
        function.add(new Ret(result));
    } else {
        // Setter
        // 'env' is parameter 0, 'this' is at 1, the value we're interested in is at index 2
        Value value = function.getParameterRef(2);
        storeValueForSetter(method, function, memberType, memberPtr.ref(), env, value, MarshalerFlags.CALL_TYPE_STRUCT_MEMBER);
        if (method.getReturnType().equals(VoidType.v())) {
            function.add(new Ret());
        } else {
            function.add(new Ret(function.getParameterRef(1)));
        }
    }
    return function;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) Load(org.robovm.compiler.llvm.Load) VariableRef(org.robovm.compiler.llvm.VariableRef) Variable(org.robovm.compiler.llvm.Variable) Inttoptr(org.robovm.compiler.llvm.Inttoptr) PointerType(org.robovm.compiler.llvm.PointerType) Getelementptr(org.robovm.compiler.llvm.Getelementptr) Function(org.robovm.compiler.llvm.Function) StructureType(org.robovm.compiler.llvm.StructureType) PointerType(org.robovm.compiler.llvm.PointerType) Type(org.robovm.compiler.llvm.Type) VoidType(soot.VoidType) Bitcast(org.robovm.compiler.llvm.Bitcast) StructureType(org.robovm.compiler.llvm.StructureType) Value(org.robovm.compiler.llvm.Value)

Example 22 with Function

use of org.robovm.compiler.llvm.Function in project robovm by robovm.

the class StructMemberMethodCompiler method structSizeOf.

private Function structSizeOf(ModuleBuilder moduleBuilder, SootMethod method) {
    Function fn = createMethodFunction(method);
    moduleBuilder.addFunction(fn);
    fn.add(new Ret(sizeof(structType)));
    return fn;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) Function(org.robovm.compiler.llvm.Function)

Example 23 with Function

use of org.robovm.compiler.llvm.Function 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 24 with Function

use of org.robovm.compiler.llvm.Function in project robovm by robovm.

the class TrampolineCompiler method createInlinedAccessorForInstanceField.

private void createInlinedAccessorForInstanceField(FieldAccessor t, SootField field) {
    Function fn = new FunctionBuilder(t).linkage(aliasLinkage()).attribs(shouldInline(), optsize).build();
    List<SootField> classFields = Collections.emptyList();
    StructureType classType = new StructureType();
    List<SootField> instanceFields = getInstanceFields(config.getOs(), config.getArch(), field.getDeclaringClass());
    StructureType instanceType = getInstanceType(config.getOs(), config.getArch(), field.getDeclaringClass());
    if (t.isGetter()) {
        ClassCompiler.createFieldGetter(fn, field, classFields, classType, instanceFields, instanceType);
    } else {
        ClassCompiler.createFieldSetter(fn, field, classFields, classType, instanceFields, instanceType);
    }
    mb.addFunction(fn);
}
Also used : Function(org.robovm.compiler.llvm.Function) StructureType(org.robovm.compiler.llvm.StructureType) SootField(soot.SootField)

Example 25 with Function

use of org.robovm.compiler.llvm.Function in project robovm by robovm.

the class TrampolineCompiler method alias.

private void alias(Trampoline t, String fnName) {
    FunctionRef aliasee = new FunctionRef(fnName, t.getFunctionType());
    if (!mb.hasSymbol(fnName)) {
        mb.addFunctionDeclaration(new FunctionDeclaration(aliasee));
    }
    Function fn = new FunctionBuilder(t).linkage(aliasLinkage()).attribs(shouldInline(), optsize).build();
    Value result = call(fn, aliasee, fn.getParameterRefs());
    fn.add(new Ret(result));
    mb.addFunction(fn);
}
Also used : Ret(org.robovm.compiler.llvm.Ret) FunctionDeclaration(org.robovm.compiler.llvm.FunctionDeclaration) Function(org.robovm.compiler.llvm.Function) Value(org.robovm.compiler.llvm.Value) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Aggregations

Function (org.robovm.compiler.llvm.Function)29 Ret (org.robovm.compiler.llvm.Ret)24 Value (org.robovm.compiler.llvm.Value)22 FunctionRef (org.robovm.compiler.llvm.FunctionRef)16 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)9 FunctionType (org.robovm.compiler.llvm.FunctionType)7 Global (org.robovm.compiler.llvm.Global)7 NullConstant (org.robovm.compiler.llvm.NullConstant)7 ArrayList (java.util.ArrayList)6 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)6 Label (org.robovm.compiler.llvm.Label)6 PointerType (org.robovm.compiler.llvm.PointerType)6 StructureType (org.robovm.compiler.llvm.StructureType)6 Unreachable (org.robovm.compiler.llvm.Unreachable)6 Variable (org.robovm.compiler.llvm.Variable)6 Bitcast (org.robovm.compiler.llvm.Bitcast)5 FunctionDeclaration (org.robovm.compiler.llvm.FunctionDeclaration)5 Load (org.robovm.compiler.llvm.Load)5 Type (org.robovm.compiler.llvm.Type)5 ModifiedUtf8HashFunction (org.robovm.compiler.hash.ModifiedUtf8HashFunction)4