use of org.robovm.compiler.llvm.IntegerConstant in project robovm by robovm.
the class HashTableGeneratorTest method testNoRehashCollisions.
@Test
public void testNoRehashCollisions() {
HashTableGenerator<Integer, Constant> gen = new HashTableGenerator<Integer, Constant>(new IntegerHash(), 2);
gen.put(0, new IntegerConstant(0));
gen.put(4, new IntegerConstant(4));
gen.put(8, new IntegerConstant(8));
StructureConstant result = gen.generate();
assertEquals("{i32 3, i32 4, i32 0, i32 3, i32 3, i32 3, i32 3, i32 0, i32 4, i32 8}", result.toString());
}
use of org.robovm.compiler.llvm.IntegerConstant in project robovm by robovm.
the class HashTableGeneratorTest method testNoRehashNoCollisions.
@Test
public void testNoRehashNoCollisions() {
HashTableGenerator<Integer, Constant> gen = new HashTableGenerator<Integer, Constant>(new IntegerHash(), 2);
gen.put(0, new IntegerConstant(0));
gen.put(1, new IntegerConstant(1));
gen.put(2, new IntegerConstant(2));
StructureConstant result = gen.generate();
assertEquals("{i32 3, i32 4, i32 0, i32 1, i32 2, i32 3, i32 3, i32 0, i32 1, i32 2}", result.toString());
}
use of org.robovm.compiler.llvm.IntegerConstant in project robovm by robovm.
the class HashTableGeneratorTest method testRehashCollisions.
@Test
public void testRehashCollisions() {
HashTableGenerator<Integer, Constant> gen = new HashTableGenerator<Integer, Constant>(new IntegerHash(), 2);
gen.put(0, new IntegerConstant(0));
gen.put(4, new IntegerConstant(4));
gen.put(8, new IntegerConstant(8));
gen.put(3, new IntegerConstant(3));
StructureConstant result = gen.generate();
assertEquals("{i32 4, i32 8, i32 0, i32 2, i32 2, i32 2, i32 3, i32 4, i32 4, i32 4, i32 4, i32 0, i32 8, i32 3, i32 4}", result.toString());
}
use of org.robovm.compiler.llvm.IntegerConstant 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);
}
}
use of org.robovm.compiler.llvm.IntegerConstant in project robovm by robovm.
the class Functions method trycatchAllEnter.
public static void trycatchAllEnter(Function fn, Value env, BasicBlockRef onNoException, BasicBlockRef onException) {
Variable ctx = fn.newVariable(TRYCATCH_CONTEXT_PTR);
fn.add(new Alloca(ctx, TRYCATCH_CONTEXT));
Variable selPtr = fn.newVariable(new PointerType(I32));
fn.add(new Getelementptr(selPtr, ctx.ref(), 0, 1));
fn.add(new Store(new IntegerConstant(-1), selPtr.ref()));
Value result = call(fn, RVM_TRYCATCH_ENTER, env, ctx.ref());
fn.add(new Switch(result, onException, new IntegerConstant(0), onNoException));
}
Aggregations