Search in sources :

Example 16 with FunctionType

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

the class CallbackMethodCompiler method compileCallback.

private Function compileCallback(ModuleBuilder moduleBuilder, SootMethod method) {
    Function callbackFn = null;
    FunctionType nativeFnType = null;
    boolean useCWrapper = requiresCWrapper(method);
    if (useCWrapper) {
        // The C wrapper is the function which is called by native code. It
        // handles structs passed/returned by value. It calls an LLVM function 
        // which has the same signature but all structs passed/returned by value
        // replaced by pointers (i8*).
        FunctionRef callbackCWrapperRef = getCallbackCWrapperRef(method, Symbols.callbackCSymbol(method));
        getCWrapperFunctions().add(createCallbackCWrapper(callbackCWrapperRef.getType(), callbackCWrapperRef.getName(), Symbols.callbackInnerCSymbol(method)));
        moduleBuilder.addFunctionDeclaration(new FunctionDeclaration(callbackCWrapperRef));
        Type callbackRetType = callbackCWrapperRef.getType().getReturnType() instanceof StructureType ? I8_PTR : callbackCWrapperRef.getType().getReturnType();
        Type[] callbackParamTypes = new Type[callbackCWrapperRef.getType().getParameterTypes().length];
        for (int i = 0; i < callbackParamTypes.length; i++) {
            Type t = callbackCWrapperRef.getType().getParameterTypes()[i];
            if (t instanceof StructureType) {
                t = I8_PTR;
            }
            callbackParamTypes[i] = t;
        }
        moduleBuilder.addAlias(new Alias(Symbols.callbackPtrSymbol(method), Linkage._private, new ConstantBitcast(callbackCWrapperRef, I8_PTR)));
        callbackFn = new FunctionBuilder(Symbols.callbackInnerCSymbol(method), new FunctionType(callbackRetType, callbackParamTypes)).build();
        nativeFnType = callbackCWrapperRef.getType();
    } else {
        FunctionType callbackFnType = getCallbackFunctionType(method, false);
        callbackFn = FunctionBuilder.callback(method, callbackFnType);
        moduleBuilder.addAlias(new Alias(Symbols.callbackPtrSymbol(method), Linkage._private, new ConstantBitcast(callbackFn.ref(), I8_PTR)));
        nativeFnType = callbackFnType;
    }
    moduleBuilder.addFunction(callbackFn);
    String targetName = method.isSynchronized() ? Symbols.synchronizedWrapperSymbol(method) : Symbols.methodSymbol(method);
    FunctionRef targetFn = new FunctionRef(targetName, getFunctionType(method));
    // Increase the attach count for the current thread (attaches the thread
    // if not attached)
    Value env = call(callbackFn, BC_ATTACH_THREAD_FROM_CALLBACK);
    BasicBlockRef bbSuccess = callbackFn.newBasicBlockRef(new Label("success"));
    BasicBlockRef bbFailure = callbackFn.newBasicBlockRef(new Label("failure"));
    pushCallbackFrame(callbackFn, env);
    trycatchAllEnter(callbackFn, env, bbSuccess, bbFailure);
    callbackFn.newBasicBlock(bbSuccess.getLabel());
    List<MarshaledArg> marshaledArgs = new ArrayList<MarshaledArg>();
    ArrayList<Value> args = new ArrayList<Value>();
    args.add(env);
    if (!method.isStatic()) {
        MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, MarshalSite.RECEIVER));
        MarshaledArg marshaledArg = new MarshaledArg();
        marshaledArg.paramIndex = MarshalSite.RECEIVER;
        marshaledArgs.add(marshaledArg);
        Value arg = callbackFn.getParameterRef(0);
        String targetClassName = getInternalName(method.getDeclaringClass());
        arg = marshalNativeToObject(callbackFn, marshalerMethod, marshaledArg, env, targetClassName, arg, MarshalerFlags.CALL_TYPE_CALLBACK);
        args.add(arg);
    }
    for (int i = 0, argIdx = 0; i < method.getParameterCount(); i++, argIdx++) {
        if (!method.isStatic() && argIdx == 0) {
            argIdx++;
        }
        Value arg = callbackFn.getParameterRef(argIdx);
        soot.Type type = method.getParameterType(i);
        if (needsMarshaler(type)) {
            MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, i));
            String targetClassName = getInternalName(type);
            if (arg.getType() instanceof PrimitiveType) {
                arg = marshalNativeToValueObject(callbackFn, marshalerMethod, env, targetClassName, arg, MarshalerFlags.CALL_TYPE_CALLBACK);
            } else {
                MarshaledArg marshaledArg = new MarshaledArg();
                marshaledArg.paramIndex = i;
                marshaledArgs.add(marshaledArg);
                Type nativeType = nativeFnType.getParameterTypes()[argIdx];
                if (nativeType instanceof StructureType) {
                    // Struct passed by value on the stack. Make a heap copy of the data and marshal that.
                    DataLayout dataLayout = config.getDataLayout();
                    Value heapCopy = call(callbackFn, BC_COPY_STRUCT, env, arg, new IntegerConstant(dataLayout.getAllocSize(nativeType)));
                    arg = marshalNativeToObject(callbackFn, marshalerMethod, marshaledArg, env, targetClassName, heapCopy, MarshalerFlags.CALL_TYPE_CALLBACK);
                } else {
                    arg = marshalNativeToObject(callbackFn, marshalerMethod, marshaledArg, env, targetClassName, arg, MarshalerFlags.CALL_TYPE_CALLBACK);
                }
            }
        } else {
            arg = marshalNativeToPrimitive(callbackFn, method, i, arg);
        }
        args.add(arg);
    }
    Value result = call(callbackFn, targetFn, args);
    // Call Marshaler.updateNative() for each object that was marshaled before
    // the call.
    updateNative(method, callbackFn, env, MarshalerFlags.CALL_TYPE_CALLBACK, marshaledArgs);
    // Marshal the returned value to a native value before returning
    if (needsMarshaler(method.getReturnType())) {
        MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
        Type nativeType = callbackFn.getType().getReturnType();
        if (nativeType instanceof PrimitiveType) {
            result = marshalValueObjectToNative(callbackFn, marshalerMethod, nativeType, env, result, MarshalerFlags.CALL_TYPE_CALLBACK);
        } else {
            result = marshalObjectToNative(callbackFn, marshalerMethod, null, nativeType, env, result, MarshalerFlags.CALL_TYPE_CALLBACK);
        }
    } else {
        result = marshalPrimitiveToNative(callbackFn, method, result);
    }
    trycatchLeave(callbackFn, env);
    popCallbackFrame(callbackFn, env);
    call(callbackFn, BC_DETACH_THREAD_FROM_CALLBACK, env);
    callbackFn.add(new Ret(result));
    callbackFn.newBasicBlock(bbFailure.getLabel());
    trycatchLeave(callbackFn, env);
    popCallbackFrame(callbackFn, env);
    Value ex = call(callbackFn, BC_EXCEPTION_CLEAR, env);
    // Call Marshaler.updateNative() for each object that was marshaled before
    // the call.
    updateNative(method, callbackFn, env, MarshalerFlags.CALL_TYPE_CALLBACK, marshaledArgs);
    call(callbackFn, BC_DETACH_THREAD_FROM_CALLBACK, env);
    call(callbackFn, BC_THROW, env, ex);
    callbackFn.add(new Unreachable());
    return callbackFn;
}
Also used : MarshalSite(org.robovm.compiler.MarshalerLookup.MarshalSite) Ret(org.robovm.compiler.llvm.Ret) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) Label(org.robovm.compiler.llvm.Label) ArrayList(java.util.ArrayList) Function(org.robovm.compiler.llvm.Function) FunctionDeclaration(org.robovm.compiler.llvm.FunctionDeclaration) BasicBlockRef(org.robovm.compiler.llvm.BasicBlockRef) Unreachable(org.robovm.compiler.llvm.Unreachable) PrimitiveType(org.robovm.compiler.llvm.PrimitiveType) FunctionRef(org.robovm.compiler.llvm.FunctionRef) DataLayout(org.robovm.compiler.llvm.DataLayout) FunctionType(org.robovm.compiler.llvm.FunctionType) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) StructureType(org.robovm.compiler.llvm.StructureType) Type(org.robovm.compiler.llvm.Type) PrimitiveType(org.robovm.compiler.llvm.PrimitiveType) FunctionType(org.robovm.compiler.llvm.FunctionType) Alias(org.robovm.compiler.llvm.Alias) StructureType(org.robovm.compiler.llvm.StructureType) Value(org.robovm.compiler.llvm.Value) MarshalerMethod(org.robovm.compiler.MarshalerLookup.MarshalerMethod) PointerMarshalerMethod(org.robovm.compiler.MarshalerLookup.PointerMarshalerMethod)

