Search in sources :

Example 1 with MarshalerMethod

use of org.robovm.compiler.MarshalerLookup.MarshalerMethod in project robovm by robovm.

the class BridgeMethodCompiler method doCompile.

protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
    validateBridgeMethod(method);
    AnnotationTag bridgeAnnotation = getAnnotation(method, BRIDGE);
    boolean dynamic = readBooleanElem(bridgeAnnotation, "dynamic", false);
    boolean optional = readBooleanElem(bridgeAnnotation, "optional", false);
    boolean useCWrapper = requiresCWrapper(method);
    Function fn = createMethodFunction(method);
    moduleBuilder.addFunction(fn);
    Type[] parameterTypes = fn.getType().getParameterTypes();
    String[] parameterNames = fn.getParameterNames();
    ArrayList<Argument> args = new ArrayList<Argument>();
    for (int i = 0; i < parameterTypes.length; i++) {
        args.add(new Argument(new VariableRef(parameterNames[i], parameterTypes[i])));
    }
    VariableRef env = fn.getParameterRef(0);
    // Load the address of the resolved @Bridge method
    Variable targetFn = fn.newVariable(I8_PTR);
    if (!dynamic) {
        Global targetFnPtr = new Global(Symbols.bridgePtrSymbol(method), _private, new NullConstant(I8_PTR));
        moduleBuilder.addGlobal(targetFnPtr);
        fn.add(new Load(targetFn, targetFnPtr.ref()));
        Label nullLabel = new Label();
        Label notNullLabel = new Label();
        Variable nullCheck = fn.newVariable(I1);
        fn.add(new Icmp(nullCheck, Condition.eq, targetFn.ref(), new NullConstant(I8_PTR)));
        fn.add(new Br(nullCheck.ref(), fn.newBasicBlockRef(nullLabel), fn.newBasicBlockRef(notNullLabel)));
        fn.newBasicBlock(nullLabel);
        call(fn, optional ? BC_THROW_UNSATISIFED_LINK_ERROR_OPTIONAL_BRIDGE_NOT_BOUND : BC_THROW_UNSATISIFED_LINK_ERROR_BRIDGE_NOT_BOUND, env, moduleBuilder.getString(className), moduleBuilder.getString(method.getName()), moduleBuilder.getString(getDescriptor(method)));
        fn.add(new Unreachable());
        fn.newBasicBlock(notNullLabel);
    } else {
        // Dynamic @Bridge methods pass the target function pointer as a
        // long in the first parameter.
        fn.add(new Inttoptr(targetFn, fn.getParameterRef(1), targetFn.getType()));
        args.remove(1);
    }
    // Marshal args
    // Remove Env* from args
    args.remove(0);
    // Save the Object->handle mapping for each marshaled object. We need it
    // after the native call to call updateObject() on the marshaler for 
    // each value. Since the LLVM variables that store these values are used 
    // after the native call we get the nice side effect that neither the
    // Java objects nor the handles can be garbage collected while we're in
    // native code.
    List<MarshaledArg> marshaledArgs = new ArrayList<MarshaledArg>();
    FunctionType targetFnType = getBridgeFunctionType(method, dynamic, false);
    Type[] targetParameterTypes = targetFnType.getParameterTypes();
    if (!method.isStatic()) {
        MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, MarshalSite.RECEIVER));
        MarshaledArg marshaledArg = new MarshaledArg();
        marshaledArg.paramIndex = MarshalSite.RECEIVER;
        marshaledArgs.add(marshaledArg);
        Type nativeType = targetParameterTypes[0];
        Value nativeValue = marshalObjectToNative(fn, marshalerMethod, marshaledArg, useCWrapper ? I8_PTR : nativeType, env, args.get(0).getValue(), MarshalerFlags.CALL_TYPE_BRIDGE);
        args.set(0, new Argument(nativeValue));
    }
    for (int i = 0, argIdx = 0; i < method.getParameterCount(); i++) {
        if (dynamic && i == 0) {
            // Skip the target function pointer for dynamic bridge methods.
            continue;
        }
        if (!method.isStatic() && argIdx == 0) {
            // Skip the receiver in args. It doesn't correspond to a parameter.
            argIdx++;
        }
        soot.Type type = method.getParameterType(i);
        if (needsMarshaler(type)) {
            MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, i));
            // The return type of the marshaler's toNative() method is derived from the target function type.
            Type nativeType = targetParameterTypes[argIdx];
            if (nativeType instanceof PrimitiveType) {
                Value nativeValue = marshalValueObjectToNative(fn, marshalerMethod, nativeType, env, args.get(argIdx).getValue(), MarshalerFlags.CALL_TYPE_BRIDGE);
                args.set(argIdx, new Argument(nativeValue));
            } else {
                ParameterAttribute[] parameterAttributes = new ParameterAttribute[0];
                if (isPassByValue(method, i) || isStructRet(method, i)) {
                    // The parameter must not be null. We assume that Structs 
                    // never have a NULL handle so we just check that the Java
                    // Object isn't null.
                    call(fn, CHECK_NULL, env, args.get(argIdx).getValue());
                }
                MarshaledArg marshaledArg = new MarshaledArg();
                marshaledArg.paramIndex = i;
                marshaledArgs.add(marshaledArg);
                Value nativeValue = marshalObjectToNative(fn, marshalerMethod, marshaledArg, useCWrapper ? I8_PTR : nativeType, env, args.get(argIdx).getValue(), MarshalerFlags.CALL_TYPE_BRIDGE);
                args.set(argIdx, new Argument(nativeValue, parameterAttributes));
            }
        } else {
            args.set(argIdx, new Argument(marshalPrimitiveToNative(fn, method, i, args.get(argIdx).getValue())));
        }
        argIdx++;
    }
    Variable structResult = null;
    Value targetFnRef = null;
    if (useCWrapper) {
        args.add(0, new Argument(targetFn.ref()));
        if (targetFnType.getReturnType() instanceof StructureType) {
            // Allocate space on the stack big enough to hold the returned struct
            Variable tmp = fn.newVariable(new PointerType(targetFnType.getReturnType()));
            fn.add(new Alloca(tmp, targetFnType.getReturnType()));
            structResult = fn.newVariable(I8_PTR);
            fn.add(new Bitcast(structResult, tmp.ref(), I8_PTR));
            args.add(1, new Argument(structResult.ref()));
        }
        String wrapperName = Symbols.bridgeCSymbol(method);
        FunctionType wrapperFnType = getBridgeFunctionType(method, dynamic, true);
        getCWrapperFunctions().add(createBridgeCWrapper(targetFnType.getReturnType(), targetFnType.getParameterTypes(), wrapperFnType.getParameterTypes(), wrapperName));
        FunctionRef wrapperFnRef = getBridgeCWrapperRef(targetFnType, wrapperName);
        moduleBuilder.addFunctionDeclaration(new FunctionDeclaration(wrapperFnRef));
        targetFnRef = wrapperFnRef;
    } else {
        Variable tmp = fn.newVariable(targetFnType);
        fn.add(new Bitcast(tmp, targetFn.ref(), targetFnType));
        targetFnRef = tmp.ref();
    }
    // Execute the call to native code
    BasicBlockRef bbSuccess = fn.newBasicBlockRef(new Label("success"));
    BasicBlockRef bbFailure = fn.newBasicBlockRef(new Label("failure"));
    pushNativeFrame(fn);
    trycatchAllEnter(fn, env, bbSuccess, bbFailure);
    fn.newBasicBlock(bbSuccess.getLabel());
    Value result = callWithArguments(fn, targetFnRef, args);
    trycatchLeave(fn, env);
    popNativeFrame(fn);
    updateObject(method, fn, env, MarshalerFlags.CALL_TYPE_BRIDGE, marshaledArgs);
    // Marshal the return value
    if (needsMarshaler(method.getReturnType())) {
        MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
        String targetClassName = getInternalName(method.getReturnType());
        if (structResult != null) {
            // Copy to the heap.
            DataLayout dataLayout = config.getDataLayout();
            Value heapCopy = call(fn, BC_COPY_STRUCT, env, structResult.ref(), new IntegerConstant(dataLayout.getAllocSize(targetFnType.getReturnType())));
            result = marshalNativeToObject(fn, marshalerMethod, null, env, targetClassName, heapCopy, MarshalerFlags.CALL_TYPE_BRIDGE);
        } else if (targetFnType.getReturnType() instanceof PrimitiveType) {
            result = marshalNativeToValueObject(fn, marshalerMethod, env, targetClassName, result, MarshalerFlags.CALL_TYPE_BRIDGE);
        } else {
            result = marshalNativeToObject(fn, marshalerMethod, null, env, targetClassName, result, MarshalerFlags.CALL_TYPE_BRIDGE);
        }
    } else {
        result = marshalNativeToPrimitive(fn, method, result);
    }
    fn.add(new Ret(result));
    fn.newBasicBlock(bbFailure.getLabel());
    trycatchLeave(fn, env);
    popNativeFrame(fn);
    Value ex = call(fn, BC_EXCEPTION_CLEAR, env);
    // Call Marshaler.updateObject() for each object that was marshaled before
    // the call.
    updateObject(method, fn, env, MarshalerFlags.CALL_TYPE_BRIDGE, marshaledArgs);
    call(fn, BC_THROW, env, ex);
    fn.add(new Unreachable());
    return fn;
}
Also used : MarshalSite(org.robovm.compiler.MarshalerLookup.MarshalSite) ParameterAttribute(org.robovm.compiler.llvm.ParameterAttribute) Ret(org.robovm.compiler.llvm.Ret) VariableRef(org.robovm.compiler.llvm.VariableRef) Variable(org.robovm.compiler.llvm.Variable) Argument(org.robovm.compiler.llvm.Argument) ArrayList(java.util.ArrayList) Label(org.robovm.compiler.llvm.Label) Inttoptr(org.robovm.compiler.llvm.Inttoptr) PointerType(org.robovm.compiler.llvm.PointerType) Global(org.robovm.compiler.llvm.Global) AnnotationTag(soot.tagkit.AnnotationTag) 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) Load(org.robovm.compiler.llvm.Load) Alloca(org.robovm.compiler.llvm.Alloca) FunctionType(org.robovm.compiler.llvm.FunctionType) NullConstant(org.robovm.compiler.llvm.NullConstant) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Br(org.robovm.compiler.llvm.Br) 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) Bitcast(org.robovm.compiler.llvm.Bitcast) StructureType(org.robovm.compiler.llvm.StructureType) Value(org.robovm.compiler.llvm.Value) MarshalerMethod(org.robovm.compiler.MarshalerLookup.MarshalerMethod) PointerMarshalerMethod(org.robovm.compiler.MarshalerLookup.PointerMarshalerMethod) Icmp(org.robovm.compiler.llvm.Icmp)

