Search in sources :

Example 1 with Bitcast

use of org.robovm.compiler.llvm.Bitcast 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 Bitcast

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

the class MethodCompiler method assign.

private void assign(DefinitionStmt stmt) {
    /*
         * leftOp is either a Local, an ArrayRef or a FieldRef
         * rightOp is either a Local, a Ref, or an Expr
         */
    soot.Value rightOp = stmt.getRightOp();
    Value result;
    if (rightOp instanceof Immediate) {
        Immediate immediate = (Immediate) rightOp;
        result = immediate(stmt, immediate);
    } else if (rightOp instanceof ThisRef) {
        result = function.getParameterRef(1);
    } else if (rightOp instanceof ParameterRef) {
        ParameterRef ref = (ParameterRef) rightOp;
        int index = (sootMethod.isStatic() ? 1 : 2) + ref.getIndex();
        Value p = new VariableRef("p" + index, getType(ref.getType()));
        result = widenToI32Value(stmt, p, isUnsigned(ref.getType()));
    } else if (rightOp instanceof CaughtExceptionRef) {
        result = call(stmt, BC_EXCEPTION_CLEAR, env);
    } else if (rightOp instanceof ArrayRef) {
        ArrayRef ref = (ArrayRef) rightOp;
        VariableRef base = (VariableRef) immediate(stmt, (Immediate) ref.getBase());
        if (ref.getType() instanceof NullType) {
            // The base value is always null. Do a null check which will
            // always throw NPE.
            checkNull(stmt, base);
            return;
        } else {
            Value index = immediate(stmt, (Immediate) ref.getIndex());
            checkNull(stmt, base);
            checkBounds(stmt, base, index);
            result = call(stmt, getArrayLoad(ref.getType()), base, index);
            result = widenToI32Value(stmt, result, isUnsigned(ref.getType()));
        }
    } else if (rightOp instanceof InstanceFieldRef) {
        InstanceFieldRef ref = (InstanceFieldRef) rightOp;
        Value base = immediate(stmt, (Immediate) ref.getBase());
        checkNull(stmt, base);
        FunctionRef fn = null;
        if (canAccessDirectly(ref)) {
            fn = new FunctionRef(Symbols.getterSymbol(ref.getFieldRef()), new FunctionType(getType(ref.getType()), ENV_PTR, OBJECT_PTR));
        } else {
            soot.Type runtimeType = ref.getBase().getType();
            String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
            String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
            Trampoline trampoline = new GetField(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()), runtimeClassName);
            trampolines.add(trampoline);
            fn = trampoline.getFunctionRef();
        }
        result = call(stmt, fn, env, base);
        result = widenToI32Value(stmt, result, isUnsigned(ref.getType()));
    } else if (rightOp instanceof StaticFieldRef) {
        StaticFieldRef ref = (StaticFieldRef) rightOp;
        FunctionRef fn = config.isDebug() ? null : Intrinsics.getIntrinsic(sootMethod, stmt);
        if (fn == null) {
            if (canAccessDirectly(ref)) {
                fn = new FunctionRef(Symbols.getterSymbol(ref.getFieldRef()), new FunctionType(getType(ref.getType()), ENV_PTR));
            } else {
                String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
                Trampoline trampoline = new GetStatic(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()));
                trampolines.add(trampoline);
                fn = trampoline.getFunctionRef();
            }
        }
        result = call(stmt, fn, env);
        result = widenToI32Value(stmt, result, isUnsigned(ref.getType()));
    } else if (rightOp instanceof Expr) {
        if (rightOp instanceof BinopExpr) {
            BinopExpr expr = (BinopExpr) rightOp;
            Type rightType = getLocalType(expr.getType());
            Variable resultVar = function.newVariable(rightType);
            result = resultVar.ref();
            Value op1 = immediate(stmt, (Immediate) expr.getOp1());
            Value op2 = immediate(stmt, (Immediate) expr.getOp2());
            if (rightOp instanceof AddExpr) {
                if (rightType instanceof IntegerType) {
                    function.add(new Add(resultVar, op1, op2)).attach(stmt);
                } else {
                    function.add(new Fadd(resultVar, op1, op2)).attach(stmt);
                }
            } else if (rightOp instanceof AndExpr) {
                function.add(new And(resultVar, op1, op2)).attach(stmt);
            } else if (rightOp instanceof CmpExpr) {
                Variable t1 = function.newVariable(I1);
                Variable t2 = function.newVariable(I1);
                Variable t3 = function.newVariable(resultVar.getType());
                Variable t4 = function.newVariable(resultVar.getType());
                function.add(new Icmp(t1, Condition.slt, op1, op2)).attach(stmt);
                function.add(new Icmp(t2, Condition.sgt, op1, op2)).attach(stmt);
                function.add(new Zext(t3, new VariableRef(t1), resultVar.getType())).attach(stmt);
                function.add(new Zext(t4, new VariableRef(t2), resultVar.getType())).attach(stmt);
                function.add(new Sub(resultVar, new VariableRef(t4), new VariableRef(t3))).attach(stmt);
            } else if (rightOp instanceof DivExpr) {
                if (rightType instanceof IntegerType) {
                    FunctionRef f = rightType == I64 ? LDIV : IDIV;
                    result = call(stmt, f, env, op1, op2);
                } else {
                    // float or double
                    function.add(new Fdiv(resultVar, op1, op2)).attach(stmt);
                }
            } else if (rightOp instanceof MulExpr) {
                if (rightType instanceof IntegerType) {
                    function.add(new Mul(resultVar, op1, op2)).attach(stmt);
                } else {
                    function.add(new Fmul(resultVar, op1, op2)).attach(stmt);
                }
            } else if (rightOp instanceof OrExpr) {
                function.add(new Or(resultVar, op1, op2)).attach(stmt);
            } else if (rightOp instanceof RemExpr) {
                if (rightType instanceof IntegerType) {
                    FunctionRef f = rightType == I64 ? LREM : IREM;
                    result = call(stmt, f, env, op1, op2);
                } else {
                    FunctionRef f = rightType == DOUBLE ? DREM : FREM;
                    result = call(stmt, f, env, op1, op2);
                }
            } else if (rightOp instanceof ShlExpr || rightOp instanceof ShrExpr || rightOp instanceof UshrExpr) {
                IntegerType type = (IntegerType) op1.getType();
                int bits = type.getBits();
                Variable t = function.newVariable(op2.getType());
                function.add(new And(t, op2, new IntegerConstant(bits - 1, (IntegerType) op2.getType()))).attach(stmt);
                Value shift = t.ref();
                if (((IntegerType) shift.getType()).getBits() < bits) {
                    Variable tmp = function.newVariable(type);
                    function.add(new Zext(tmp, shift, type)).attach(stmt);
                    shift = tmp.ref();
                }
                if (rightOp instanceof ShlExpr) {
                    function.add(new Shl(resultVar, op1, shift)).attach(stmt);
                } else if (rightOp instanceof ShrExpr) {
                    function.add(new Ashr(resultVar, op1, shift)).attach(stmt);
                } else {
                    function.add(new Lshr(resultVar, op1, shift)).attach(stmt);
                }
            } else if (rightOp instanceof SubExpr) {
                if (rightType instanceof IntegerType) {
                    function.add(new Sub(resultVar, op1, op2)).attach(stmt);
                } else {
                    function.add(new Fsub(resultVar, op1, op2)).attach(stmt);
                }
            } else if (rightOp instanceof XorExpr) {
                function.add(new Xor(resultVar, op1, op2)).attach(stmt);
            } else if (rightOp instanceof XorExpr) {
                function.add(new Xor(resultVar, op1, op2)).attach(stmt);
            } else if (rightOp instanceof CmplExpr) {
                FunctionRef f = op1.getType() == FLOAT ? FCMPL : DCMPL;
                function.add(new Call(resultVar, f, op1, op2)).attach(stmt);
            } else if (rightOp instanceof CmpgExpr) {
                FunctionRef f = op1.getType() == FLOAT ? FCMPG : DCMPG;
                function.add(new Call(resultVar, f, op1, op2)).attach(stmt);
            } else {
                throw new IllegalArgumentException("Unknown type for rightOp: " + rightOp.getClass());
            }
        } else if (rightOp instanceof CastExpr) {
            Value op = immediate(stmt, (Immediate) ((CastExpr) rightOp).getOp());
            soot.Type sootTargetType = ((CastExpr) rightOp).getCastType();
            soot.Type sootSourceType = ((CastExpr) rightOp).getOp().getType();
            if (sootTargetType instanceof PrimType) {
                Type targetType = getType(sootTargetType);
                Type sourceType = getType(sootSourceType);
                if (targetType instanceof IntegerType && sourceType instanceof IntegerType) {
                    // op is at least I32 and has already been widened if source type had fewer bits then I32
                    IntegerType toType = (IntegerType) targetType;
                    IntegerType fromType = (IntegerType) op.getType();
                    Variable v = function.newVariable(toType);
                    if (fromType.getBits() < toType.getBits()) {
                        // Widening
                        if (isUnsigned(sootSourceType)) {
                            function.add(new Zext(v, op, toType)).attach(stmt);
                        } else {
                            function.add(new Sext(v, op, toType)).attach(stmt);
                        }
                    } else if (fromType.getBits() == toType.getBits()) {
                        function.add(new Bitcast(v, op, toType)).attach(stmt);
                    } else {
                        // Narrow
                        function.add(new Trunc(v, op, toType)).attach(stmt);
                    }
                    result = widenToI32Value(stmt, v.ref(), isUnsigned(sootTargetType));
                } else if (targetType instanceof FloatingPointType && sourceType instanceof IntegerType) {
                    // we always to a signed conversion since if op is char it has already been zero extended to I32
                    Variable v = function.newVariable(targetType);
                    function.add(new Sitofp(v, op, targetType)).attach(stmt);
                    result = v.ref();
                } else if (targetType instanceof FloatingPointType && sourceType instanceof FloatingPointType) {
                    Variable v = function.newVariable(targetType);
                    if (targetType == FLOAT && sourceType == DOUBLE) {
                        function.add(new Fptrunc(v, op, targetType)).attach(stmt);
                    } else if (targetType == DOUBLE && sourceType == FLOAT) {
                        function.add(new Fpext(v, op, targetType)).attach(stmt);
                    } else {
                        function.add(new Bitcast(v, op, targetType)).attach(stmt);
                    }
                    result = v.ref();
                } else {
                    // F2I, F2L, D2I, D2L
                    FunctionRef f = null;
                    if (targetType == I32 && sourceType == FLOAT) {
                        f = F2I;
                    } else if (targetType == I64 && sourceType == FLOAT) {
                        f = F2L;
                    } else if (targetType == I32 && sourceType == DOUBLE) {
                        f = D2I;
                    } else if (targetType == I64 && sourceType == DOUBLE) {
                        f = D2L;
                    } else {
                        throw new IllegalArgumentException();
                    }
                    Variable v = function.newVariable(targetType);
                    function.add(new Call(v, f, op)).attach(stmt);
                    result = v.ref();
                }
            } else {
                if (sootTargetType instanceof soot.ArrayType && ((soot.ArrayType) sootTargetType).getElementType() instanceof PrimType) {
                    soot.Type primType = ((soot.ArrayType) sootTargetType).getElementType();
                    GlobalRef arrayClassPtr = new GlobalRef("array_" + getDescriptor(primType), CLASS_PTR);
                    Variable arrayClass = function.newVariable(CLASS_PTR);
                    function.add(new Load(arrayClass, arrayClassPtr)).attach(stmt);
                    result = call(stmt, CHECKCAST_PRIM_ARRAY, env, arrayClass.ref(), op);
                } else {
                    String targetClassName = getInternalName(sootTargetType);
                    Trampoline trampoline = new Checkcast(this.className, targetClassName);
                    trampolines.add(trampoline);
                    result = call(stmt, trampoline.getFunctionRef(), env, op);
                }
            }
        } else if (rightOp instanceof InstanceOfExpr) {
            Value op = immediate(stmt, (Immediate) ((InstanceOfExpr) rightOp).getOp());
            soot.Type checkType = ((InstanceOfExpr) rightOp).getCheckType();
            if (checkType instanceof soot.ArrayType && ((soot.ArrayType) checkType).getElementType() instanceof PrimType) {
                soot.Type primType = ((soot.ArrayType) checkType).getElementType();
                GlobalRef arrayClassPtr = new GlobalRef("array_" + getDescriptor(primType), CLASS_PTR);
                Variable arrayClass = function.newVariable(CLASS_PTR);
                function.add(new Load(arrayClass, arrayClassPtr)).attach(stmt);
                result = call(stmt, INSTANCEOF_PRIM_ARRAY, env, arrayClass.ref(), op);
            } else {
                String targetClassName = getInternalName(checkType);
                Trampoline trampoline = new Instanceof(this.className, targetClassName);
                trampolines.add(trampoline);
                result = call(stmt, trampoline.getFunctionRef(), env, op);
            }
        } else if (rightOp instanceof NewExpr) {
            String targetClassName = getInternalName(((NewExpr) rightOp).getBaseType());
            FunctionRef fn = null;
            if (targetClassName.equals(this.className)) {
                fn = FunctionBuilder.allocator(sootMethod.getDeclaringClass()).ref();
            } else {
                Trampoline trampoline = new New(this.className, targetClassName);
                trampolines.add(trampoline);
                fn = trampoline.getFunctionRef();
            }
            result = call(stmt, fn, env);
        } else if (rightOp instanceof NewArrayExpr) {
            NewArrayExpr expr = (NewArrayExpr) rightOp;
            Value size = immediate(stmt, (Immediate) expr.getSize());
            if (expr.getBaseType() instanceof PrimType) {
                result = call(stmt, getNewArray(expr.getBaseType()), env, size);
            } else {
                String targetClassName = getInternalName(expr.getType());
                Trampoline trampoline = new Anewarray(this.className, targetClassName);
                trampolines.add(trampoline);
                result = call(stmt, trampoline.getFunctionRef(), env, size);
            }
        } else if (rightOp instanceof NewMultiArrayExpr) {
            NewMultiArrayExpr expr = (NewMultiArrayExpr) rightOp;
            if (expr.getBaseType().numDimensions == 1 && expr.getBaseType().getElementType() instanceof PrimType) {
                Value size = immediate(stmt, (Immediate) expr.getSize(0));
                result = call(stmt, getNewArray(expr.getBaseType().getElementType()), env, size);
            } else {
                for (int i = 0; i < expr.getSizeCount(); i++) {
                    Value size = immediate(stmt, (Immediate) expr.getSize(i));
                    Variable ptr = function.newVariable(new PointerType(I32));
                    function.add(new Getelementptr(ptr, dims.ref(), 0, i)).attach(stmt);
                    function.add(new Store(size, ptr.ref())).attach(stmt);
                }
                Variable dimsI32 = function.newVariable(new PointerType(I32));
                function.add(new Bitcast(dimsI32, dims.ref(), dimsI32.getType())).attach(stmt);
                String targetClassName = getInternalName(expr.getType());
                Trampoline trampoline = new Multianewarray(this.className, targetClassName);
                trampolines.add(trampoline);
                result = call(stmt, trampoline.getFunctionRef(), env, new IntegerConstant(expr.getSizeCount()), dimsI32.ref());
            }
        } else if (rightOp instanceof InvokeExpr) {
            result = invokeExpr(stmt, (InvokeExpr) rightOp);
        } else if (rightOp instanceof LengthExpr) {
            Value op = immediate(stmt, (Immediate) ((LengthExpr) rightOp).getOp());
            checkNull(stmt, op);
            Variable v = function.newVariable(I32);
            function.add(new Call(v, ARRAY_LENGTH, op)).attach(stmt);
            result = v.ref();
        } else if (rightOp instanceof NegExpr) {
            NegExpr expr = (NegExpr) rightOp;
            Value op = immediate(stmt, (Immediate) expr.getOp());
            Type rightType = op.getType();
            Variable v = function.newVariable(op.getType());
            if (rightType instanceof IntegerType) {
                function.add(new Sub(v, new IntegerConstant(0, (IntegerType) rightType), op)).attach(stmt);
            } else {
                function.add(new Fmul(v, new FloatingPointConstant(-1.0, (FloatingPointType) rightType), op)).attach(stmt);
            }
            result = v.ref();
        } else {
            throw new IllegalArgumentException("Unknown type for rightOp: " + rightOp.getClass());
        }
    } else {
        throw new IllegalArgumentException("Unknown type for rightOp: " + rightOp.getClass());
    }
    soot.Value leftOp = stmt.getLeftOp();
    if (leftOp instanceof Local) {
        Local local = (Local) leftOp;
        VariableRef v = new VariableRef(local.getName(), new PointerType(getLocalType(leftOp.getType())));
        function.add(new Store(result, v, !sootMethod.getActiveBody().getTraps().isEmpty())).attach(stmt);
    } else {
        Type leftType = getType(leftOp.getType());
        Value narrowedResult = narrowFromI32Value(stmt, leftType, result);
        if (leftOp instanceof ArrayRef) {
            ArrayRef ref = (ArrayRef) leftOp;
            VariableRef base = (VariableRef) immediate(stmt, (Immediate) ref.getBase());
            Value index = immediate(stmt, (Immediate) ref.getIndex());
            checkNull(stmt, base);
            checkBounds(stmt, base, index);
            if (leftOp.getType() instanceof RefLikeType) {
                call(stmt, BC_SET_OBJECT_ARRAY_ELEMENT, env, base, index, narrowedResult);
            } else {
                call(stmt, getArrayStore(leftOp.getType()), base, index, narrowedResult);
            }
        } else if (leftOp instanceof InstanceFieldRef) {
            InstanceFieldRef ref = (InstanceFieldRef) leftOp;
            Value base = immediate(stmt, (Immediate) ref.getBase());
            checkNull(stmt, base);
            FunctionRef fn = null;
            if (canAccessDirectly(ref)) {
                fn = new FunctionRef(Symbols.setterSymbol(ref.getFieldRef()), new FunctionType(VOID, ENV_PTR, OBJECT_PTR, getType(ref.getType())));
            } else {
                soot.Type runtimeType = ref.getBase().getType();
                String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
                String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
                Trampoline trampoline = new PutField(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()), runtimeClassName);
                trampolines.add(trampoline);
                fn = trampoline.getFunctionRef();
            }
            call(stmt, fn, env, base, narrowedResult);
        } else if (leftOp instanceof StaticFieldRef) {
            StaticFieldRef ref = (StaticFieldRef) leftOp;
            FunctionRef fn = null;
            if (canAccessDirectly(ref)) {
                fn = new FunctionRef(Symbols.setterSymbol(ref.getFieldRef()), new FunctionType(VOID, ENV_PTR, getType(ref.getType())));
            } else {
                String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
                Trampoline trampoline = new PutStatic(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()));
                trampolines.add(trampoline);
                fn = trampoline.getFunctionRef();
            }
            call(stmt, fn, env, narrowedResult);
        } else {
            throw new IllegalArgumentException("Unknown type for leftOp: " + leftOp.getClass());
        }
    }
}
Also used : Add(org.robovm.compiler.llvm.Add) AndExpr(soot.jimple.AndExpr) New(org.robovm.compiler.trampoline.New) Or(org.robovm.compiler.llvm.Or) Store(org.robovm.compiler.llvm.Store) FloatingPointType(org.robovm.compiler.llvm.FloatingPointType) ArrayType(org.robovm.compiler.llvm.ArrayType) RefLikeType(soot.RefLikeType) GetStatic(org.robovm.compiler.trampoline.GetStatic) InterfaceInvokeExpr(soot.jimple.InterfaceInvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) Shl(org.robovm.compiler.llvm.Shl) CastExpr(soot.jimple.CastExpr) PrimType(soot.PrimType) Fsub(org.robovm.compiler.llvm.Fsub) ShlExpr(soot.jimple.ShlExpr) Checkcast(org.robovm.compiler.trampoline.Checkcast) FunctionRef(org.robovm.compiler.llvm.FunctionRef) Fmul(org.robovm.compiler.llvm.Fmul) Sub(org.robovm.compiler.llvm.Sub) GetField(org.robovm.compiler.trampoline.GetField) Load(org.robovm.compiler.llvm.Load) FloatingPointConstant(org.robovm.compiler.llvm.FloatingPointConstant) Mul(org.robovm.compiler.llvm.Mul) XorExpr(soot.jimple.XorExpr) Fptrunc(org.robovm.compiler.llvm.Fptrunc) Local(soot.Local) AddExpr(soot.jimple.AddExpr) Fdiv(org.robovm.compiler.llvm.Fdiv) Zext(org.robovm.compiler.llvm.Zext) InstanceOfExpr(soot.jimple.InstanceOfExpr) OrExpr(soot.jimple.OrExpr) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) StaticFieldRef(soot.jimple.StaticFieldRef) NegExpr(soot.jimple.NegExpr) UshrExpr(soot.jimple.UshrExpr) InterfaceInvokeExpr(soot.jimple.InterfaceInvokeExpr) GeExpr(soot.jimple.GeExpr) DivExpr(soot.jimple.DivExpr) ConditionExpr(soot.jimple.ConditionExpr) SubExpr(soot.jimple.SubExpr) NewMultiArrayExpr(soot.jimple.NewMultiArrayExpr) OrExpr(soot.jimple.OrExpr) Expr(soot.jimple.Expr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) LengthExpr(soot.jimple.LengthExpr) ShlExpr(soot.jimple.ShlExpr) NeExpr(soot.jimple.NeExpr) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) CmpExpr(soot.jimple.CmpExpr) MulExpr(soot.jimple.MulExpr) BinopExpr(soot.jimple.BinopExpr) LtExpr(soot.jimple.LtExpr) ShrExpr(soot.jimple.ShrExpr) CmpgExpr(soot.jimple.CmpgExpr) EqExpr(soot.jimple.EqExpr) NewArrayExpr(soot.jimple.NewArrayExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) AndExpr(soot.jimple.AndExpr) LeExpr(soot.jimple.LeExpr) CastExpr(soot.jimple.CastExpr) InvokeExpr(soot.jimple.InvokeExpr) NewExpr(soot.jimple.NewExpr) CmplExpr(soot.jimple.CmplExpr) InstanceOfExpr(soot.jimple.InstanceOfExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) RemExpr(soot.jimple.RemExpr) XorExpr(soot.jimple.XorExpr) AddExpr(soot.jimple.AddExpr) GtExpr(soot.jimple.GtExpr) Bitcast(org.robovm.compiler.llvm.Bitcast) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) NewArrayExpr(soot.jimple.NewArrayExpr) And(org.robovm.compiler.llvm.And) CmpExpr(soot.jimple.CmpExpr) RemExpr(soot.jimple.RemExpr) ShrExpr(soot.jimple.ShrExpr) Value(org.robovm.compiler.llvm.Value) NewExpr(soot.jimple.NewExpr) Fadd(org.robovm.compiler.llvm.Fadd) Xor(org.robovm.compiler.llvm.Xor) NullType(soot.NullType) CmplExpr(soot.jimple.CmplExpr) BinopExpr(soot.jimple.BinopExpr) MulExpr(soot.jimple.MulExpr) GlobalRef(org.robovm.compiler.llvm.GlobalRef) VariableRef(org.robovm.compiler.llvm.VariableRef) Variable(org.robovm.compiler.llvm.Variable) Ashr(org.robovm.compiler.llvm.Ashr) CaughtExceptionRef(soot.jimple.CaughtExceptionRef) NewMultiArrayExpr(soot.jimple.NewMultiArrayExpr) Sext(org.robovm.compiler.llvm.Sext) NegExpr(soot.jimple.NegExpr) PointerType(org.robovm.compiler.llvm.PointerType) Getelementptr(org.robovm.compiler.llvm.Getelementptr) Multianewarray(org.robovm.compiler.trampoline.Multianewarray) UshrExpr(soot.jimple.UshrExpr) ArrayRef(soot.jimple.ArrayRef) Lshr(org.robovm.compiler.llvm.Lshr) InstanceFieldRef(soot.jimple.InstanceFieldRef) Trunc(org.robovm.compiler.llvm.Trunc) ConstantTrunc(org.robovm.compiler.llvm.ConstantTrunc) Instanceof(org.robovm.compiler.trampoline.Instanceof) Sitofp(org.robovm.compiler.llvm.Sitofp) PutField(org.robovm.compiler.trampoline.PutField) Call(org.robovm.compiler.llvm.Call) Trampoline(org.robovm.compiler.trampoline.Trampoline) LengthExpr(soot.jimple.LengthExpr) Immediate(soot.Immediate) FunctionType(org.robovm.compiler.llvm.FunctionType) SubExpr(soot.jimple.SubExpr) Anewarray(org.robovm.compiler.trampoline.Anewarray) PutStatic(org.robovm.compiler.trampoline.PutStatic) IntegerType(org.robovm.compiler.llvm.IntegerType) FloatingPointType(org.robovm.compiler.llvm.FloatingPointType) IntegerType(org.robovm.compiler.llvm.IntegerType) PointerType(org.robovm.compiler.llvm.PointerType) NullType(soot.NullType) FunctionType(org.robovm.compiler.llvm.FunctionType) ArrayType(org.robovm.compiler.llvm.ArrayType) CharType(soot.CharType) RefLikeType(soot.RefLikeType) Type(org.robovm.compiler.llvm.Type) PrimType(soot.PrimType) DivExpr(soot.jimple.DivExpr) ParameterRef(soot.jimple.ParameterRef) ThisRef(soot.jimple.ThisRef) CmpgExpr(soot.jimple.CmpgExpr) Fpext(org.robovm.compiler.llvm.Fpext) Icmp(org.robovm.compiler.llvm.Icmp)