Example 17 with FunctionType

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

the class TrampolineCompiler method createLdcArray.

private FunctionRef createLdcArray(String targetClass) {
    if (isPrimitiveComponentType(targetClass)) {
        throw new IllegalArgumentException();
    }
    String fnName = Symbols.arrayldcSymbol(targetClass);
    FunctionRef fnRef = new FunctionRef(fnName, new FunctionType(OBJECT_PTR, ENV_PTR));
    if (!mb.hasSymbol(fnName)) {
        Function fn = new FunctionBuilder(fnRef).name(fnName).linkage(weak).build();
        Global g = new Global(Symbols.arrayPtrSymbol(targetClass), weak, new NullConstant(OBJECT_PTR));
        if (!mb.hasSymbol(g.getName())) {
            mb.addGlobal(g);
        }
        FunctionRef ldcArrayClassFn = BC_LDC_ARRAY_BOOT_CLASS;
        if (!isPrimitiveBaseType(targetClass)) {
            Clazz baseType = config.getClazzes().load(getBaseType(targetClass));
            if (!baseType.isInBootClasspath()) {
                ldcArrayClassFn = BC_LDC_ARRAY_CLASS;
            }
        }
        Value arrayClass = call(fn, ldcArrayClassFn, fn.getParameterRef(0), g.ref(), mb.getString(targetClass));
        fn.add(new Ret(arrayClass));
        mb.addFunction(fn);
    }
    return fnRef;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) Function(org.robovm.compiler.llvm.Function) FunctionType(org.robovm.compiler.llvm.FunctionType) Value(org.robovm.compiler.llvm.Value) NullConstant(org.robovm.compiler.llvm.NullConstant) Clazz(org.robovm.compiler.clazz.Clazz) Global(org.robovm.compiler.llvm.Global) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Example 18 with FunctionType

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