Example 2 with MarshalerMethod

use of org.robovm.compiler.MarshalerLookup.MarshalerMethod 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 3 with MarshalerMethod

use of org.robovm.compiler.MarshalerLookup.MarshalerMethod in project robovm by robovm.

the class BroMethodCompiler method getReturnType.

private Type getReturnType(String anno, SootMethod method) {
    soot.Type sootType = method.getReturnType();
    if (hasPointerAnnotation(method)) {
        if (!sootType.equals(LongType.v())) {
            throw new IllegalArgumentException(anno + " annotated method " + method + " must return long when annotated with @Pointer");
        }
        return I8_PTR;
    }
    if (hasMachineSizedFloatAnnotation(method)) {
        if (!sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) {
            throw new IllegalArgumentException(anno + " annotated method " + method + " must return float or double when annotated with @MachineSizedFloat");
        }
        return config.getArch().is32Bit() ? FLOAT : DOUBLE;
    }
    if (hasMachineSizedSIntAnnotation(method) || hasMachineSizedUIntAnnotation(method)) {
        if (!sootType.equals(LongType.v())) {
            throw new IllegalArgumentException(anno + " annotated method " + method + " must return long when annotated with @MachineSizedSInt or @MachineSizedUInt");
        }
        return config.getArch().is32Bit() ? I32 : I64;
    }
    if (isStruct(sootType)) {
        if (!isPassByValue(method)) {
            // Structs are returned by reference by default
            return new PointerType(getStructType(sootType));
        }
        return getStructType(sootType);
    } else if (isNativeObject(sootType)) {
        // NativeObjects are always returned by reference.
        return I8_PTR;
    } else if (sootType instanceof PrimType || sootType == VoidType.v()) {
        return getType(sootType);
    }
    MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
    if (marshalerMethod instanceof ValueMarshalerMethod) {
        return ((ValueMarshalerMethod) marshalerMethod).getNativeType(config.getArch());
    } else {
        return I8_PTR;
    }
}
Also used : MarshalSite(org.robovm.compiler.MarshalerLookup.MarshalSite) ValueMarshalerMethod(org.robovm.compiler.MarshalerLookup.ValueMarshalerMethod) PrimType(soot.PrimType) PointerType(org.robovm.compiler.llvm.PointerType) MarshalerMethod(org.robovm.compiler.MarshalerLookup.MarshalerMethod) ValueMarshalerMethod(org.robovm.compiler.MarshalerLookup.ValueMarshalerMethod) ArrayMarshalerMethod(org.robovm.compiler.MarshalerLookup.ArrayMarshalerMethod)

