Search in sources :

Example 11 with FunctionType

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

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

the class MethodCompiler method ldcString.

private FunctionRef ldcString(String s) {
    byte[] modUtf8 = stringToModifiedUtf8Z(s);
    FunctionRef fref = new FunctionRef(Symbols.ldcStringSymbol(modUtf8), new FunctionType(OBJECT_PTR, ENV_PTR));
    if (moduleBuilder.hasSymbol(fref.getName())) {
        return fref;
    }
    Global g = new Global(Symbols.ldcStringPtrSymbol(modUtf8), weak, new NullConstant(OBJECT_PTR));
    moduleBuilder.addGlobal(g);
    Function f = new FunctionBuilder(fref).linkage(weak).build();
    moduleBuilder.addFunction(f);
    Value result = Functions.call(f, BC_LDC_STRING, f.getParameterRef(0), g.ref(), moduleBuilder.getString(s), new IntegerConstant(s.length()));
    f.add(new Ret(result));
    return fref;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) Function(org.robovm.compiler.llvm.Function) FunctionType(org.robovm.compiler.llvm.FunctionType) Value(org.robovm.compiler.llvm.Value) NullConstant(org.robovm.compiler.llvm.NullConstant) Global(org.robovm.compiler.llvm.Global) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Example 13 with FunctionType

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

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

the class MethodCompiler method call.

private Value call(Unit unit, Value fn, Value... args) {
    Variable result = null;
    Type returnType = ((FunctionType) fn.getType()).getReturnType();
    if (returnType != VOID) {
        result = function.newVariable(returnType);
    }
    function.add(new Call(result, fn, args)).attach(unit);
    return result == null ? null : result.ref();
}
Also used : Call(org.robovm.compiler.llvm.Call) 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) Variable(org.robovm.compiler.llvm.Variable) FunctionType(org.robovm.compiler.llvm.FunctionType)

Example 15 with FunctionType

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

the class Linker method link.

