Search in sources :

Example 11 with Global

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

the class TrampolineCompiler method createLdcArray.

private FunctionRef createLdcArray(String targetClass) {
    if (isPrimitiveComponentType(targetClass)) {
        throw new IllegalArgumentException();
    }
    String fnName = Symbols.arrayldcSymbol(targetClass);
    FunctionRef fnRef = new FunctionRef(fnName, new FunctionType(OBJECT_PTR, ENV_PTR));
    if (!mb.hasSymbol(fnName)) {
        Function fn = new FunctionBuilder(fnRef).name(fnName).linkage(weak).build();
        Global g = new Global(Symbols.arrayPtrSymbol(targetClass), weak, new NullConstant(OBJECT_PTR));
        if (!mb.hasSymbol(g.getName())) {
            mb.addGlobal(g);
        }
        FunctionRef ldcArrayClassFn = BC_LDC_ARRAY_BOOT_CLASS;
        if (!isPrimitiveBaseType(targetClass)) {
            Clazz baseType = config.getClazzes().load(getBaseType(targetClass));
            if (!baseType.isInBootClasspath()) {
                ldcArrayClassFn = BC_LDC_ARRAY_CLASS;
            }
        }
        Value arrayClass = call(fn, ldcArrayClassFn, fn.getParameterRef(0), g.ref(), mb.getString(targetClass));
        fn.add(new Ret(arrayClass));
        mb.addFunction(fn);
    }
    return fnRef;
}
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) Clazz(org.robovm.compiler.clazz.Clazz) Global(org.robovm.compiler.llvm.Global) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Example 12 with Global

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

the class ClassCompiler method createVTableStruct.

private Constant createVTableStruct() {
    VTable vtable = config.getVTableCache().get(sootClass);
    String name = Symbols.vtableSymbol(getInternalName(sootClass));
    for (VTable.Entry entry : vtable.getEntries()) {
        FunctionRef fref = entry.getFunctionRef();
        if (fref != null && !mb.hasSymbol(fref.getName())) {
            mb.addFunctionDeclaration(new FunctionDeclaration(fref));
        }
    }
    Global vtableStruct = new Global(name, Linkage._private, vtable.getStruct(), true);
    mb.addGlobal(vtableStruct);
    return new ConstantBitcast(vtableStruct.ref(), I8_PTR);
}
Also used : FunctionDeclaration(org.robovm.compiler.llvm.FunctionDeclaration) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) Global(org.robovm.compiler.llvm.Global) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Example 13 with Global

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

the class AttributesEncoder method encode.

public void encode(ModuleBuilder mb, SootClass sootClass) {
    this.mb = mb;
    dependencies = new HashSet<String>();
    classAttributes = null;
    fieldAttributes = new HashMap<SootField, Global>();
    methodAttributes = new HashMap<SootMethod, Global>();
    encodeAttributes(sootClass);
    Constant classAttributes = encodeAttributes(sootClass);
    if (classAttributes != null) {
        Global g = new Global(Symbols.classAttributesSymbol(sootClass), Linkage._private, classAttributes, true);
        mb.addGlobal(g);
        this.classAttributes = g;
    }
    for (SootField field : sootClass.getFields()) {
        Constant fieldAttributes = encodeAttributes(field);
        if (fieldAttributes != null) {
            Global g = new Global(Symbols.fieldAttributesSymbol(field), Linkage._private, fieldAttributes, true);
            mb.addGlobal(g);
            this.fieldAttributes.put(field, g);
        }
    }
    for (SootMethod method : sootClass.getMethods()) {
        Constant methodAttributes = encodeAttributes(method);
        if (methodAttributes != null) {
            Global g = new Global(Symbols.methodAttributesSymbol(method), Linkage._private, methodAttributes, true);
            mb.addGlobal(g);
            this.methodAttributes.put(method, g);
        }
    }
}
Also used : IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) StructureConstant(org.robovm.compiler.llvm.StructureConstant) Constant(org.robovm.compiler.llvm.Constant) PackedStructureConstant(org.robovm.compiler.llvm.PackedStructureConstant) FloatingPointConstant(org.robovm.compiler.llvm.FloatingPointConstant) ArrayConstant(org.robovm.compiler.llvm.ArrayConstant) SootMethod(soot.SootMethod) SootField(soot.SootField) Global(org.robovm.compiler.llvm.Global)

