use of org.robovm.compiler.llvm.StructureConstant in project robovm by robovm.
the class AttributesEncoder method encodeAttributes.
private Constant encodeAttributes(Host host) {
List<Value> attributes = new ArrayList<Value>();
for (Tag tag : host.getTags()) {
if (tag instanceof SourceFileTag) {
// Skip. We don't need this at this time.
Value sourceFile = getString(((SourceFileTag) tag).getSourceFile());
attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I8_PTR), new IntegerConstant(SOURCE_FILE), sourceFile));
} else if (tag instanceof EnclosingMethodTag) {
EnclosingMethodTag emt = (EnclosingMethodTag) tag;
Value eClass = getString(emt.getEnclosingClass());
Value eMethod = getStringOrNull(emt.getEnclosingMethod());
Value eDesc = getStringOrNull(emt.getEnclosingMethodSig());
attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I8_PTR, I8_PTR, I8_PTR), new IntegerConstant(ENCLOSING_METHOD), eClass, eMethod, eDesc));
} else if (tag instanceof SignatureTag) {
Value signature = getString(((SignatureTag) tag).getSignature());
attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I8_PTR), new IntegerConstant(SIGNATURE), signature));
} else if (tag instanceof InnerClassTag) {
InnerClassTag ict = (InnerClassTag) tag;
Value innerClass = getStringOrNull(ict.getInnerClass());
Value outerClass = getStringOrNull(ict.getOuterClass());
Value innerName = getStringOrNull(ict.getShortName());
Value innerClassAccess = new IntegerConstant(ict.getAccessFlags());
attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I8_PTR, I8_PTR, I8_PTR, I32), new IntegerConstant(INNER_CLASS), innerClass, outerClass, innerName, innerClassAccess));
} else if (tag instanceof AnnotationDefaultTag) {
StructureConstant value = encodeAnnotationElementValue(((AnnotationDefaultTag) tag).getDefaultVal());
attributes.add(new PackedStructureConstant(new PackedStructureType(I8, value.getType()), new IntegerConstant(ANNOTATION_DEFAULT), value));
} else if (tag instanceof VisibilityAnnotationTag) {
VisibilityAnnotationTag vat = (VisibilityAnnotationTag) tag;
if (vat.getVisibility() == AnnotationConstants.RUNTIME_VISIBLE) {
Type[] types = new Type[vat.getAnnotations().size()];
Value[] values = new Value[vat.getAnnotations().size()];
int i = 0;
for (AnnotationTag at : vat.getAnnotations()) {
values[i] = encodeAnnotationTagValue(at);
types[i] = values[i].getType();
i++;
}
attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I32, new PackedStructureType(types)), new IntegerConstant(RUNTIME_VISIBLE_ANNOTATIONS), new IntegerConstant(vat.getAnnotations().size()), new PackedStructureConstant(new PackedStructureType(types), values)));
}
} else if (tag instanceof VisibilityParameterAnnotationTag) {
VisibilityParameterAnnotationTag vpat = (VisibilityParameterAnnotationTag) tag;
List<Type> typesList = new ArrayList<Type>();
List<Value> valuesList = new ArrayList<Value>();
boolean hasRuntimeVisible = false;
for (VisibilityAnnotationTag vat : vpat.getVisibilityAnnotations()) {
typesList.add(I32);
if (vat.getVisibility() == AnnotationConstants.RUNTIME_VISIBLE && vat.getAnnotations() != null && !vat.getAnnotations().isEmpty()) {
hasRuntimeVisible = true;
valuesList.add(new IntegerConstant(vat.getAnnotations().size()));
for (AnnotationTag at : vat.getAnnotations()) {
valuesList.add(encodeAnnotationTagValue(at));
typesList.add(valuesList.get(valuesList.size() - 1).getType());
}
} else {
valuesList.add(new IntegerConstant(0));
}
}
if (hasRuntimeVisible) {
Type[] types = typesList.toArray(new Type[typesList.size()]);
Value[] values = valuesList.toArray(new Value[valuesList.size()]);
attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I32, new PackedStructureType(types)), new IntegerConstant(RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS), new IntegerConstant(vpat.getVisibilityAnnotations().size()), new PackedStructureConstant(new PackedStructureType(types), values)));
}
}
}
if (host instanceof SootMethod) {
List<SootClass> exceptions = ((SootMethod) host).getExceptions();
if (!exceptions.isEmpty()) {
Value[] values = new Value[exceptions.size()];
for (int i = 0; i < exceptions.size(); i++) {
String exName = getInternalName(exceptions.get(i));
values[i] = getString(exName);
addDependency(exName);
}
attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I32, new ArrayType(exceptions.size(), I8_PTR)), new IntegerConstant(EXCEPTIONS), new IntegerConstant(exceptions.size()), new ArrayConstant(new ArrayType(exceptions.size(), I8_PTR), values)));
}
}
if (attributes.isEmpty()) {
return null;
}
attributes.add(0, new IntegerConstant(attributes.size()));
Type[] types = new Type[attributes.size()];
for (int i = 0; i < types.length; i++) {
types[i] = attributes.get(i).getType();
}
return new PackedStructureConstant(new PackedStructureType(types), attributes.toArray(new Value[0]));
}
use of org.robovm.compiler.llvm.StructureConstant 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);
}
use of org.robovm.compiler.llvm.StructureConstant 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.StructureConstant 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.StructureConstant 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());
}
Aggregations