Search in sources :

Example 6 with PointerType

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

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

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

the class Types method offsetof.

public static Constant offsetof(AggregateType type, int... idx) {
    int[] i = new int[idx.length + 1];
    i[0] = 0;
    System.arraycopy(idx, 0, i, 1, idx.length);
    return new ConstantPtrtoint(new ConstantGetelementptr(new NullConstant(new PointerType(type)), i), I32);
}
Also used : NullConstant(org.robovm.compiler.llvm.NullConstant) ConstantPtrtoint(org.robovm.compiler.llvm.ConstantPtrtoint) PointerType(org.robovm.compiler.llvm.PointerType) ConstantGetelementptr(org.robovm.compiler.llvm.ConstantGetelementptr)

Example 9 with PointerType

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

Example 10 with PointerType

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

the class BroMethodCompiler method getReturnType.

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

Aggregations

PointerType (org.robovm.compiler.llvm.PointerType)22 Variable (org.robovm.compiler.llvm.Variable)13 FunctionType (org.robovm.compiler.llvm.FunctionType)11 StructureType (org.robovm.compiler.llvm.StructureType)11 Value (org.robovm.compiler.llvm.Value)9 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)8 Load (org.robovm.compiler.llvm.Load)8 Type (org.robovm.compiler.llvm.Type)8 ArrayType (org.robovm.compiler.llvm.ArrayType)7 Bitcast (org.robovm.compiler.llvm.Bitcast)7 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)6 FunctionRef (org.robovm.compiler.llvm.FunctionRef)6 Getelementptr (org.robovm.compiler.llvm.Getelementptr)6 NullConstant (org.robovm.compiler.llvm.NullConstant)6 Ret (org.robovm.compiler.llvm.Ret)6 PrimType (soot.PrimType)6 Br (org.robovm.compiler.llvm.Br)5 Function (org.robovm.compiler.llvm.Function)5 Icmp (org.robovm.compiler.llvm.Icmp)5 IntegerType (org.robovm.compiler.llvm.IntegerType)5