Search in sources :

Example 1 with ArrayConstantBuilder

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

the class Linker method runtimeDataToBytes.

private ArrayConstant runtimeDataToBytes() throws UnsupportedEncodingException {
    // The data consists of key value pairs prefixed with the number of
    // pairs (int). In each pair the key is an UTF8 encoded string prefixed
    // with the key's length (int) and the data is a byte array prefixed
    // with the data length (int). We prefix the data with the length of the
    // data (int).
    LinkedList<byte[]> dataList = new LinkedList<>();
    int length = 4;
    for (Entry<String, byte[]> entry : runtimeData.entrySet()) {
        dataList.add(entry.getKey().getBytes("UTF8"));
        length += 4 + dataList.getLast().length;
        dataList.add(entry.getValue());
        length += 4 + dataList.getLast().length;
    }
    ByteBuffer bb = ByteBuffer.wrap(new byte[length + 4]).order(config.getArch().getByteOrder());
    bb.putInt(length);
    bb.putInt(runtimeData.size());
    for (byte[] b : dataList) {
        bb.putInt(b.length);
        bb.put(b);
    }
    return new ArrayConstantBuilder(I8).add(bb.array()).build();
}
Also used : ArrayConstantBuilder(org.robovm.compiler.llvm.ArrayConstantBuilder) ByteBuffer(java.nio.ByteBuffer) LinkedList(java.util.LinkedList)

Example 2 with ArrayConstantBuilder

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

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

Example 4 with ArrayConstantBuilder

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

the class ITable method getStruct.

public StructureConstant getStruct(ModuleBuilder mb, SootClass clazz) {
    if (clazz.isInterface()) {
        throw new IllegalArgumentException("Expected a class got an interface: " + clazz.getName());
    }
    ArrayConstantBuilder table = new ArrayConstantBuilder(I8_PTR);
    for (Entry entry : entries) {
        ResolvedEntry resolvedEntry = entry.resolve(clazz);
        if (resolvedEntry == null) {
            FunctionRef defaultFunctionRef = entry.getFunctionRef();
            if (defaultFunctionRef != null) {
                if (!mb.hasSymbol(defaultFunctionRef.getName())) {
                    mb.addFunctionDeclaration(new FunctionDeclaration(defaultFunctionRef));
                }
                table.add(new ConstantBitcast(defaultFunctionRef, I8_PTR));
            } else {
                table.add(new ConstantBitcast(BC_ABSTRACT_METHOD_CALLED, I8_PTR));
            }
        } else if (Modifier.isAbstract(resolvedEntry.getModifiers())) {
            table.add(new ConstantBitcast(BC_ABSTRACT_METHOD_CALLED, I8_PTR));
        } else if (!Modifier.isPublic(resolvedEntry.getModifiers())) {
            table.add(new ConstantBitcast(BC_NON_PUBLIC_METHOD_CALLED, I8_PTR));
        } else {
            /*
                 * Found a non-abstract method implementation. Either on the
                 * class, in one of its super classes or a default method in an
                 * implemented interface.
                 */
            FunctionRef functionRef = resolvedEntry.getFunctionRef();
            if (!resolvedEntry.declaringClass.equals(clazz.getName())) {
                if (!mb.hasSymbol(functionRef.getName())) {
                    mb.addFunctionDeclaration(new FunctionDeclaration(functionRef));
                }
            }
            table.add(new ConstantBitcast(functionRef, I8_PTR));
        }
    }
    return new StructureConstantBuilder().add(new IntegerConstant((short) entries.length)).add(table.build()).build();
}
Also used : ArrayConstantBuilder(org.robovm.compiler.llvm.ArrayConstantBuilder) FunctionDeclaration(org.robovm.compiler.llvm.FunctionDeclaration) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Aggregations

ArrayConstantBuilder (org.robovm.compiler.llvm.ArrayConstantBuilder)4 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)3 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)3 StructureConstantBuilder (org.robovm.compiler.llvm.StructureConstantBuilder)3 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 Constant (org.robovm.compiler.llvm.Constant)2 FunctionDeclaration (org.robovm.compiler.llvm.FunctionDeclaration)2 FunctionRef (org.robovm.compiler.llvm.FunctionRef)2 Global (org.robovm.compiler.llvm.Global)2 NullConstant (org.robovm.compiler.llvm.NullConstant)2 StructureConstant (org.robovm.compiler.llvm.StructureConstant)2 File (java.io.File)1 ByteBuffer (java.nio.ByteBuffer)1 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1 Random (java.util.Random)1 TreeSet (java.util.TreeSet)1 Clazz (org.robovm.compiler.clazz.Clazz)1 ClazzInfo (org.robovm.compiler.clazz.ClazzInfo)1