Example 4 with MarshalerMethod

use of org.robovm.compiler.MarshalerLookup.MarshalerMethod in project robovm by robovm.

the class BridgeMethodCompiler method updateObject.

private void updateObject(SootMethod method, Function fn, Value env, long flags, List<MarshaledArg> marshaledArgs) {
    for (MarshaledArg value : marshaledArgs) {
        MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, value.paramIndex));
        SootMethod afterMethod = ((PointerMarshalerMethod) marshalerMethod).getAfterBridgeCallMethod();
        if (afterMethod != null) {
            Invokestatic invokestatic = new Invokestatic(getInternalName(method.getDeclaringClass()), getInternalName(afterMethod.getDeclaringClass()), afterMethod.getName(), getDescriptor(afterMethod));
            trampolines.add(invokestatic);
            call(fn, invokestatic.getFunctionRef(), env, value.object, value.handle, new IntegerConstant(flags));
        }
    }
}
Also used : MarshalSite(org.robovm.compiler.MarshalerLookup.MarshalSite) Invokestatic(org.robovm.compiler.trampoline.Invokestatic) PointerMarshalerMethod(org.robovm.compiler.MarshalerLookup.PointerMarshalerMethod) SootMethod(soot.SootMethod) MarshalerMethod(org.robovm.compiler.MarshalerLookup.MarshalerMethod) PointerMarshalerMethod(org.robovm.compiler.MarshalerLookup.PointerMarshalerMethod) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant)

