Search in sources :

Example 11 with Value

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

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

the class ClassCompiler method createLdcClassWrapper.

private Function createLdcClassWrapper() {
    Function fn = FunctionBuilder.ldcExternal(sootClass);
    Value info = getInfoStruct(fn, sootClass);
    Value result = call(fn, LDC_CLASS_WRAPPER, fn.getParameterRef(0), info);
    fn.add(new Ret(result));
    return fn;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) Function(org.robovm.compiler.llvm.Function) Value(org.robovm.compiler.llvm.Value)

Example 13 with Value

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

the class ClassCompiler method createClassInitWrapperFunction.

private Function createClassInitWrapperFunction(FunctionRef targetFn) {
    Function fn = FunctionBuilder.clinitWrapper(targetFn);
    Value info = getInfoStruct(fn, sootClass);
    Variable infoHeader = fn.newVariable(new PointerType(new StructureType(I8_PTR, I32)));
    fn.add(new Bitcast(infoHeader, info, infoHeader.getType()));
    Variable infoHeaderFlags = fn.newVariable(new PointerType(I32));
    fn.add(new Getelementptr(infoHeaderFlags, infoHeader.ref(), 0, 1));
    Variable flags = fn.newVariable(I32);
    fn.add(new Load(flags, infoHeaderFlags.ref()));
    Variable initializedFlag = fn.newVariable(I32);
    fn.add(new And(initializedFlag, flags.ref(), new IntegerConstant(CI_INITIALIZED)));
    Variable initialized = fn.newVariable(I1);
    fn.add(new Icmp(initialized, Icmp.Condition.eq, initializedFlag.ref(), new IntegerConstant(CI_INITIALIZED)));
    Label trueLabel = new Label();
    Label falseLabel = new Label();
    fn.add(new Br(initialized.ref(), fn.newBasicBlockRef(trueLabel), fn.newBasicBlockRef(falseLabel)));
    fn.newBasicBlock(trueLabel);
    Value result = call(fn, targetFn, fn.getParameterRefs());
    fn.add(new Ret(result));
    fn.newBasicBlock(falseLabel);
    call(fn, BC_INITIALIZE_CLASS, fn.getParameterRef(0), info);
    fn.add(new Br(fn.newBasicBlockRef(trueLabel)));
    return fn;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) Load(org.robovm.compiler.llvm.Load) Variable(org.robovm.compiler.llvm.Variable) Label(org.robovm.compiler.llvm.Label) PointerType(org.robovm.compiler.llvm.PointerType) Getelementptr(org.robovm.compiler.llvm.Getelementptr) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Br(org.robovm.compiler.llvm.Br) Function(org.robovm.compiler.llvm.Function) Bitcast(org.robovm.compiler.llvm.Bitcast) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) And(org.robovm.compiler.llvm.And) StructureType(org.robovm.compiler.llvm.StructureType) Value(org.robovm.compiler.llvm.Value) Icmp(org.robovm.compiler.llvm.Icmp)

Example 14 with Value

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

the class ClassCompiler method createFieldGetter.

static Function createFieldGetter(Function fn, SootField field, List<SootField> classFields, StructureType classType, List<SootField> instanceFields, StructureType instanceType) {
    Value fieldPtr = null;
    if (field.isStatic()) {
        fieldPtr = getClassFieldPtr(fn, field, classFields, classType);
    } else {
        fieldPtr = getInstanceFieldPtr(fn, fn.getParameterRef(1), field, instanceFields, instanceType);
    }
    Variable result = fn.newVariable(getType(field.getType()));
    if (Modifier.isVolatile(field.getModifiers())) {
        fn.add(new Fence(Ordering.seq_cst));
        if (LongType.v().equals(field.getType())) {
            fn.add(new Load(result, fieldPtr, false, Ordering.unordered, 8));
        } else {
            fn.add(new Load(result, fieldPtr));
        }
    } else {
        fn.add(new Load(result, fieldPtr));
    }
    fn.add(new Ret(new VariableRef(result)));
    return fn;
}
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) Value(org.robovm.compiler.llvm.Value) Fence(org.robovm.compiler.llvm.Fence)

Example 15 with Value

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

the class ClassCompiler method createAllocator.

private Function createAllocator() {
    Function fn = FunctionBuilder.allocator(sootClass);
    Value info = getInfoStruct(fn, sootClass);
    Value result = call(fn, BC_ALLOCATE, fn.getParameterRef(0), info);
    fn.add(new Ret(result));
    return fn;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) Function(org.robovm.compiler.llvm.Function) Value(org.robovm.compiler.llvm.Value)

Aggregations

Value (org.robovm.compiler.llvm.Value)48 Ret (org.robovm.compiler.llvm.Ret)26 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)24 Function (org.robovm.compiler.llvm.Function)22 Variable (org.robovm.compiler.llvm.Variable)18 FunctionRef (org.robovm.compiler.llvm.FunctionRef)16 Label (org.robovm.compiler.llvm.Label)10 Load (org.robovm.compiler.llvm.Load)10 ArrayList (java.util.ArrayList)9 PointerType (org.robovm.compiler.llvm.PointerType)9 Bitcast (org.robovm.compiler.llvm.Bitcast)8 FunctionType (org.robovm.compiler.llvm.FunctionType)8 NullConstant (org.robovm.compiler.llvm.NullConstant)8 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)7 StructureType (org.robovm.compiler.llvm.StructureType)7 Type (org.robovm.compiler.llvm.Type)7 VariableRef (org.robovm.compiler.llvm.VariableRef)7 Invokestatic (org.robovm.compiler.trampoline.Invokestatic)7 BasicBlockRef (org.robovm.compiler.llvm.BasicBlockRef)6 Br (org.robovm.compiler.llvm.Br)6