Search in sources :

Example 6 with StructureType

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

the class BridgeMethodCompiler method getBridgeCWrapperRef.

protected static FunctionRef getBridgeCWrapperRef(FunctionType functionType, String name) {
    Type returnType = functionType.getReturnType();
    Type wrapperReturnType = returnType instanceof StructureType ? VOID : returnType;
    List<Type> wrapperParamTypes = new ArrayList<>();
    wrapperParamTypes.add(I8_PTR);
    if (returnType instanceof StructureType) {
        wrapperParamTypes.add(I8_PTR);
    }
    for (Type t : functionType.getParameterTypes()) {
        if (t instanceof StructureType || t instanceof PointerType) {
            wrapperParamTypes.add(I8_PTR);
        } else {
            wrapperParamTypes.add(t);
        }
    }
    FunctionType wrapperFnType = new FunctionType(wrapperReturnType, wrapperParamTypes.toArray(new Type[wrapperParamTypes.size()]));
    return new FunctionRef(name, wrapperFnType);
}
Also used : StructureType(org.robovm.compiler.llvm.StructureType) PointerType(org.robovm.compiler.llvm.PointerType) LongType(soot.LongType) Type(org.robovm.compiler.llvm.Type) PrimitiveType(org.robovm.compiler.llvm.PrimitiveType) FunctionType(org.robovm.compiler.llvm.FunctionType) StructureType(org.robovm.compiler.llvm.StructureType) FunctionType(org.robovm.compiler.llvm.FunctionType) ArrayList(java.util.ArrayList) PointerType(org.robovm.compiler.llvm.PointerType) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Example 7 with StructureType

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

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

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

the class BroMethodCompiler method marshalObjectToNative.

protected Value marshalObjectToNative(Function fn, MarshalerMethod marshalerMethod, MarshaledArg marshaledArg, Type nativeType, Value env, Value object, long flags) {
    Invokestatic invokestatic = marshalerMethod.getInvokeStatic(sootMethod.getDeclaringClass());
    trampolines.add(invokestatic);
    Value handle = call(fn, invokestatic.getFunctionRef(), env, object, new IntegerConstant(flags));
    Variable nativeValue = fn.newVariable(nativeType);
    if (nativeType instanceof StructureType || nativeType instanceof ArrayType) {
        Variable tmp = fn.newVariable(new PointerType(nativeType));
        fn.add(new Inttoptr(tmp, handle, tmp.getType()));
        fn.add(new Load(nativeValue, tmp.ref()));
    } else {
        fn.add(new Inttoptr(nativeValue, handle, nativeType));
    }
    if (marshaledArg != null) {
        marshaledArg.handle = handle;
        marshaledArg.object = object;
    }
    return nativeValue.ref();
}
Also used : ArrayType(org.robovm.compiler.llvm.ArrayType) Invokestatic(org.robovm.compiler.trampoline.Invokestatic) Load(org.robovm.compiler.llvm.Load) Variable(org.robovm.compiler.llvm.Variable) StructureType(org.robovm.compiler.llvm.StructureType) Value(org.robovm.compiler.llvm.Value) Inttoptr(org.robovm.compiler.llvm.Inttoptr) PointerType(org.robovm.compiler.llvm.PointerType) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant)

Example 10 with StructureType

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

the class BroMethodCompiler method getLoType.

protected static String getLoType(final Type type, String base, int index, Map<String, String> structs) {
    if (type instanceof StructureType) {
        StringBuilder sb = new StringBuilder();
        StructureType st = (StructureType) type;
        sb.append("{");
        String name = String.format("%s_%04d", base, index);
        for (int i = 0; i < st.getTypeCount(); i++) {
            Type t = st.getTypeAt(i);
            if (i == 0 && t instanceof StructureType) {
                if (((StructureType) t).getTypeCount() == 0) {
                    // Skip empty structs as first member
                    continue;
                }
            }
            // Only support arrays embedded in structs
            StringBuilder dims = new StringBuilder();
            while (t instanceof ArrayType) {
                ArrayType at = (ArrayType) t;
                dims.append('[').append(at.getSize()).append(']');
                t = ((ArrayType) t).getElementType();
            }
            sb.append(getLoType(t, name, i, structs)).append(" m" + i).append(dims).append(";");
        }
        sb.append("}");
        structs.put(name, sb.toString());
        return "struct " + name;
    } else {
        return getHiType(type);
    }
}
Also used : ArrayType(org.robovm.compiler.llvm.ArrayType) RefType(soot.RefType) IntegerType(org.robovm.compiler.llvm.IntegerType) StructureType(org.robovm.compiler.llvm.StructureType) ArrayType(org.robovm.compiler.llvm.ArrayType) PointerType(org.robovm.compiler.llvm.PointerType) DoubleType(soot.DoubleType) FloatType(soot.FloatType) LongType(soot.LongType) Type(org.robovm.compiler.llvm.Type) AggregateType(org.robovm.compiler.llvm.AggregateType) PrimitiveType(org.robovm.compiler.llvm.PrimitiveType) PrimType(soot.PrimType) VoidType(soot.VoidType) FunctionType(org.robovm.compiler.llvm.FunctionType) StructureType(org.robovm.compiler.llvm.StructureType) Ptrtoint(org.robovm.compiler.llvm.Ptrtoint)

Aggregations

StructureType (org.robovm.compiler.llvm.StructureType)25 FunctionType (org.robovm.compiler.llvm.FunctionType)16 PointerType (org.robovm.compiler.llvm.PointerType)14 Test (org.junit.Test)10 ArrayType (org.robovm.compiler.llvm.ArrayType)8 PrimitiveType (org.robovm.compiler.llvm.PrimitiveType)8 Type (org.robovm.compiler.llvm.Type)8 Value (org.robovm.compiler.llvm.Value)7 Variable (org.robovm.compiler.llvm.Variable)6 LongType (soot.LongType)6 MarshalSite (org.robovm.compiler.MarshalerLookup.MarshalSite)5 MarshalerMethod (org.robovm.compiler.MarshalerLookup.MarshalerMethod)5 Function (org.robovm.compiler.llvm.Function)5 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)5 Load (org.robovm.compiler.llvm.Load)5 ArrayList (java.util.ArrayList)4 AggregateType (org.robovm.compiler.llvm.AggregateType)4 Bitcast (org.robovm.compiler.llvm.Bitcast)4 IntegerType (org.robovm.compiler.llvm.IntegerType)4 Ptrtoint (org.robovm.compiler.llvm.Ptrtoint)4