Search in sources :

Example 1 with Global

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

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

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

the class Linker method getInfoStruct.

private Value getInfoStruct(ModuleBuilder mb, Function f, Clazz clazz) {
    String symbol = Symbols.infoStructSymbol(clazz.getInternalName());
    if (!mb.hasSymbol(symbol)) {
        Global info = new Global(symbol, external, I8_PTR, false);
        mb.addGlobal(info);
        return info.ref();
    } else {
        return new ConstantBitcast(mb.getGlobalRef(symbol), I8_PTR_PTR);
    }
}
Also used : ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) Global(org.robovm.compiler.llvm.Global)

Example 4 with Global

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

Example 5 with Global

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

the class ClassCompiler method createITablesStruct.

private Constant createITablesStruct() {
    if (!sootClass.isInterface()) {
        HashSet<SootClass> interfaces = new HashSet<SootClass>();
        collectInterfaces(sootClass, interfaces);
        List<Constant> tables = new ArrayList<Constant>();
        int i = 0;
        for (SootClass ifs : interfaces) {
            ITable itable = config.getITableCache().get(ifs);
            if (itable.size() > 0) {
                String name = Symbols.itableSymbol(getInternalName(sootClass), i++);
                String typeInfoName = Symbols.typeInfoSymbol(getInternalName(ifs));
                if (!mb.hasSymbol(typeInfoName)) {
                    mb.addGlobal(new Global(typeInfoName, Linkage.external, I8_PTR, true));
                }
                Global itableStruct = new Global(name, Linkage._private, new StructureConstantBuilder().add(mb.getGlobalRef(typeInfoName)).add(itable.getStruct(mb, sootClass)).build(), true);
                mb.addGlobal(itableStruct);
                tables.add(new ConstantBitcast(itableStruct.ref(), I8_PTR));
            }
        }
        if (tables.isEmpty()) {
            return new NullConstant(I8_PTR);
        } else {
            Global itablesStruct = new Global(Symbols.itablesSymbol(getInternalName(sootClass)), Linkage._private, new StructureConstantBuilder().add(new IntegerConstant((short) tables.size())).add(// cache value must never be null
            tables.get(0)).add(new ArrayConstantBuilder(I8_PTR).add(tables).build()).build());
            mb.addGlobal(itablesStruct);
            return new ConstantBitcast(itablesStruct.ref(), I8_PTR);
        }
    } else {
        return new NullConstant(I8_PTR);
    }
}
Also used : StructureConstant(org.robovm.compiler.llvm.StructureConstant) Constant(org.robovm.compiler.llvm.Constant) NullConstant(org.robovm.compiler.llvm.NullConstant) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) ArrayList(java.util.ArrayList) NullConstant(org.robovm.compiler.llvm.NullConstant) SootClass(soot.SootClass) Global(org.robovm.compiler.llvm.Global) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) PackedStructureConstantBuilder(org.robovm.compiler.llvm.PackedStructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) ArrayConstantBuilder(org.robovm.compiler.llvm.ArrayConstantBuilder) HashSet(java.util.HashSet)

Aggregations

Global (org.robovm.compiler.llvm.Global)17 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)9 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)9 NullConstant (org.robovm.compiler.llvm.NullConstant)9 FunctionRef (org.robovm.compiler.llvm.FunctionRef)8 Function (org.robovm.compiler.llvm.Function)7 Ret (org.robovm.compiler.llvm.Ret)7 FunctionType (org.robovm.compiler.llvm.FunctionType)6 Value (org.robovm.compiler.llvm.Value)6 ArrayList (java.util.ArrayList)5 PointerType (org.robovm.compiler.llvm.PointerType)5 StructureConstantBuilder (org.robovm.compiler.llvm.StructureConstantBuilder)5 HashSet (java.util.HashSet)4 Br (org.robovm.compiler.llvm.Br)4 Constant (org.robovm.compiler.llvm.Constant)4 Label (org.robovm.compiler.llvm.Label)4 StructureConstant (org.robovm.compiler.llvm.StructureConstant)4 Type (org.robovm.compiler.llvm.Type)4 Variable (org.robovm.compiler.llvm.Variable)4 Bitcast (org.robovm.compiler.llvm.Bitcast)3