Example 3 with Bitcast

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

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

the class MethodCompiler method doCompile.

protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
    function = createMethodFunction(method);
    moduleBuilder.addFunction(function);
    this.moduleBuilder = moduleBuilder;
    env = function.getParameterRef(0);
    trapsAt = new HashMap<Unit, List<Trap>>();
    Body body = method.retrieveActiveBody();
    NopStmt prependedNop = null;
    if (method.isStatic() && !body.getUnits().getFirst().getBoxesPointingToThis().isEmpty()) {
        // Fix for issue #1. This prevents an NPE in Soot's ArrayBoundsCheckerAnalysis. The NPE
        // occurs for static methods which start with a unit that is the target of some other
        // unit. We work around this by inserting a nop statement as the first unit in such 
        // methods. See http://www.sable.mcgill.ca/listarchives/soot-list/msg01397.html.
        Unit insertionPoint = body.getUnits().getFirst();
        prependedNop = Jimple.v().newNopStmt();
        body.getUnits().getNonPatchingChain().insertBefore(prependedNop, insertionPoint);
    }
    PackManager.v().getPack("jtp").apply(body);
    PackManager.v().getPack("jop").apply(body);
    PackManager.v().getPack("jap").apply(body);
    if (body.getUnits().getFirst() == prependedNop && prependedNop.getBoxesPointingToThis().isEmpty()) {
        // Remove the nop we inserted above to work around the bug in Soot's 
        // ArrayBoundsCheckerAnalysis which has now been run.
        body.getUnits().getNonPatchingChain().removeFirst();
    }
    PatchingChain<Unit> units = body.getUnits();
    Map<Unit, List<Unit>> branchTargets = getBranchTargets(body);
    Map<Unit, Integer> trapHandlers = getTrapHandlers(body);
    Map<Unit, Integer> selChanges = new HashMap<Unit, Integer>();
    int multiANewArrayMaxDims = 0;
    Set<Local> locals = new HashSet<Local>();
    boolean emitCheckStackOverflow = false;
    for (Unit unit : units) {
        if (unit instanceof DefinitionStmt) {
            DefinitionStmt stmt = (DefinitionStmt) unit;
            if (stmt.getLeftOp() instanceof Local) {
                Local local = (Local) stmt.getLeftOp();
                if (!locals.contains(local)) {
                    Type type = getLocalType(local.getType());
                    Alloca alloca = new Alloca(function.newVariable(local.getName(), type), type);
                    alloca.attach(local);
                    function.add(alloca);
                    locals.add(local);
                }
            }
            if (stmt.getRightOp() instanceof NewMultiArrayExpr) {
                NewMultiArrayExpr expr = (NewMultiArrayExpr) stmt.getRightOp();
                multiANewArrayMaxDims = Math.max(multiANewArrayMaxDims, expr.getSizeCount());
            }
            if (stmt.getRightOp() instanceof InvokeExpr) {
                emitCheckStackOverflow = true;
            }
        }
        if (unit instanceof InvokeStmt) {
            emitCheckStackOverflow = true;
        }
    }
    dims = null;
    if (multiANewArrayMaxDims > 0) {
        dims = function.newVariable("dims", new PointerType(new ArrayType(multiANewArrayMaxDims, I32)));
        function.add(new Alloca(dims, new ArrayType(multiANewArrayMaxDims, I32)));
    }
    if (emitCheckStackOverflow) {
        call(CHECK_STACK_OVERFLOW);
    }
    Value trycatchContext = null;
    if (!body.getTraps().isEmpty()) {
        List<List<Trap>> recordedTraps = new ArrayList<List<Trap>>();
        for (Unit unit : units) {
            // Calculate the predecessor units of unit 
            Set<Unit> incoming = new HashSet<Unit>();
            if (units.getFirst() != unit && units.getPredOf(unit).fallsThrough()) {
                incoming.add(units.getPredOf(unit));
            }
            if (branchTargets.keySet().contains(unit)) {
                incoming.addAll(branchTargets.get(unit));
            }
            if (unit == units.getFirst() || trapHandlers.containsKey(unit) || trapsDiffer(unit, incoming)) {
                List<Trap> traps = getTrapsAt(unit);
                if (traps.isEmpty()) {
                    selChanges.put(unit, 0);
                } else {
                    int index = recordedTraps.indexOf(traps);
                    if (index == -1) {
                        index = recordedTraps.size();
                        recordedTraps.add(traps);
                    }
                    selChanges.put(unit, index + 1);
                }
            }
        }
        StructureConstantBuilder landingPadsPtrs = new StructureConstantBuilder();
        for (List<Trap> traps : recordedTraps) {
            StructureConstantBuilder landingPads = new StructureConstantBuilder();
            for (Trap trap : traps) {
                SootClass exClass = trap.getException();
                StructureConstantBuilder landingPad = new StructureConstantBuilder();
                if ("java.lang.Throwable".equals(exClass.getName()) || exClass.isPhantom()) {
                    landingPad.add(new NullConstant(I8_PTR));
                } else {
                    catches.add(getInternalName(exClass));
                    if (exClass == sootClass) {
                        /*
                             * The class being compiled is an exception class
                             * with a catch clause which catches itself. We
                             * cannot reference the info struct directly since
                             * we don't know the type of it and it hasn't been
                             * emitted by ClassCompiler yet. Use the internal
                             * i8* alias instead which ClassCompiler will emit.
                             * See #1007.
                             */
                        landingPad.add(new AliasRef(Symbols.infoStructSymbol(getInternalName(exClass)) + "_i8ptr", I8_PTR));
                    } else {
                        Global g = new Global(Symbols.infoStructSymbol(getInternalName(exClass)), I8_PTR, true);
                        if (!moduleBuilder.hasSymbol(g.getName())) {
                            moduleBuilder.addGlobal(g);
                        }
                        landingPad.add(g.ref());
                    }
                }
                landingPad.add(new IntegerConstant(trapHandlers.get(trap.getHandlerUnit()) + 1));
                landingPads.add(landingPad.build());
            }
            landingPads.add(new StructureConstantBuilder().add(new NullConstant(I8_PTR)).add(new IntegerConstant(0)).build());
            Global g = moduleBuilder.newGlobal(landingPads.build(), true);
            landingPadsPtrs.add(new ConstantBitcast(g.ref(), I8_PTR));
        }
        Global g = moduleBuilder.newGlobal(landingPadsPtrs.build(), true);
        Variable ctx = function.newVariable(TRYCATCH_CONTEXT_PTR);
        Variable bcCtx = function.newVariable(BC_TRYCATCH_CONTEXT_PTR);
        function.add(new Alloca(bcCtx, BC_TRYCATCH_CONTEXT));
        Variable selPtr = function.newVariable(new PointerType(I32));
        function.add(new Getelementptr(selPtr, bcCtx.ref(), 0, 0, 1));
        function.add(new Store(new IntegerConstant(0), selPtr.ref()));
        Variable bcCtxLandingPadsPtr = function.newVariable(I8_PTR_PTR);
        function.add(new Getelementptr(bcCtxLandingPadsPtr, bcCtx.ref(), 0, 1));
        function.add(new Store(new ConstantBitcast(g.ref(), I8_PTR), bcCtxLandingPadsPtr.ref()));
        function.add(new Bitcast(ctx, bcCtx.ref(), TRYCATCH_CONTEXT_PTR));
        trycatchContext = ctx.ref();
        Value result = call(RVM_TRYCATCH_ENTER, env, trycatchContext);
        Map<IntegerConstant, BasicBlockRef> alt = new TreeMap<IntegerConstant, BasicBlockRef>();
        for (Entry<Unit, Integer> entry : trapHandlers.entrySet()) {
            alt.put(new IntegerConstant(entry.getValue() + 1), function.newBasicBlockRef(new Label(entry.getKey())));
        }
        function.add(new Switch(result, function.newBasicBlockRef(new Label(units.getFirst())), alt));
        if (!branchTargets.containsKey(units.getFirst())) {
            function.newBasicBlock(new Label(units.getFirst()));
        }
    }
    if ("<clinit>".equals(method.getName())) {
        initializeClassFields();
    }
    for (Unit unit : units) {
        if (branchTargets.containsKey(unit) || trapHandlers.containsKey(unit)) {
            BasicBlock oldBlock = function.getCurrentBasicBlock();
            function.newBasicBlock(new Label(unit));
            if (oldBlock != null) {
                Instruction last = oldBlock.last();
                if (last == null || !isTerminator(last)) {
                    oldBlock.add(new Br(function.newBasicBlockRef(new Label(unit))));
                }
            }
        }
        if (selChanges.containsKey(unit)) {
            int sel = selChanges.get(unit);
            // trycatchContext->sel = sel
            Variable selPtr = function.newVariable(new PointerType(I32));
            function.add(new Getelementptr(selPtr, trycatchContext, 0, 1)).attach(unit);
            function.add(new Store(new IntegerConstant(sel), selPtr.ref())).attach(unit);
        }
        if (unit instanceof DefinitionStmt) {
            assign((DefinitionStmt) unit);
        } else if (unit instanceof ReturnStmt) {
            if (!body.getTraps().isEmpty()) {
                trycatchLeave(function);
            }
            return_((ReturnStmt) unit);
        } else if (unit instanceof ReturnVoidStmt) {
            if (!body.getTraps().isEmpty()) {
                trycatchLeave(function);
            }
            returnVoid((ReturnVoidStmt) unit);
        } else if (unit instanceof IfStmt) {
            if_((IfStmt) unit);
        } else if (unit instanceof LookupSwitchStmt) {
            lookupSwitch((LookupSwitchStmt) unit);
        } else if (unit instanceof TableSwitchStmt) {
            tableSwitch((TableSwitchStmt) unit);
        } else if (unit instanceof GotoStmt) {
            goto_((GotoStmt) unit);
        } else if (unit instanceof ThrowStmt) {
            throw_((ThrowStmt) unit);
        } else if (unit instanceof InvokeStmt) {
            invoke((InvokeStmt) unit);
        } else if (unit instanceof EnterMonitorStmt) {
            enterMonitor((EnterMonitorStmt) unit);
        } else if (unit instanceof ExitMonitorStmt) {
            exitMonitor((ExitMonitorStmt) unit);
        } else if (unit instanceof NopStmt) {
            nop((NopStmt) unit);
        } else {
            throw new IllegalArgumentException("Unknown Unit type: " + unit.getClass());
        }
    }
    if (this.className.equals("java/lang/Object") && "<init>".equals(method.getName())) {
        // If it is the object will be registered for finalization.
        for (BasicBlock bb : function.getBasicBlocks()) {
            if (bb.last() instanceof Ret) {
                // Insert a call to register_finalizable() before this ret
                Call call = new Call(REGISTER_FINALIZABLE, env, function.getParameterRef(1));
                call.attach(bb.last().getAttachment(Unit.class));
                bb.insertBefore(bb.last(), call);
            }
        }
    }
    return function;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Label(org.robovm.compiler.llvm.Label) Store(org.robovm.compiler.llvm.Store) Unit(soot.Unit) Instruction(org.robovm.compiler.llvm.Instruction) Global(org.robovm.compiler.llvm.Global) ArrayType(org.robovm.compiler.llvm.ArrayType) TableSwitchStmt(soot.jimple.TableSwitchStmt) InterfaceInvokeExpr(soot.jimple.InterfaceInvokeExpr) SpecialInvokeExpr(soot.jimple.SpecialInvokeExpr) InstanceInvokeExpr(soot.jimple.InstanceInvokeExpr) VirtualInvokeExpr(soot.jimple.VirtualInvokeExpr) InvokeExpr(soot.jimple.InvokeExpr) StaticInvokeExpr(soot.jimple.StaticInvokeExpr) GotoStmt(soot.jimple.GotoStmt) ArrayList(java.util.ArrayList) List(java.util.List) EnterMonitorStmt(soot.jimple.EnterMonitorStmt) HashSet(java.util.HashSet) BasicBlock(org.robovm.compiler.llvm.BasicBlock) Local(soot.Local) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Switch(org.robovm.compiler.llvm.Switch) Bitcast(org.robovm.compiler.llvm.Bitcast) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) Value(org.robovm.compiler.llvm.Value) DefinitionStmt(soot.jimple.DefinitionStmt) ReturnStmt(soot.jimple.ReturnStmt) ThrowStmt(soot.jimple.ThrowStmt) ExitMonitorStmt(soot.jimple.ExitMonitorStmt) Variable(org.robovm.compiler.llvm.Variable) InvokeStmt(soot.jimple.InvokeStmt) AliasRef(org.robovm.compiler.llvm.AliasRef) NewMultiArrayExpr(soot.jimple.NewMultiArrayExpr) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) ReturnVoidStmt(soot.jimple.ReturnVoidStmt) PointerType(org.robovm.compiler.llvm.PointerType) Getelementptr(org.robovm.compiler.llvm.Getelementptr) BasicBlockRef(org.robovm.compiler.llvm.BasicBlockRef) Body(soot.Body) Call(org.robovm.compiler.llvm.Call) Alloca(org.robovm.compiler.llvm.Alloca) NullConstant(org.robovm.compiler.llvm.NullConstant) Trap(soot.Trap) LookupSwitchStmt(soot.jimple.LookupSwitchStmt) SootClass(soot.SootClass) TreeMap(java.util.TreeMap) Br(org.robovm.compiler.llvm.Br) FloatingPointType(org.robovm.compiler.llvm.FloatingPointType) IntegerType(org.robovm.compiler.llvm.IntegerType) PointerType(org.robovm.compiler.llvm.PointerType) NullType(soot.NullType) FunctionType(org.robovm.compiler.llvm.FunctionType) ArrayType(org.robovm.compiler.llvm.ArrayType) CharType(soot.CharType) RefLikeType(soot.RefLikeType) Type(org.robovm.compiler.llvm.Type) PrimType(soot.PrimType) IfStmt(soot.jimple.IfStmt) NopStmt(soot.jimple.NopStmt)