public void link(Set<Clazz> classes) throws IOException {
    for (CompilerPlugin plugin : config.getCompilerPlugins()) {
        plugin.beforeLinker(config, this, classes);
    }
    Arch arch = config.getArch();
    OS os = config.getOs();
    Set<Clazz> linkClasses = new TreeSet<Clazz>(classes);
    config.getLogger().info("Linking %d classes (%s %s %s)", linkClasses.size(), os, arch, config.isDebug() ? "debug" : "release");
    ModuleBuilder mb = new ModuleBuilder();
    mb.addInclude(getClass().getClassLoader().getResource(String.format("header-%s-%s.ll", os.getFamily(), arch)));
    mb.addInclude(getClass().getClassLoader().getResource("header.ll"));
    mb.addGlobal(new Global("_bcRuntimeData", runtimeDataToBytes()));
    ArrayConstantBuilder staticLibs = new ArrayConstantBuilder(I8_PTR);
    for (Config.Lib lib : config.getLibs()) {
        String p = lib.getValue();
        if (p.endsWith(".a")) {
            p = new File(p).getName();
            String libName = p.substring(0, p.length() - 2);
            if (libName.startsWith("lib")) {
                libName = libName.substring(3);
            }
            staticLibs.add(mb.getString(libName));
        }
    }
    staticLibs.add(new NullConstant(Type.I8_PTR));
    mb.addGlobal(new Global("_bcStaticLibs", new ConstantGetelementptr(mb.newGlobal(staticLibs.build()).ref(), 0, 0)));
    HashTableGenerator<String, Constant> bcpHashGen = new HashTableGenerator<String, Constant>(new ModifiedUtf8HashFunction());
    HashTableGenerator<String, Constant> cpHashGen = new HashTableGenerator<String, Constant>(new ModifiedUtf8HashFunction());
    int classCount = 0;
    Map<ClazzInfo, TypeInfo> typeInfos = new HashMap<ClazzInfo, TypeInfo>();
    for (Clazz clazz : linkClasses) {
        TypeInfo typeInfo = new TypeInfo();
        typeInfo.clazz = clazz;
        typeInfo.id = classCount++;
        typeInfos.put(clazz.getClazzInfo(), typeInfo);
        StructureConstant infoErrorStruct = createClassInfoErrorStruct(mb, clazz.getClazzInfo());
        Global info = null;
        if (infoErrorStruct == null) {
            info = new Global(Symbols.infoStructSymbol(clazz.getInternalName()), external, I8_PTR, false);
        } else {
            typeInfo.error = true;
            info = new Global(Symbols.infoStructSymbol(clazz.getInternalName()), infoErrorStruct);
        }
        mb.addGlobal(info);
        if (clazz.isInBootClasspath()) {
            bcpHashGen.put(clazz.getInternalName(), new ConstantBitcast(info.ref(), I8_PTR));
        } else {
            cpHashGen.put(clazz.getInternalName(), new ConstantBitcast(info.ref(), I8_PTR));
        }
    }
    mb.addGlobal(new Global("_bcBootClassesHash", new ConstantGetelementptr(mb.newGlobal(bcpHashGen.generate(), true).ref(), 0, 0)));
    mb.addGlobal(new Global("_bcClassesHash", new ConstantGetelementptr(mb.newGlobal(cpHashGen.generate(), true).ref(), 0, 0)));
    ArrayConstantBuilder bootClasspathValues = new ArrayConstantBuilder(I8_PTR);
    ArrayConstantBuilder classpathValues = new ArrayConstantBuilder(I8_PTR);
    List<Path> allPaths = new ArrayList<Path>();
    allPaths.addAll(config.getClazzes().getPaths());
    allPaths.addAll(config.getResourcesPaths());
    for (Path path : allPaths) {
        String entryName = null;
        if (config.isSkipInstall() && config.getTarget().canLaunchInPlace()) {
            entryName = path.getFile().getAbsolutePath();
        } else {
            entryName = config.getTarget().getInstallRelativeArchivePath(path);
        }
        if (path.isInBootClasspath()) {
            bootClasspathValues.add(mb.getString(entryName));
        } else {
            classpathValues.add(mb.getString(entryName));
        }
    }
    bootClasspathValues.add(new NullConstant(Type.I8_PTR));
    classpathValues.add(new NullConstant(Type.I8_PTR));
    mb.addGlobal(new Global("_bcBootclasspath", new ConstantGetelementptr(mb.newGlobal(bootClasspathValues.build()).ref(), 0, 0)));
    mb.addGlobal(new Global("_bcClasspath", new ConstantGetelementptr(mb.newGlobal(classpathValues.build()).ref(), 0, 0)));
    if (config.getMainClass() != null) {
        mb.addGlobal(new Global("_bcMainClass", mb.getString(config.getMainClass())));
    }
    ModuleBuilder[] mbs = new ModuleBuilder[config.getThreads() + 1];
    FunctionRef[] stubRefs = new FunctionRef[mbs.length];
    ArrayConstantBuilder stubRefsArray = new ArrayConstantBuilder(I8_PTR);
    mbs[0] = mb;
    for (int i = 1; i < mbs.length; i++) {
        mbs[i] = new ModuleBuilder();
        mbs[i].addInclude(getClass().getClassLoader().getResource(String.format("header-%s-%s.ll", os.getFamily(), arch)));
        mbs[i].addInclude(getClass().getClassLoader().getResource("header.ll"));
        Function fn = new FunctionBuilder("_stripped_method" + i, new FunctionType(VOID, ENV_PTR)).linkage(external).build();
        call(fn, BC_THROW_NO_SUCH_METHOD_ERROR, fn.getParameterRef(0), mbs[i].getString("Method has been stripped out of the executable"));
        fn.add(new Unreachable());
        mbs[i].addFunction(fn);
        mb.addFunctionDeclaration(new FunctionDeclaration(fn.ref()));
        stubRefs[i] = fn.ref();
        stubRefsArray.add(new ConstantBitcast(fn.ref(), I8_PTR));
    }
    stubRefsArray.add(new NullConstant(I8_PTR));
    mb.addGlobal(new Global("_bcStrippedMethodStubs", stubRefsArray.build()));
    Random rnd = new Random();
    buildTypeInfos(typeInfos);
    Set<String> checkcasts = new HashSet<>();
    Set<String> instanceofs = new HashSet<>();
    Set<String> invokes = new HashSet<>();
    for (Clazz clazz : linkClasses) {
        ClazzInfo ci = clazz.getClazzInfo();
        checkcasts.addAll(ci.getCheckcasts());
        instanceofs.addAll(ci.getInstanceofs());
        invokes.addAll(ci.getInvokes());
    }
    Set<String> reachableMethods = new HashSet<>();
    for (Triple<String, String, String> node : config.getDependencyGraph().findReachableMethods()) {
        reachableMethods.add(node.getLeft() + "." + node.getMiddle() + node.getRight());
    }
    int totalMethodCount = 0;
    int reachableMethodCount = 0;
    for (Clazz clazz : linkClasses) {
        int mbIdx = rnd.nextInt(mbs.length - 1) + 1;
        ClazzInfo ci = clazz.getClazzInfo();
        // symbols errors.
        for (MethodInfo mi : ci.getMethods()) {
            if (!mi.isAbstract()) {
                totalMethodCount++;
                if (!reachableMethods.contains(clazz.getInternalName() + "." + mi.getName() + mi.getDesc())) {
                    createStrippedMethodStub(stubRefs[mbIdx], mbs[mbIdx], clazz, mi);
                } else {
                    reachableMethodCount++;
                }
            }
        }
        TypeInfo typeInfo = typeInfos.get(ci);
        if (typeInfo.error) {
            // Add an empty TypeInfo
            mb.addGlobal(new Global(Symbols.typeInfoSymbol(clazz.getInternalName()), new StructureConstantBuilder().add(new IntegerConstant(typeInfo.id)).add(new IntegerConstant(0)).add(new IntegerConstant(-1)).add(new IntegerConstant(0)).add(new IntegerConstant(0)).build()));
        } else {
            int[] classIds = new int[typeInfo.classTypes.length];
            for (int i = 0; i < typeInfo.classTypes.length; i++) {
                classIds[i] = typeInfo.classTypes[i].id;
            }
            int[] interfaceIds = new int[typeInfo.interfaceTypes.length];
            for (int i = 0; i < typeInfo.interfaceTypes.length; i++) {
                interfaceIds[i] = typeInfo.interfaceTypes[i].id;
            }
            mb.addGlobal(new Global(Symbols.typeInfoSymbol(clazz.getInternalName()), new StructureConstantBuilder().add(new IntegerConstant(typeInfo.id)).add(new IntegerConstant((typeInfo.classTypes.length - 1) * 4 + 5 * 4)).add(new IntegerConstant(-1)).add(new IntegerConstant(typeInfo.classTypes.length)).add(new IntegerConstant(typeInfo.interfaceTypes.length)).add(new ArrayConstantBuilder(I32).add(classIds).build()).add(new ArrayConstantBuilder(I32).add(interfaceIds).build()).build()));
            if (!config.isDebug() && !ci.isInterface() && !ci.isFinal() && typeInfo.children.isEmpty()) {
                // which doesn't do any lookup.
                for (MethodInfo mi : ci.getMethods()) {
                    String name = mi.getName();
                    if (!name.equals("<clinit>") && !name.equals("<init>") && !mi.isPrivate() && !mi.isStatic() && !mi.isFinal() && !mi.isAbstract()) {
                        if (invokes.contains(clazz.getInternalName() + "." + name + mi.getDesc())) {
                            if (reachableMethods.contains(clazz.getInternalName() + "." + name + mi.getDesc())) {
                                mbs[mbIdx].addFunction(createLookup(mbs[mbIdx], ci, mi));
                            }
                        }
                    }
                }
            }
        }
        if (checkcasts.contains(clazz.getInternalName())) {
            mbs[mbIdx].addFunction(createCheckcast(mbs[mbIdx], clazz, typeInfo));
        }
        if (instanceofs.contains(clazz.getInternalName())) {
            mbs[mbIdx].addFunction(createInstanceof(mbs[mbIdx], clazz, typeInfo));
        }
    }
    config.getLogger().info("%d methods out of %d included in the executable", reachableMethodCount, totalMethodCount);
    List<File> objectFiles = new ArrayList<File>();
    generateMachineCode(config, mbs, objectFiles);
    for (Clazz clazz : linkClasses) {
        objectFiles.add(config.getOFile(clazz));
    }
    /*
         * Assemble the lines files for all linked classes into the module.
         */
    for (Clazz clazz : linkClasses) {
        File f = config.getLinesOFile(clazz);
        if (f.exists() && f.length() > 0) {
            objectFiles.add(f);
        }
    }
    config.getTarget().build(objectFiles);
}
Also used : HashMap(java.util.HashMap) CompilerPlugin(org.robovm.compiler.plugin.CompilerPlugin) Config(org.robovm.compiler.config.Config) NullConstant(org.robovm.compiler.llvm.NullConstant) StructureConstant(org.robovm.compiler.llvm.StructureConstant) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Constant(org.robovm.compiler.llvm.Constant) ArrayConstant(org.robovm.compiler.llvm.ArrayConstant) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) ArrayList(java.util.ArrayList) Global(org.robovm.compiler.llvm.Global) HashTableGenerator(org.robovm.compiler.hash.HashTableGenerator) ModifiedUtf8HashFunction(org.robovm.compiler.hash.ModifiedUtf8HashFunction) ArrayConstantBuilder(org.robovm.compiler.llvm.ArrayConstantBuilder) ModifiedUtf8HashFunction(org.robovm.compiler.hash.ModifiedUtf8HashFunction) Function(org.robovm.compiler.llvm.Function) FunctionDeclaration(org.robovm.compiler.llvm.FunctionDeclaration) Random(java.util.Random) Unreachable(org.robovm.compiler.llvm.Unreachable) TreeSet(java.util.TreeSet) Clazz(org.robovm.compiler.clazz.Clazz) FunctionRef(org.robovm.compiler.llvm.FunctionRef) HashSet(java.util.HashSet) Path(org.robovm.compiler.clazz.Path) OS(org.robovm.compiler.config.OS) FunctionType(org.robovm.compiler.llvm.FunctionType) Arch(org.robovm.compiler.config.Arch) NullConstant(org.robovm.compiler.llvm.NullConstant) ClazzInfo(org.robovm.compiler.clazz.ClazzInfo) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) StructureConstant(org.robovm.compiler.llvm.StructureConstant) MethodInfo(org.robovm.compiler.clazz.MethodInfo) File(java.io.File) ConstantGetelementptr(org.robovm.compiler.llvm.ConstantGetelementptr)

Aggregations

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