the class TypesTest method testGetFunctionTypeFromDescriptor.

@Test
public void testGetFunctionTypeFromDescriptor() {
    FunctionType type = null;
    type = getFunctionType("()V", true);
    assertEquals(VOID, type.getReturnType());
    assertEquals(1, type.getParameterTypes().length);
    assertEquals(ENV_PTR, type.getParameterTypes()[0]);
    type = getFunctionType("()V", false);
    assertEquals(VOID, type.getReturnType());
    assertEquals(2, type.getParameterTypes().length);
    assertEquals(ENV_PTR, type.getParameterTypes()[0]);
    assertEquals(OBJECT_PTR, type.getParameterTypes()[1]);
    type = getFunctionType("(Ljava/lang/Object;)Ljava/lang/String;", true);
    assertEquals(OBJECT_PTR, type.getReturnType());
    assertEquals(2, type.getParameterTypes().length);
    assertEquals(ENV_PTR, type.getParameterTypes()[0]);
    assertEquals(OBJECT_PTR, type.getParameterTypes()[1]);
    type = getFunctionType("(Ljava/lang/Object;)Ljava/lang/String;", false);
    assertEquals(OBJECT_PTR, type.getReturnType());
    assertEquals(3, type.getParameterTypes().length);
    assertEquals(ENV_PTR, type.getParameterTypes()[0]);
    assertEquals(OBJECT_PTR, type.getParameterTypes()[1]);
    assertEquals(OBJECT_PTR, type.getParameterTypes()[2]);
}
Also used : FunctionType(org.robovm.compiler.llvm.FunctionType) Test(org.junit.Test)

Example 19 with FunctionType

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

the class Functions method callWithArguments.

public static Value callWithArguments(Function currentFunction, Value fn, Argument... args) {
    Variable result = null;
    Type returnType = ((FunctionType) fn.getType()).getReturnType();
    if (returnType != VOID) {
        result = currentFunction.newVariable(returnType);
    }
    currentFunction.add(new Call(result, fn, args));
    return result == null ? null : result.ref();
}
Also used : TailCall(org.robovm.compiler.llvm.TailCall) Call(org.robovm.compiler.llvm.Call) PointerType(org.robovm.compiler.llvm.PointerType) Type(org.robovm.compiler.llvm.Type) FunctionType(org.robovm.compiler.llvm.FunctionType) Variable(org.robovm.compiler.llvm.Variable) FunctionType(org.robovm.compiler.llvm.FunctionType)

Example 20 with FunctionType

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

the class Functions method invoke.

public static Value invoke(Function currentFunction, Value fn, BasicBlockRef success, BasicBlockRef failure, Value... args) {
    Variable result = null;
    Type returnType = ((FunctionType) fn.getType()).getReturnType();
    if (returnType != VOID) {
        result = currentFunction.newVariable(returnType);
    }
    currentFunction.add(new Invoke(result, fn, success, failure, args));
    return result == null ? null : result.ref();
}
Also used : PointerType(org.robovm.compiler.llvm.PointerType) Type(org.robovm.compiler.llvm.Type) FunctionType(org.robovm.compiler.llvm.FunctionType) Variable(org.robovm.compiler.llvm.Variable) FunctionType(org.robovm.compiler.llvm.FunctionType) Invoke(org.robovm.compiler.llvm.Invoke)

Aggregations

FunctionType (org.robovm.compiler.llvm.FunctionType)33 PointerType (org.robovm.compiler.llvm.PointerType)16 Test (org.junit.Test)15 StructureType (org.robovm.compiler.llvm.StructureType)15 Type (org.robovm.compiler.llvm.Type)12 FunctionRef (org.robovm.compiler.llvm.FunctionRef)10 Variable (org.robovm.compiler.llvm.Variable)8 ArrayList (java.util.ArrayList)7 Function (org.robovm.compiler.llvm.Function)7 Value (org.robovm.compiler.llvm.Value)7 IntegerType (org.robovm.compiler.llvm.IntegerType)6 Ret (org.robovm.compiler.llvm.Ret)6 ArrayType (org.robovm.compiler.llvm.ArrayType)5 Global (org.robovm.compiler.llvm.Global)5 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)5 LongType (soot.LongType)5 PrimType (soot.PrimType)5 Call (org.robovm.compiler.llvm.Call)4 Label (org.robovm.compiler.llvm.Label)4 NullConstant (org.robovm.compiler.llvm.NullConstant)4