Example 5 with Bitcast

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

the class Types method getFieldPtr.

public static Value getFieldPtr(Function f, Value base, Constant offset, Type fieldType) {
    Variable baseI8Ptr = f.newVariable(I8_PTR);
    f.add(new Bitcast(baseI8Ptr, base, I8_PTR));
    Variable fieldI8Ptr = f.newVariable(I8_PTR);
    f.add(new Getelementptr(fieldI8Ptr, baseI8Ptr.ref(), offset));
    Variable fieldPtr = f.newVariable(new PointerType(fieldType));
    f.add(new Bitcast(fieldPtr, fieldI8Ptr.ref(), fieldPtr.getType()));
    return fieldPtr.ref();
}
Also used : Variable(org.robovm.compiler.llvm.Variable) Bitcast(org.robovm.compiler.llvm.Bitcast) ConstantGetelementptr(org.robovm.compiler.llvm.ConstantGetelementptr) Getelementptr(org.robovm.compiler.llvm.Getelementptr) PointerType(org.robovm.compiler.llvm.PointerType)

Aggregations

Bitcast (org.robovm.compiler.llvm.Bitcast)9 Variable (org.robovm.compiler.llvm.Variable)9 Value (org.robovm.compiler.llvm.Value)8 PointerType (org.robovm.compiler.llvm.PointerType)7 Getelementptr (org.robovm.compiler.llvm.Getelementptr)6 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)6 Load (org.robovm.compiler.llvm.Load)6 Ret (org.robovm.compiler.llvm.Ret)6 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)5 Function (org.robovm.compiler.llvm.Function)5 Br (org.robovm.compiler.llvm.Br)4 FunctionType (org.robovm.compiler.llvm.FunctionType)4 Icmp (org.robovm.compiler.llvm.Icmp)4 Label (org.robovm.compiler.llvm.Label)4 StructureType (org.robovm.compiler.llvm.StructureType)4 Type (org.robovm.compiler.llvm.Type)4 ArrayList (java.util.ArrayList)3 ArrayType (org.robovm.compiler.llvm.ArrayType)3 FloatingPointType (org.robovm.compiler.llvm.FloatingPointType)3 FunctionRef (org.robovm.compiler.llvm.FunctionRef)3