Example 5 with MarshalerMethod

use of org.robovm.compiler.MarshalerLookup.MarshalerMethod in project robovm by robovm.

the class BroMethodCompiler method loadValueForGetter.

protected Value loadValueForGetter(SootMethod method, Function fn, Type memberType, Value memberPtr, Value env, boolean dereference, long flags) {
    soot.Type type = method.getReturnType();
    Value result = null;
    if (memberType instanceof StructureType) {
        // The member is a child struct contained in the current struct
        result = memberPtr;
    } else if (memberType instanceof ArrayType) {
        // The member is an array contained in the current struct
        result = memberPtr;
    } else if (dereference) {
        Variable tmp = fn.newVariable(memberType);
        fn.add(new Load(tmp, memberPtr));
        result = tmp.ref();
    } else {
        // Do not dereference the pointer but use it as is. This is needed for
        // global values such as _dispatch_main_q which is a struct and not a
        // pointer which we should load. We want the address of the struct.
        Variable tmp = fn.newVariable(memberType);
        fn.add(new Bitcast(tmp, memberPtr, tmp.getType()));
        result = tmp.ref();
    }
    if (needsMarshaler(type)) {
        MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
        String targetClassName = getInternalName(type);
        if (memberType instanceof PrimitiveType) {
            // Value type wrapping a primitive value (e.g. Enum, Integer and Bits)
            result = marshalNativeToValueObject(fn, marshalerMethod, env, targetClassName, result, flags);
        } else {
            if (memberType instanceof ArrayType) {
                // Array
                result = marshalNativeToArray(fn, marshalerMethod, env, targetClassName, result, flags, getArrayDimensions(method));
            } else {
                result = marshalNativeToObject(fn, marshalerMethod, null, env, targetClassName, result, flags);
            }
        }
    } else {
        result = marshalNativeToPrimitive(fn, method, result);
    }
    return result;
}
Also used : ArrayType(org.robovm.compiler.llvm.ArrayType) MarshalSite(org.robovm.compiler.MarshalerLookup.MarshalSite) Load(org.robovm.compiler.llvm.Load) Variable(org.robovm.compiler.llvm.Variable) Bitcast(org.robovm.compiler.llvm.Bitcast) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) StructureType(org.robovm.compiler.llvm.StructureType) Value(org.robovm.compiler.llvm.Value) PrimitiveType(org.robovm.compiler.llvm.PrimitiveType) MarshalerMethod(org.robovm.compiler.MarshalerLookup.MarshalerMethod) ValueMarshalerMethod(org.robovm.compiler.MarshalerLookup.ValueMarshalerMethod) ArrayMarshalerMethod(org.robovm.compiler.MarshalerLookup.ArrayMarshalerMethod)

Aggregations

MarshalSite (org.robovm.compiler.MarshalerLookup.MarshalSite)9 MarshalerMethod (org.robovm.compiler.MarshalerLookup.MarshalerMethod)9 StructureType (org.robovm.compiler.llvm.StructureType)6 ArrayMarshalerMethod (org.robovm.compiler.MarshalerLookup.ArrayMarshalerMethod)5 ValueMarshalerMethod (org.robovm.compiler.MarshalerLookup.ValueMarshalerMethod)5 PrimitiveType (org.robovm.compiler.llvm.PrimitiveType)5 PointerMarshalerMethod (org.robovm.compiler.MarshalerLookup.PointerMarshalerMethod)4 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)4 PointerType (org.robovm.compiler.llvm.PointerType)4 ArrayType (org.robovm.compiler.llvm.ArrayType)3 FunctionType (org.robovm.compiler.llvm.FunctionType)3 Type (org.robovm.compiler.llvm.Type)3 Value (org.robovm.compiler.llvm.Value)3 PrimType (soot.PrimType)3 SootMethod (soot.SootMethod)3 ArrayList (java.util.ArrayList)2 BasicBlockRef (org.robovm.compiler.llvm.BasicBlockRef)2 Bitcast (org.robovm.compiler.llvm.Bitcast)2 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)2 DataLayout (org.robovm.compiler.llvm.DataLayout)2