Example 14 with Global

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

the class ClassCompiler method createClassInfoStruct.

private StructureConstant createClassInfoStruct() {
    int flags = 0;
    if (Modifier.isPublic(sootClass.getModifiers())) {
        flags |= CI_PUBLIC;
    }
    if (Modifier.isFinal(sootClass.getModifiers())) {
        flags |= CI_FINAL;
    }
    if (Modifier.isInterface(sootClass.getModifiers())) {
        flags |= CI_INTERFACE;
    }
    if (Modifier.isAbstract(sootClass.getModifiers())) {
        flags |= CI_ABSTRACT;
    }
    if ((sootClass.getModifiers() & 0x1000) > 0) {
        flags |= CI_SYNTHETIC;
    }
    if (Modifier.isAnnotation(sootClass.getModifiers())) {
        flags |= CI_ANNOTATION;
    }
    if (Modifier.isEnum(sootClass.getModifiers())) {
        flags |= CI_ENUM;
    }
    if (attributesEncoder.classHasAttributes()) {
        flags |= CI_ATTRIBUTES;
    }
    if (hasFinalizer(sootClass)) {
        flags |= CI_FINALIZABLE;
    }
    // Create the ClassInfoHeader structure.
    StructureConstantBuilder header = new StructureConstantBuilder();
    // Points to the runtime Class struct
    header.add(new NullConstant(I8_PTR));
    header.add(new IntegerConstant(flags));
    header.add(getString(getInternalName(sootClass)));
    if (sootClass.declaresMethod("<clinit>", Collections.emptyList(), VoidType.v())) {
        SootMethod method = sootClass.getMethod("<clinit>", Collections.emptyList(), VoidType.v());
        header.add(new FunctionRef(Symbols.methodSymbol(method), getFunctionType(method)));
    } else {
        header.add(new NullConstant(I8_PTR));
    }
    mb.addGlobal(new Global(Symbols.typeInfoSymbol(getInternalName(sootClass)), Linkage.external, I8_PTR, true));
    // TypeInfo* generated by Linker
    header.add(new GlobalRef(Symbols.typeInfoSymbol(getInternalName(sootClass)), I8_PTR));
    if (!sootClass.isInterface()) {
        header.add(createVTableStruct());
    } else {
        header.add(createITableStruct());
    }
    header.add(createITablesStruct());
    header.add(sizeof(classType));
    header.add(sizeof(instanceType));
    if (!instanceFields.isEmpty()) {
        header.add(offsetof(instanceType, 1, 1));
    } else {
        header.add(sizeof(instanceType));
    }
    header.add(new IntegerConstant((short) countReferences(classFields)));
    header.add(new IntegerConstant((short) countReferences(instanceFields)));
    PackedStructureConstantBuilder body = new PackedStructureConstantBuilder();
    body.add(new IntegerConstant((short) sootClass.getInterfaceCount()));
    body.add(new IntegerConstant((short) sootClass.getFieldCount()));
    body.add(new IntegerConstant((short) sootClass.getMethodCount()));
    if (!sootClass.isInterface()) {
        body.add(getStringOrNull(sootClass.hasSuperclass() ? getInternalName(sootClass.getSuperclass()) : null));
    }
    if (attributesEncoder.classHasAttributes()) {
        body.add(new ConstantBitcast(attributesEncoder.getClassAttributes().ref(), I8_PTR));
    }
    for (SootClass s : sootClass.getInterfaces()) {
        body.add(getString(getInternalName(s)));
    }
    for (SootField f : sootClass.getFields()) {
        flags = 0;
        soot.Type t = f.getType();
        if (t instanceof PrimType) {
            if (t.equals(BooleanType.v())) {
                flags |= DESC_Z;
            } else if (t.equals(ByteType.v())) {
                flags |= DESC_B;
            } else if (t.equals(ShortType.v())) {
                flags |= DESC_S;
            } else if (t.equals(CharType.v())) {
                flags |= DESC_C;
            } else if (t.equals(IntType.v())) {
                flags |= DESC_I;
            } else if (t.equals(LongType.v())) {
                flags |= DESC_J;
            } else if (t.equals(FloatType.v())) {
                flags |= DESC_F;
            } else if (t.equals(DoubleType.v())) {
                flags |= DESC_D;
            }
            flags <<= 12;
        }
        if (Modifier.isPublic(f.getModifiers())) {
            flags |= FI_PUBLIC;
        } else if (Modifier.isPrivate(f.getModifiers())) {
            flags |= FI_PRIVATE;
        } else if (Modifier.isProtected(f.getModifiers())) {
            flags |= FI_PROTECTED;
        }
        if (Modifier.isStatic(f.getModifiers())) {
            flags |= FI_STATIC;
        }
        if (Modifier.isFinal(f.getModifiers())) {
            flags |= FI_FINAL;
        }
        if (Modifier.isVolatile(f.getModifiers())) {
            flags |= FI_VOLATILE;
        }
        if (Modifier.isTransient(f.getModifiers())) {
            flags |= FI_TRANSIENT;
        }
        if ((f.getModifiers() & 0x1000) > 0) {
            flags |= FI_SYNTHETIC;
        }
        if (Modifier.isEnum(f.getModifiers())) {
            flags |= FI_ENUM;
        }
        if (attributesEncoder.fieldHasAttributes(f)) {
            flags |= FI_ATTRIBUTES;
        }
        body.add(new IntegerConstant((short) flags));
        body.add(getString(f.getName()));
        if (!(t instanceof PrimType)) {
            body.add(getString(getDescriptor(f)));
        }
        if (f.isStatic()) {
            int index = classFields.indexOf(f);
            body.add(offsetof(classType, 1, index, 1));
        } else {
            int index = instanceFields.indexOf(f);
            body.add(offsetof(instanceType, 1, 1 + index, 1));
        }
        if (attributesEncoder.fieldHasAttributes(f)) {
            body.add(new ConstantBitcast(attributesEncoder.getFieldAttributes(f).ref(), I8_PTR));
        }
    }
    VTable vtable = !sootClass.isInterface() ? config.getVTableCache().get(sootClass) : null;
    ITable itable = sootClass.isInterface() ? config.getITableCache().get(sootClass) : null;
    ;
    for (SootMethod m : sootClass.getMethods()) {
        soot.Type t = m.getReturnType();
        flags = 0;
        if (Modifier.isPublic(m.getModifiers())) {
            flags |= MI_PUBLIC;
        } else if (Modifier.isPrivate(m.getModifiers())) {
            flags |= MI_PRIVATE;
        } else if (Modifier.isProtected(m.getModifiers())) {
            flags |= MI_PROTECTED;
        }
        if (Modifier.isStatic(m.getModifiers())) {
            flags |= MI_STATIC;
        }
        if (Modifier.isFinal(m.getModifiers())) {
            flags |= MI_FINAL;
        }
        if (Modifier.isSynchronized(m.getModifiers())) {
            flags |= MI_SYNCHRONIZED;
        }
        if ((m.getModifiers() & 0x0040) > 0) {
            flags |= MI_BRIDGE;
        }
        if ((m.getModifiers() & 0x0080) > 0) {
            flags |= MI_VARARGS;
        }
        if (Modifier.isNative(m.getModifiers())) {
            if (!isStruct(sootClass) && !hasStructMemberAnnotation(m)) {
                flags |= MI_NATIVE;
            }
        }
        if (Modifier.isAbstract(m.getModifiers())) {
            flags |= MI_ABSTRACT;
        }
        if (Modifier.isStrictFP(m.getModifiers())) {
            flags |= MI_STRICT;
        }
        if ((m.getModifiers() & 0x1000) > 0) {
            flags |= MI_SYNTHETIC;
        }
        if (attributesEncoder.methodHasAttributes(m)) {
            flags |= MI_ATTRIBUTES;
        }
        if (hasBridgeAnnotation(m) || hasGlobalValueAnnotation(m)) {
            flags |= MI_BRO_BRIDGE;
        }
        if (hasCallbackAnnotation(m)) {
            flags |= MI_BRO_CALLBACK;
        }
        if ((t instanceof PrimType || t == VoidType.v()) && m.getParameterCount() == 0) {
            flags |= MI_COMPACT_DESC;
        }
        body.add(new IntegerConstant((short) flags));
        Constant viTableIndex = new IntegerConstant((short) -1);
        if (vtable != null) {
            VTable.Entry entry = vtable.getEntry(m);
            if (entry != null) {
                viTableIndex = new IntegerConstant((short) entry.getIndex());
            }
        } else {
            ITable.Entry entry = itable.getEntry(m);
            if (entry != null) {
                viTableIndex = new IntegerConstant((short) entry.getIndex());
            }
        }
        body.add(viTableIndex);
        body.add(getString(m.getName()));
        if ((flags & MI_COMPACT_DESC) > 0) {
            int desc = 0;
            if (t.equals(BooleanType.v())) {
                desc = DESC_Z;
            } else if (t.equals(ByteType.v())) {
                desc = DESC_B;
            } else if (t.equals(ShortType.v())) {
                desc = DESC_S;
            } else if (t.equals(CharType.v())) {
                desc = DESC_C;
            } else if (t.equals(IntType.v())) {
                desc = DESC_I;
            } else if (t.equals(LongType.v())) {
                desc = DESC_J;
            } else if (t.equals(FloatType.v())) {
                desc = DESC_F;
            } else if (t.equals(DoubleType.v())) {
                desc = DESC_D;
            } else if (t.equals(VoidType.v())) {
                desc = DESC_V;
            }
            body.add(new IntegerConstant((byte) desc));
        } else {
            body.add(getString(getDescriptor(m)));
        }
        if (attributesEncoder.methodHasAttributes(m)) {
            body.add(new ConstantBitcast(attributesEncoder.getMethodAttributes(m).ref(), I8_PTR));
        }
        if (!m.isAbstract()) {
            body.add(new ConstantBitcast(new FunctionRef(Symbols.methodSymbol(m), getFunctionType(m)), I8_PTR));
            // Size of function. This value will be modified later by patching the .s file.
            body.add(new IntegerConstant(DUMMY_METHOD_SIZE));
            if (m.isSynchronized()) {
                body.add(new ConstantBitcast(new FunctionRef(Symbols.synchronizedWrapperSymbol(m), getFunctionType(m)), I8_PTR));
            }
            if ((flags & MI_NATIVE) == 0) {
                // Cannot use m.isNative() in the condition above since methods which are native in the
                // Java class file may have been changed to non-native by the RoboVM compiler 
                // (e.g. @StructMember methods). The native code which parses the info structs will see 
                // the method as non-native.
                // Add a weak linetable pointer which points to a -1 value which will be interpreted as 0 linenumbers in the table
                Global linetableGlobal = new Global(Symbols.linetableSymbol(m), Linkage.weak, new IntegerConstant(-1));
                mb.addGlobal(linetableGlobal);
                body.add(linetableGlobal.ref());
            }
        }
        if (hasBridgeAnnotation(m)) {
            if (!readBooleanElem(getAnnotation(m, BRIDGE), "dynamic", false)) {
                body.add(new GlobalRef(Symbols.bridgePtrSymbol(m), I8_PTR));
            } else {
                body.add(new NullConstant(I8_PTR));
            }
        } else if (hasGlobalValueAnnotation(m)) {
            body.add(new GlobalRef(Symbols.globalValuePtrSymbol(m), I8_PTR));
        }
        if (hasCallbackAnnotation(m)) {
            body.add(new AliasRef(Symbols.callbackPtrSymbol(m), I8_PTR));
        }
    }
    // after sizeof(ClassInfoHeader) bytes.
    return new StructureConstantBuilder().add(header.build()).add(body.build()).build();
}
Also used : GlobalRef(org.robovm.compiler.llvm.GlobalRef) PackedStructureConstantBuilder(org.robovm.compiler.llvm.PackedStructureConstantBuilder) AliasRef(org.robovm.compiler.llvm.AliasRef) 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) NullConstant(org.robovm.compiler.llvm.NullConstant) SootClass(soot.SootClass) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) PackedStructureConstantBuilder(org.robovm.compiler.llvm.PackedStructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Global(org.robovm.compiler.llvm.Global) SootMethod(soot.SootMethod) PrimType(soot.PrimType) SootField(soot.SootField) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Example 15 with Global

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

the class ClassCompiler method generateMachineCode.

private static void generateMachineCode(Config config, Clazz clazz, byte[] llData, List<String> cCode) throws IOException {
    if (config.isDumpIntermediates()) {
        File llFile = config.getLlFile(clazz);
        llFile.getParentFile().mkdirs();
        FileUtils.writeByteArrayToFile(llFile, llData);
        File cFile = config.getCFile(clazz);
        if (cCode.isEmpty()) {
            cFile.delete();
        } else {
            FileUtils.writeLines(cFile, "ascii", cCode);
        }
    }
    File oFile = config.getOFile(clazz);
    try (Context context = new Context()) {
        try (Module module = Module.parseIR(context, llData, clazz.getClassName())) {
            if (!cCode.isEmpty()) {
                int size = 0;
                for (String s : cCode) {
                    size += s.length();
                }
                StringBuilder sb = new StringBuilder(size);
                for (String s : cCode) {
                    sb.append(s);
                }
                try (Module m2 = Module.parseClangString(context, sb.toString(), clazz.getClassName() + ".c", config.getClangTriple())) {
                    module.link(m2);
                    for (org.robovm.llvm.Function f1 : m2.getFunctions()) {
                        String name = f1.getName();
                        org.robovm.llvm.Function f2 = module.getFunctionByName(name);
                        if (Symbols.isBridgeCSymbol(name) || Symbols.isCallbackCSymbol(name) || Symbols.isCallbackInnerCSymbol(name)) {
                            f2.setLinkage(org.robovm.llvm.binding.Linkage.PrivateLinkage);
                            if (Symbols.isCallbackInnerCSymbol(name)) {
                                // TODO: We should also always inline the bridge functions but for some reason
                                // that makes the RoboVM tests hang indefinitely.
                                f2.removeAttribute(Attribute.NoInlineAttribute);
                                f2.addAttribute(Attribute.AlwaysInlineAttribute);
                            }
                        }
                    }
                }
            }
            try (PassManager passManager = createPassManager(config)) {
                passManager.run(module);
            }
            if (config.isDumpIntermediates()) {
                File bcFile = config.getBcFile(clazz);
                bcFile.getParentFile().mkdirs();
                module.writeBitcode(bcFile);
            }
            String triple = config.getTriple();
            Target target = Target.lookupTarget(triple);
            try (TargetMachine targetMachine = target.createTargetMachine(triple, config.getArch().getLlvmCpu(), null, config.isDebug() ? CodeGenOptLevel.CodeGenLevelNone : null, RelocMode.RelocPIC, null)) {
                targetMachine.setAsmVerbosityDefault(true);
                targetMachine.setFunctionSections(true);
                targetMachine.setDataSections(true);
                targetMachine.getOptions().setNoFramePointerElim(true);
                // NOTE: Doesn't have any effect on x86. See #503.
                targetMachine.getOptions().setPositionIndependentExecutable(!config.isDebug());
                ByteArrayOutputStream output = new ByteArrayOutputStream(256 * 1024);
                targetMachine.emit(module, output, CodeGenFileType.AssemblyFile);
                byte[] asm = output.toByteArray();
                output.reset();
                patchAsmWithFunctionSizes(config, clazz, new ByteArrayInputStream(asm), output);
                asm = output.toByteArray();
                if (config.isDumpIntermediates()) {
                    File sFile = config.getSFile(clazz);
                    sFile.getParentFile().mkdirs();
                    FileUtils.writeByteArrayToFile(sFile, asm);
                }
                oFile.getParentFile().mkdirs();
                ByteArrayOutputStream oFileBytes = new ByteArrayOutputStream();
                targetMachine.assemble(asm, clazz.getClassName(), oFileBytes);
                new HfsCompressor().compress(oFile, oFileBytes.toByteArray(), config);
                for (CompilerPlugin plugin : config.getCompilerPlugins()) {
                    plugin.afterObjectFile(config, clazz, oFile);
                }
                /*
                     * Read out line number info from the .o file if any and
                     * assemble into a separate .o file.
                     */
                String symbolPrefix = config.getOs().getFamily() == OS.Family.darwin ? "_" : "";
                symbolPrefix += Symbols.EXTERNAL_SYMBOL_PREFIX;
                ModuleBuilder linesMb = null;
                try (ObjectFile objectFile = ObjectFile.load(oFile)) {
                    for (Symbol symbol : objectFile.getSymbols()) {
                        if (symbol.getSize() > 0 && symbol.getName().startsWith(symbolPrefix)) {
                            List<LineInfo> lineInfos = objectFile.getLineInfos(symbol);
                            if (!lineInfos.isEmpty()) {
                                Collections.sort(lineInfos, new Comparator<LineInfo>() {

                                    public int compare(LineInfo o1, LineInfo o2) {
                                        return Long.compare(o1.getAddress(), o2.getAddress());
                                    }
                                });
                                // The base address of the method which will be used to calculate offsets into the method
                                long baseAddress = symbol.getAddress();
                                // The first line number in the method. All other line numbers in the table will be deltas against this.
                                int firstLineNumber = lineInfos.get(0).getLineNumber();
                                // Calculate the max address and line number offsets
                                long maxAddressOffset = 0;
                                long maxLineOffset = 0;
                                for (LineInfo lineInfo : lineInfos) {
                                    maxAddressOffset = Math.max(maxAddressOffset, lineInfo.getAddress() - baseAddress);
                                    maxLineOffset = Math.max(maxLineOffset, lineInfo.getLineNumber() - firstLineNumber);
                                }
                                // Calculate the number of bytes needed to represent the highest offsets.
                                // Either 1, 2 or 4 bytes will be used.
                                int addressOffsetSize = (maxAddressOffset & ~0xff) == 0 ? 1 : ((maxAddressOffset & ~0xffff) == 0 ? 2 : 4);
                                int lineOffsetSize = (maxLineOffset & ~0xff) == 0 ? 1 : ((maxLineOffset & ~0xffff) == 0 ? 2 : 4);
                                // The size of the address offsets table. We skip the first LineInfo as its offset is always 0.
                                int addressOffsetTableSize = addressOffsetSize * (lineInfos.size() - 1);
                                // Pad size of address offset table to make sure line offsets are aligned properly 
                                int addressOffsetPadding = (lineOffsetSize - (addressOffsetTableSize & (lineOffsetSize - 1))) & (lineOffsetSize - 1);
                                addressOffsetTableSize += addressOffsetPadding;
                                // The first 32 bits of the line number info contains the number of line numbers
                                // minus the first. The 4 most significant bits are used to store the number of
                                // bytes needed by each entry in each table.
                                int flags = 0;
                                flags = addressOffsetSize - 1;
                                flags <<= 2;
                                flags |= lineOffsetSize - 1;
                                flags <<= 28;
                                flags |= (lineInfos.size() - 1) & 0x0fffffff;
                                StructureConstantBuilder builder = new StructureConstantBuilder();
                                builder.add(new IntegerConstant(flags)).add(new IntegerConstant(firstLineNumber));
                                for (LineInfo lineInfo : lineInfos.subList(1, lineInfos.size())) {
                                    if (addressOffsetSize == 1) {
                                        builder.add(new IntegerConstant((byte) (lineInfo.getAddress() - baseAddress)));
                                    } else if (addressOffsetSize == 2) {
                                        builder.add(new IntegerConstant((short) (lineInfo.getAddress() - baseAddress)));
                                    } else {
                                        builder.add(new IntegerConstant((int) (lineInfo.getAddress() - baseAddress)));
                                    }
                                }
                                // Padding
                                for (int i = 0; i < addressOffsetPadding; i++) {
                                    builder.add(new IntegerConstant((byte) 0));
                                }
                                for (LineInfo lineInfo : lineInfos.subList(1, lineInfos.size())) {
                                    if (lineOffsetSize == 1) {
                                        builder.add(new IntegerConstant((byte) (lineInfo.getLineNumber() - firstLineNumber)));
                                    } else if (lineOffsetSize == 2) {
                                        builder.add(new IntegerConstant((short) (lineInfo.getLineNumber() - firstLineNumber)));
                                    } else {
                                        builder.add(new IntegerConstant((int) (lineInfo.getLineNumber() - firstLineNumber)));
                                    }
                                }
                                // Extract the method's name and descriptor from the symbol and
                                // build the linetable symbol name.
                                String methodName = symbol.getName().substring(symbol.getName().lastIndexOf('.') + 1);
                                methodName = methodName.substring(0, methodName.indexOf('('));
                                String methodDesc = symbol.getName().substring(symbol.getName().lastIndexOf('('));
                                String linetableSymbol = Symbols.linetableSymbol(clazz.getInternalName(), methodName, methodDesc);
                                if (linesMb == null) {
                                    linesMb = new ModuleBuilder();
                                }
                                linesMb.addGlobal(new Global(linetableSymbol, builder.build(), true));
                            }
                        }
                    }
                }
                if (linesMb != null) {
                    byte[] linesData = linesMb.build().toString().getBytes("UTF-8");
                    if (config.isDumpIntermediates()) {
                        File linesLlFile = config.getLinesLlFile(clazz);
                        linesLlFile.getParentFile().mkdirs();
                        FileUtils.writeByteArrayToFile(linesLlFile, linesData);
                    }
                    try (Module linesModule = Module.parseIR(context, linesData, clazz.getClassName() + ".lines")) {
                        File linesOFile = config.getLinesOFile(clazz);
                        ByteArrayOutputStream linesOBytes = new ByteArrayOutputStream();
                        targetMachine.emit(linesModule, linesOBytes, CodeGenFileType.ObjectFile);
                        new HfsCompressor().compress(linesOFile, linesOBytes.toByteArray(), config);
                    }
                } else {
                    // Make sure there's no stale lines.o file lingering
                    File linesOFile = config.getLinesOFile(clazz);
                    if (linesOFile.exists()) {
                        linesOFile.delete();
                    }
                }
            }
        }
    } catch (Throwable t) {
        if (oFile.exists()) {
            oFile.delete();
        }
        if (t instanceof IOException) {
            throw (IOException) t;
        }
        if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        }
        if (t instanceof Error) {
            throw (Error) t;
        }
        throw new CompilerException(t);
    }
}
Also used : CompilerPlugin(org.robovm.compiler.plugin.CompilerPlugin) Symbol(org.robovm.llvm.Symbol) LineInfo(org.robovm.llvm.LineInfo) PassManager(org.robovm.llvm.PassManager) Global(org.robovm.compiler.llvm.Global) HfsCompressor(org.robovm.compiler.util.io.HfsCompressor) Target(org.robovm.llvm.Target) ObjectFile(org.robovm.llvm.ObjectFile) Context(org.robovm.llvm.Context) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) PackedStructureConstantBuilder(org.robovm.compiler.llvm.PackedStructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) TargetMachine(org.robovm.llvm.TargetMachine) ByteArrayInputStream(java.io.ByteArrayInputStream) Module(org.robovm.llvm.Module) ObjectFile(org.robovm.llvm.ObjectFile) File(java.io.File)

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